summary refs log tree commit diff
path: root/clients
diff options
context:
space:
mode:
Diffstat (limited to 'clients')
-rw-r--r--clients/cli/agent.c5
-rw-r--r--clients/cli/common.c1246
-rw-r--r--clients/cli/common.h35
-rw-r--r--clients/cli/connections.c3051
-rw-r--r--clients/cli/connections.h11
-rw-r--r--clients/cli/devices.c1031
-rw-r--r--clients/cli/devices.h34
-rw-r--r--clients/cli/general.c705
-rw-r--r--clients/cli/nmcli.c398
-rw-r--r--clients/cli/nmcli.h106
-rw-r--r--clients/cli/polkit-agent.c4
-rw-r--r--clients/cli/settings-docs.c520
-rw-r--r--clients/cli/settings-docs.xsl86
-rw-r--r--clients/cli/settings.c9628
-rw-r--r--clients/cli/settings.h48
-rw-r--r--clients/cli/utils.c1507
-rw-r--r--clients/cli/utils.h163
-rw-r--r--clients/common/nm-client-utils.c517
-rw-r--r--clients/common/nm-client-utils.h59
-rw-r--r--clients/common/nm-meta-setting-access.c638
-rw-r--r--clients/common/nm-meta-setting-access.h101
-rw-r--r--clients/common/nm-meta-setting-desc.c7284
-rw-r--r--clients/common/nm-meta-setting-desc.h444
-rw-r--r--clients/common/nm-secret-agent-simple.c73
-rw-r--r--clients/common/nm-vpn-helpers.c41
-rw-r--r--clients/common/settings-docs.c363
-rw-r--r--clients/common/settings-docs.c.in363
-rw-r--r--clients/common/settings-docs.xsl49
-rw-r--r--clients/common/tests/test-general.c162
-rw-r--r--clients/tui/newt/nmt-newt-entry-numeric.c96
-rw-r--r--clients/tui/newt/nmt-newt-entry-numeric.h9
-rw-r--r--clients/tui/nm-editor-bindings.c131
-rw-r--r--clients/tui/nmt-connect-connection-list.c8
-rw-r--r--clients/tui/nmt-ip-entry.c33
-rw-r--r--clients/tui/nmt-page-bond.c14
-rw-r--r--clients/tui/nmt-page-bridge.c6
-rw-r--r--clients/tui/nmt-page-ip4.c6
-rw-r--r--clients/tui/nmt-page-ip6.c6
-rw-r--r--clients/tui/nmt-page-vlan.c29
-rw-r--r--clients/tui/nmt-page-wifi.c30
-rw-r--r--clients/tui/nmt-route-entry.c2
-rw-r--r--clients/tui/nmt-route-table.c4
-rw-r--r--clients/tui/nmtui-connect.c74
43 files changed, 14674 insertions, 14446 deletions
diff --git a/clients/cli/agent.c b/clients/cli/agent.c
index 23582f49..656a5851 100644
--- a/clients/cli/agent.c
+++ b/clients/cli/agent.c
@@ -21,6 +21,8 @@
 
 #include "nm-default.h"
 
+#include "agent.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -31,7 +33,6 @@
 #include "utils.h"
 #include "nm-secret-agent-simple.h"
 #include "polkit-agent.h"
-#include "agent.h"
 
 static void
 usage (void)
@@ -125,7 +126,7 @@ secrets_requested (NMSecretAgentSimple *agent,
 	NmCli *nmc = (NmCli *) user_data;
 	gboolean success = FALSE;
 
-	if (nmc->print_output == NMC_PRINT_PRETTY)
+	if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 		nmc_terminal_erase_line ();
 
 	success = get_secrets_from_user (request_id, title, msg, secrets);
diff --git a/clients/cli/common.c b/clients/cli/common.c
index 27477166..0f5aea57 100644
--- a/clients/cli/common.c
+++ b/clients/cli/common.c
@@ -21,6 +21,8 @@
 
 #include "nm-default.h"
 
+#include "common.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -29,236 +31,338 @@
 #include <readline/readline.h>
 #include <readline/history.h>
 
+#include "nm-utils/nm-hash-utils.h"
 #include "nm-vpn-helpers.h"
-#include "common.h"
+#include "nm-client-utils.h"
+
 #include "utils.h"
 
-extern GMainLoop *loop;
-
-/* Available fields for IPv4 group */
-NmcOutputField nmc_fields_ip4_config[] = {
-	{"GROUP",      N_("GROUP")},    /* 0 */
-	{"ADDRESS",    N_("ADDRESS")},  /* 1 */
-	{"GATEWAY",    N_("GATEWAY")},  /* 2 */
-	{"ROUTE",      N_("ROUTE")},    /* 3 */
-	{"DNS",        N_("DNS")},      /* 4 */
-	{"DOMAIN",     N_("DOMAIN")},   /* 5 */
-	{"WINS",       N_("WINS")},     /* 6 */
-	{NULL, NULL}
-};
-#define NMC_FIELDS_IP4_CONFIG_ALL     "GROUP,ADDRESS,GATEWAY,ROUTE,DNS,DOMAIN,WINS"
+/*****************************************************************************/
 
-/* Available fields for DHCPv4 group */
-NmcOutputField nmc_fields_dhcp4_config[] = {
-	{"GROUP",      N_("GROUP")},   /* 0 */
-	{"OPTION",     N_("OPTION")},  /* 1 */
-	{NULL, NULL}
-};
-#define NMC_FIELDS_DHCP4_CONFIG_ALL     "GROUP,OPTION"
-
-/* Available fields for IPv6 group */
-NmcOutputField nmc_fields_ip6_config[] = {
-	{"GROUP",      N_("GROUP")},    /* 0 */
-	{"ADDRESS",    N_("ADDRESS")},  /* 1 */
-	{"GATEWAY",    N_("GATEWAY")},  /* 2 */
-	{"ROUTE",      N_("ROUTE")},    /* 3 */
-	{"DNS",        N_("DNS")},      /* 4 */
-	{"DOMAIN",     N_("DOMAIN")},   /* 5 */
-	{NULL, NULL}
-};
-#define NMC_FIELDS_IP6_CONFIG_ALL     "GROUP,ADDRESS,GATEWAY,ROUTE,DNS,DOMAIN"
+static char **
+_ip_config_get_routes (NMIPConfig *cfg)
+{
+	gs_unref_hashtable GHashTable *hash = NULL;
+	GPtrArray *ptr_array;
+	char **arr;
+	guint i;
 
-/* Available fields for DHCPv6 group */
-NmcOutputField nmc_fields_dhcp6_config[] = {
-	{"GROUP",      N_("GROUP")},   /* 0 */
-	{"OPTION",     N_("OPTION")},  /* 1 */
-	{NULL, NULL}
-};
-#define NMC_FIELDS_DHCP6_CONFIG_ALL     "GROUP,OPTION"
+	ptr_array = nm_ip_config_get_routes (cfg);
+	if (!ptr_array)
+		return NULL;
 
+	arr = g_new (char *, ptr_array->len + 1);
+	for (i = 0; i < ptr_array->len; i++) {
+		NMIPRoute *route = g_ptr_array_index (ptr_array, i);
+		gs_strfreev char **names = NULL;
+		gsize j;
+		GString *str;
+		guint64 metric;
+		gs_free char *attributes = NULL;
+
+		str = g_string_new (NULL);
+		g_string_append_printf (str,
+		                        "dst = %s/%u, nh = %s",
+		                        nm_ip_route_get_dest (route),
+		                        nm_ip_route_get_prefix (route),
+		                        nm_ip_route_get_next_hop (route)
+		                          ?: (nm_ip_route_get_family (route) == AF_INET ? "0.0.0.0" : "::"));
+
+		metric = nm_ip_route_get_metric (route);
+		if (metric != -1) {
+			g_string_append_printf (str,
+			                        ", mt = %u",
+			                        (guint) metric);
+		}
 
-gboolean
-print_ip4_config (NMIPConfig *cfg4,
-                  NmCli *nmc,
-                  const char *group_prefix,
-                  const char *one_field)
+		names = nm_ip_route_get_attribute_names (route);
+		if (names[0]) {
+			if (!hash)
+				hash = g_hash_table_new (nm_str_hash, g_str_equal);
+			else
+				g_hash_table_remove_all (hash);
+
+			for (j = 0; names[j]; j++)
+				g_hash_table_insert (hash, names[j], nm_ip_route_get_attribute (route, names[j]));
+
+			attributes = nm_utils_format_variant_attributes (hash, ',', '=');
+			if (attributes) {
+				g_string_append (str, ", ");
+				g_string_append (str, attributes);
+			}
+		}
+
+		arr[i] = g_string_free (str, FALSE);
+	}
+
+	nm_assert (i == ptr_array->len);
+	arr[i] = NULL;
+
+	return arr;
+}
+
+static gconstpointer
+_metagen_ip4_config_get_fcn (const NMMetaEnvironment *environment,
+                             gpointer environment_user_data,
+                             const NmcMetaGenericInfo *info,
+                             gpointer target,
+                             NMMetaAccessorGetType get_type,
+                             NMMetaAccessorGetFlags get_flags,
+                             NMMetaAccessorGetOutFlags *out_flags,
+                             gpointer *out_to_free)
 {
+	NMIPConfig *cfg4 = target;
 	GPtrArray *ptr_array;
-	char **addr_arr = NULL;
-	char **route_arr = NULL;
-	char **dns_arr = NULL;
-	char **domain_arr = NULL;
-	char **wins_arr = NULL;
-	int i = 0;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	char **arr;
+	const char *const*arrc;
+	guint i = 0;
 
-	if (cfg4 == NULL)
-		return FALSE;
+	nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM);
 
-	tmpl = nmc_fields_ip4_config;
-	tmpl_len = sizeof (nmc_fields_ip4_config);
-	nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_IP4_CONFIG_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	/* addresses */
-	ptr_array = nm_ip_config_get_addresses (cfg4);
-	if (ptr_array) {
-		addr_arr = g_new (char *, ptr_array->len + 1);
-		for (i = 0; i < ptr_array->len; i++) {
-			NMIPAddress *addr = (NMIPAddress *) g_ptr_array_index (ptr_array, i);
-
-			addr_arr[i] = g_strdup_printf ("%s/%u",
-			                               nm_ip_address_get_address (addr),
-			                               nm_ip_address_get_prefix (addr));
-		}
-		addr_arr[i] = NULL;
+	NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL);
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ADDRESS:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		ptr_array = nm_ip_config_get_addresses (cfg4);
+		if (ptr_array) {
+			arr = g_new (char *, ptr_array->len + 1);
+			for (i = 0; i < ptr_array->len; i++) {
+				NMIPAddress *addr = g_ptr_array_index (ptr_array, i);
+
+				arr[i] = g_strdup_printf ("%s/%u",
+				                          nm_ip_address_get_address (addr),
+				                          nm_ip_address_get_prefix (addr));
+			}
+			arr[i] = NULL;
+		} else
+			arr = NULL;
+		goto arr_out;
+	case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_GATEWAY:
+		return nm_ip_config_get_gateway (cfg4);
+	case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ROUTE:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		arr = _ip_config_get_routes (cfg4);
+		goto arr_out;
+	case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DNS:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		arrc = nm_ip_config_get_nameservers (cfg4);
+		goto arrc_out;
+	case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DOMAIN:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		arrc = nm_ip_config_get_domains (cfg4);
+		goto arrc_out;
+	case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_WINS:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		arrc = nm_ip_config_get_wins_servers (cfg4);
+		goto arrc_out;
+	default:
+		break;
 	}
 
-	/* routes */
-	ptr_array = nm_ip_config_get_routes (cfg4);
-	if (ptr_array) {
-		route_arr = g_new (char *, ptr_array->len + 1);
-		for (i = 0; i < ptr_array->len; i++) {
-			NMIPRoute *route = (NMIPRoute *) g_ptr_array_index (ptr_array, i);
-			const char *next_hop;
-
-			next_hop = nm_ip_route_get_next_hop (route);
-			if (!next_hop)
-				next_hop = "0.0.0.0";
-
-			route_arr[i] = g_strdup_printf ("dst = %s/%u, nh = %s%c mt = %u",
-			                                nm_ip_route_get_dest (route),
-			                                nm_ip_route_get_prefix (route),
-			                                next_hop,
-			                                nm_ip_route_get_metric (route) == -1 ? '\0' : ',',
-			                                (guint32) nm_ip_route_get_metric (route));
-		}
-		route_arr[i] = NULL;
+	g_return_val_if_reached (NULL);
+
+arrc_out:
+	*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
+	return arrc;
+
+arr_out:
+	*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
+	*out_to_free = arr;
+	return arr;
+}
+
+static gconstpointer
+_metagen_ip6_config_get_fcn (const NMMetaEnvironment *environment,
+                             gpointer environment_user_data,
+                             const NmcMetaGenericInfo *info,
+                             gpointer target,
+                             NMMetaAccessorGetType get_type,
+                             NMMetaAccessorGetFlags get_flags,
+                             NMMetaAccessorGetOutFlags *out_flags,
+                             gpointer *out_to_free)
+{
+	NMIPConfig *cfg6 = target;
+	GPtrArray *ptr_array;
+	char **arr;
+	const char *const*arrc;
+	guint i = 0;
+
+	nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM);
+
+	NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL);
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ADDRESS:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		ptr_array = nm_ip_config_get_addresses (cfg6);
+		if (ptr_array) {
+			arr = g_new (char *, ptr_array->len + 1);
+			for (i = 0; i < ptr_array->len; i++) {
+				NMIPAddress *addr = g_ptr_array_index (ptr_array, i);
+
+				arr[i] = g_strdup_printf ("%s/%u",
+				                          nm_ip_address_get_address (addr),
+				                          nm_ip_address_get_prefix (addr));
+			}
+			arr[i] = NULL;
+		} else
+			arr = NULL;
+		goto arr_out;
+	case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_GATEWAY:
+		return nm_ip_config_get_gateway (cfg6);
+	case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ROUTE:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		arr = _ip_config_get_routes (cfg6);
+		goto arr_out;
+	case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DNS:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		arrc = nm_ip_config_get_nameservers (cfg6);
+		goto arrc_out;
+	case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		arrc = nm_ip_config_get_domains (cfg6);
+		goto arrc_out;
+	default:
+		break;
 	}
 
-	/* DNS */
-	dns_arr = g_strdupv ((char **) nm_ip_config_get_nameservers (cfg4));
+	g_return_val_if_reached (NULL);
+
+arrc_out:
+	*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
+	return arrc;
+
+arr_out:
+	*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
+	*out_to_free = arr;
+	return arr;
+}
+
+const NmcMetaGenericInfo *const metagen_ip4_config[_NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM + 1] = {
+#define _METAGEN_IP4_CONFIG(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_ip4_config_get_fcn)
+	_METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ADDRESS, "ADDRESS"),
+	_METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_GATEWAY, "GATEWAY"),
+	_METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ROUTE,   "ROUTE"),
+	_METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DNS,     "DNS"),
+	_METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DOMAIN,  "DOMAIN"),
+	_METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_WINS,    "WINS"),
+};
+
+static const NmcMetaGenericInfo *const metagen_ip4_config_group[] = {
+	NMC_META_GENERIC_WITH_NESTED ("IP4", metagen_ip4_config, .name_header = N_("GROUP")),
+	NULL,
+};
 
-	/* domains */
-	domain_arr = g_strdupv ((char **) nm_ip_config_get_domains (cfg4));
+const NmcMetaGenericInfo *const metagen_ip6_config[_NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM + 1] = {
+#define _METAGEN_IP6_CONFIG(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_ip6_config_get_fcn)
+	_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ADDRESS, "ADDRESS"),
+	_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_GATEWAY, "GATEWAY"),
+	_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ROUTE,   "ROUTE"),
+	_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DNS,     "DNS"),
+	_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN,  "DOMAIN"),
+};
 
-	/* WINS */
-	wins_arr = g_strdupv ((char **) nm_ip_config_get_wins_servers (cfg4));
+static const NmcMetaGenericInfo *const metagen_ip6_config_group[] = {
+	NMC_META_GENERIC_WITH_NESTED ("IP6", metagen_ip6_config, .name_header = N_("GROUP")),
+	NULL,
+};
 
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_strc (arr, 0, group_prefix);
-	set_val_arr  (arr, 1, addr_arr);
-	set_val_strc (arr, 2, nm_ip_config_get_gateway (cfg4));
-	set_val_arr  (arr, 3, route_arr);
-	set_val_arr  (arr, 4, dns_arr);
-	set_val_arr  (arr, 5, domain_arr);
-	set_val_arr  (arr, 6, wins_arr);
-	g_ptr_array_add (nmc->output_data, arr);
+/*****************************************************************************/
 
-	print_data (nmc); /* Print all data */
+const NmcMetaGenericInfo *const nmc_fields_dhcp4_config[] = {
+	NMC_META_GENERIC ("GROUP"),    /* 0 */
+	NMC_META_GENERIC ("OPTION"),   /* 1 */
+	NULL,
+};
+
+const NmcMetaGenericInfo *const nmc_fields_ip6_config[] = {
+	NMC_META_GENERIC ("GROUP"),     /* 0 */
+	NMC_META_GENERIC ("ADDRESS"),   /* 1 */
+	NMC_META_GENERIC ("GATEWAY"),   /* 2 */
+	NMC_META_GENERIC ("ROUTE"),     /* 3 */
+	NMC_META_GENERIC ("DNS"),       /* 4 */
+	NMC_META_GENERIC ("DOMAIN"),    /* 5 */
+	NULL,
+};
 
-	/* Remove any previous data */
-	nmc_empty_output_fields (nmc);
+const NmcMetaGenericInfo *const nmc_fields_dhcp6_config[] = {
+	NMC_META_GENERIC ("GROUP"),    /* 0 */
+	NMC_META_GENERIC ("OPTION"),   /* 1 */
+	NULL,
+};
+
+gboolean
+print_ip4_config (NMIPConfig *cfg4,
+                  const NmcConfig *nmc_config,
+                  const char *one_field)
+{
+	gs_free_error GError *error = NULL;
+	gs_free char *field_str = NULL;
+
+	if (cfg4 == NULL)
+		return FALSE;
 
+	if (one_field)
+		field_str = g_strdup_printf ("IP4.%s", one_field);
+
+	if (!nmc_print (nmc_config,
+	                (gpointer[]) { cfg4, NULL },
+	                NULL,
+	                (const NMMetaAbstractInfo *const*) metagen_ip4_config_group,
+	                field_str,
+	                &error)) {
+		return FALSE;
+	}
 	return TRUE;
 }
 
 gboolean
 print_ip6_config (NMIPConfig *cfg6,
-                  NmCli *nmc,
+                  const NmcConfig *nmc_config,
                   const char *group_prefix,
                   const char *one_field)
 {
-	GPtrArray *ptr_array;
-	char **addr_arr = NULL;
-	char **route_arr = NULL;
-	char **dns_arr = NULL;
-	char **domain_arr = NULL;
-	int i = 0;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	gs_free_error GError *error = NULL;
+	gs_free char *field_str = NULL;
 
 	if (cfg6 == NULL)
 		return FALSE;
 
-	tmpl = nmc_fields_ip6_config;
-	tmpl_len = sizeof (nmc_fields_ip6_config);
-	nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_IP6_CONFIG_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	/* addresses */
-	ptr_array = nm_ip_config_get_addresses (cfg6);
-	if (ptr_array) {
-		addr_arr = g_new (char *, ptr_array->len + 1);
-		for (i = 0; i < ptr_array->len; i++) {
-			NMIPAddress *addr = (NMIPAddress *) g_ptr_array_index (ptr_array, i);
-
-			addr_arr[i] = g_strdup_printf ("%s/%u",
-			                               nm_ip_address_get_address (addr),
-			                               nm_ip_address_get_prefix (addr));
-		}
-		addr_arr[i] = NULL;
-	}
+	if (one_field)
+		field_str = g_strdup_printf ("IP6.%s", one_field);
 
-	/* routes */
-	ptr_array = nm_ip_config_get_routes (cfg6);
-	if (ptr_array) {
-		route_arr = g_new (char *, ptr_array->len + 1);
-		for (i = 0; i < ptr_array->len; i++) {
-			NMIPRoute *route = (NMIPRoute *) g_ptr_array_index (ptr_array, i);
-			const char *next_hop;
-
-			next_hop = nm_ip_route_get_next_hop (route);
-			if (!next_hop)
-				next_hop = "::";
-
-			route_arr[i] = g_strdup_printf ("dst = %s/%u, nh = %s%c mt = %u",
-			                                nm_ip_route_get_dest (route),
-			                                nm_ip_route_get_prefix (route),
-			                                next_hop,
-			                                nm_ip_route_get_metric (route) == -1 ? '\0' : ',',
-			                                (guint32) nm_ip_route_get_metric (route));
-		}
-		route_arr[i] = NULL;
+	if (!nmc_print (nmc_config,
+	                (gpointer[]) { cfg6, NULL },
+	                NULL,
+	                (const NMMetaAbstractInfo *const*) metagen_ip6_config_group,
+	                field_str,
+	                &error)) {
+		return FALSE;
 	}
-
-	/* DNS */
-	dns_arr = g_strdupv ((char **) nm_ip_config_get_nameservers (cfg6));
-
-	/* domains */
-	domain_arr = g_strdupv ((char **) nm_ip_config_get_domains (cfg6));
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_strc (arr, 0, group_prefix);
-	set_val_arr  (arr, 1, addr_arr);
-	set_val_strc (arr, 2, nm_ip_config_get_gateway (cfg6));
-	set_val_arr  (arr, 3, route_arr);
-	set_val_arr  (arr, 4, dns_arr);
-	set_val_arr  (arr, 5, domain_arr);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc); /* Print all data */
-
-	/* Remove any previous data */
-	nmc_empty_output_fields (nmc);
-
 	return TRUE;
 }
 
 gboolean
 print_dhcp4_config (NMDhcpConfig *dhcp4,
-                    NmCli *nmc,
+                    const NmcConfig *nmc_config,
                     const char *group_prefix,
                     const char *one_field)
 {
 	GHashTable *table;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	const NMMetaAbstractInfo *const*tmpl;
+	NmcOutputField *arr;
 
 	if (dhcp4 == NULL)
 		return FALSE;
@@ -269,13 +373,13 @@ print_dhcp4_config (NMDhcpConfig *dhcp4,
 		gpointer key, value;
 		char **options_arr = NULL;
 		int i = 0;
+		NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
-		tmpl = nmc_fields_dhcp4_config;
-		tmpl_len = sizeof (nmc_fields_dhcp4_config);
-		nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DHCP4_CONFIG_ALL,
-		                                                 tmpl, FALSE, NULL, NULL);
-		arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-		g_ptr_array_add (nmc->output_data, arr);
+		tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dhcp4_config;
+		out_indices = parse_output_fields (one_field,
+		                                   tmpl, FALSE, NULL, NULL);
+		arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+		g_ptr_array_add (out.output_data, arr);
 
 		options_arr = g_new (char *, g_hash_table_size (table) + 1);
 		g_hash_table_iter_init (&table_iter, table);
@@ -283,15 +387,13 @@ print_dhcp4_config (NMDhcpConfig *dhcp4,
 			options_arr[i++] = g_strdup_printf ("%s = %s", (char *) key, (char *) value);
 		options_arr[i] = NULL;
 
-		arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
+		arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
 		set_val_strc (arr, 0, group_prefix);
 		set_val_arr  (arr, 1, options_arr);
-		g_ptr_array_add (nmc->output_data, arr);
+		g_ptr_array_add (out.output_data, arr);
 
-		print_data (nmc); /* Print all data */
-
-		/* Remove any previous data */
-		nmc_empty_output_fields (nmc);
+		print_data_prepare_width (out.output_data);
+		print_data (nmc_config, out_indices, NULL, 0, &out);
 
 		return TRUE;
 	}
@@ -300,13 +402,13 @@ print_dhcp4_config (NMDhcpConfig *dhcp4,
 
 gboolean
 print_dhcp6_config (NMDhcpConfig *dhcp6,
-                    NmCli *nmc,
+                    const NmcConfig *nmc_config,
                     const char *group_prefix,
                     const char *one_field)
 {
 	GHashTable *table;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	const NMMetaAbstractInfo *const*tmpl;
+	NmcOutputField *arr;
 
 	if (dhcp6 == NULL)
 		return FALSE;
@@ -317,13 +419,13 @@ print_dhcp6_config (NMDhcpConfig *dhcp6,
 		gpointer key, value;
 		char **options_arr = NULL;
 		int i = 0;
+		NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
-		tmpl = nmc_fields_dhcp6_config;
-		tmpl_len = sizeof (nmc_fields_dhcp6_config);
-		nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DHCP6_CONFIG_ALL,
-		                                                 tmpl, FALSE, NULL, NULL);
-		arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-		g_ptr_array_add (nmc->output_data, arr);
+		tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dhcp6_config;
+		out_indices = parse_output_fields (one_field,
+		                                   tmpl, FALSE, NULL, NULL);
+		arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+		g_ptr_array_add (out.output_data, arr);
 
 		options_arr = g_new (char *, g_hash_table_size (table) + 1);
 		g_hash_table_iter_init (&table_iter, table);
@@ -331,15 +433,13 @@ print_dhcp6_config (NMDhcpConfig *dhcp6,
 			options_arr[i++] = g_strdup_printf ("%s = %s", (char *) key, (char *) value);
 		options_arr[i] = NULL;
 
-		arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
+		arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
 		set_val_strc (arr, 0, group_prefix);
 		set_val_arr  (arr, 1, options_arr);
-		g_ptr_array_add (nmc->output_data, arr);
-
-		print_data (nmc); /* Print all data */
+		g_ptr_array_add (out.output_data, arr);
 
-		/* Remove any previous data */
-		nmc_empty_output_fields (nmc);
+		print_data_prepare_width (out.output_data);
+		print_data (nmc_config, out_indices, NULL, 0, &out);
 
 		return TRUE;
 	}
@@ -347,677 +447,6 @@ print_dhcp6_config (NMDhcpConfig *dhcp6,
 }
 
 /*
- * Parse IP address from string to NMIPAddress stucture.
- * ip_str is the IP address in the form address/prefix
- */
-NMIPAddress *
-nmc_parse_and_build_address (int family, const char *ip_str, GError **error)
-{
-	int max_prefix = (family == AF_INET) ? 32 : 128;
-	NMIPAddress *addr = NULL;
-	const char *ip;
-	char *tmp;
-	char *plen;
-	long int prefix;
-	GError *local = NULL;
-
-	g_return_val_if_fail (ip_str != NULL, NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	tmp = g_strdup (ip_str);
-	plen = strchr (tmp, '/');  /* prefix delimiter */
-	if (plen)
-		*plen++ = '\0';
-
-	ip = tmp;
-
-	prefix = max_prefix;
-	if (plen) {
-		if (!nmc_string_to_int (plen, TRUE, 1, max_prefix, &prefix)) {
-			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("invalid prefix '%s'; <1-%d> allowed"), plen, max_prefix);
-			goto finish;
-		}
-	}
-
-	addr = nm_ip_address_new (family, ip, (guint32) prefix, &local);
-	if (!addr) {
-		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-		             _("invalid IP address: %s"), local->message);
-		g_clear_error (&local);
-	}
-
-finish:
-	g_free (tmp);
-	return addr;
-}
-
-/*
- * nmc_parse_and_build_route:
- * @family: AF_INET or AF_INET6
- * @str: route string to be parsed
- * @error: location to store GError
- *
- * Parse route from string and return an #NMIPRoute
- *
- * Returns: a new #NMIPRoute or %NULL on error
- */
-NMIPRoute *
-nmc_parse_and_build_route (int family,
-                           const char *str,
-                           GError **error)
-{
-	int max_prefix = (family == AF_INET) ? 32 : 128;
-	char *plen = NULL;
-	const char *next_hop = NULL;
-	const char *canon_dest;
-	long int prefix = max_prefix;
-	unsigned long int tmp_ulong;
-	NMIPRoute *route = NULL;
-	gboolean success = FALSE;
-	GError *local = NULL;
-	gint64 metric = -1;
-	guint i, len;
-	gs_strfreev char **routev = NULL;
-	gs_free char *value = NULL;
-	gs_free char *dest = NULL;
-	gs_unref_hashtable GHashTable *attrs = NULL;
-	GHashTable *tmp_attrs;
-	const char *syntax = _("The valid syntax is: 'ip[/prefix] [next-hop] [metric] [attribute=val]... [,ip[/prefix] ...]'");
-
-	g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE);
-	g_return_val_if_fail (str, FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	value = g_strdup (str);
-	routev = nmc_strsplit_set (g_strstrip (value), " \t", 0);
-	len = g_strv_length (routev);
-	if (len < 1) {
-		g_set_error (error, 1, 0, "%s", syntax);
-		g_prefix_error (error, "'%s' is not valid. ", str);
-		goto finish;
-	}
-
-	dest = g_strdup (routev[0]);
-	plen = strchr (dest, '/');  /* prefix delimiter */
-	if (plen)
-		*plen++ = '\0';
-
-	if (plen) {
-		if (!nmc_string_to_int (plen, TRUE, 1, max_prefix, &prefix)) {
-			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("invalid prefix '%s'; <1-%d> allowed"),
-			             plen, max_prefix);
-			goto finish;
-		}
-	}
-
-	for (i = 1; i < len; i++) {
-		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]);
-				goto finish;
-			}
-			next_hop = routev[i];
-		} else if (nmc_string_to_uint (routev[i], TRUE, 0, G_MAXUINT32, &tmp_ulong)) {
-			if (attrs) {
-				g_set_error (error, 1, 0, _("the metric ('%s') must be before attributes"), routev[i]);
-				goto finish;
-			}
-			metric = tmp_ulong;
-		} 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]);
-				goto finish;
-			}
-
-			if (!attrs)
-				attrs = g_hash_table_new (g_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);
-					goto finish;
-				}
-				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", syntax);
-			goto finish;
-		}
-	}
-
-	route = nm_ip_route_new (family, dest, prefix, next_hop, metric, &local);
-	if (!route) {
-		g_set_error (error, 1, 0, "%s", syntax);
-		g_prefix_error (error, _("invalid route: %s. "), local->message);
-		g_clear_error (&local);
-		goto finish;
-	}
-
-	/* 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, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-		                     _("default route cannot be added (NetworkManager handles it by itself)"));
-		g_clear_pointer (&route, nm_ip_route_unref);
-		goto finish;
-	}
-
-	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);
-	}
-
-	success = TRUE;
-
-finish:
-	return route;
-}
-
-const char *
-nmc_device_state_to_string (NMDeviceState state)
-{
-	switch (state) {
-	case NM_DEVICE_STATE_UNMANAGED:
-		return _("unmanaged");
-	case NM_DEVICE_STATE_UNAVAILABLE:
-		return _("unavailable");
-	case NM_DEVICE_STATE_DISCONNECTED:
-		return _("disconnected");
-	case NM_DEVICE_STATE_PREPARE:
-		return _("connecting (prepare)");
-	case NM_DEVICE_STATE_CONFIG:
-		return _("connecting (configuring)");
-	case NM_DEVICE_STATE_NEED_AUTH:
-		return _("connecting (need authentication)");
-	case NM_DEVICE_STATE_IP_CONFIG:
-		return _("connecting (getting IP configuration)");
-	case NM_DEVICE_STATE_IP_CHECK:
-		return _("connecting (checking IP connectivity)");
-	case NM_DEVICE_STATE_SECONDARIES:
-		return _("connecting (starting secondary connections)");
-	case NM_DEVICE_STATE_ACTIVATED:
-		return _("connected");
-	case NM_DEVICE_STATE_DEACTIVATING:
-		return _("deactivating");
-	case NM_DEVICE_STATE_FAILED:
-		return _("connection failed");
-	default:
-		return _("unknown");
-	}
-}
-
-const char *
-nmc_device_metered_to_string (NMMetered value)
-{
-	switch (value) {
-	case NM_METERED_YES:
-		return _("yes");
-	case NM_METERED_NO:
-		return _("no");
-	case NM_METERED_GUESS_YES:
-		return _("yes (guessed)");
-	case NM_METERED_GUESS_NO:
-		return _("no (guessed)");
-	default:
-		return _("unknown");
-	}
-}
-
-const char *
-nmc_device_reason_to_string (NMDeviceStateReason reason)
-{
-	switch (reason) {
-	case NM_DEVICE_STATE_REASON_NONE:
-		return _("No reason given");
-
-	case NM_DEVICE_STATE_REASON_UNKNOWN:
-		return _("Unknown error");
-
-	case NM_DEVICE_STATE_REASON_NOW_MANAGED:
-		return _("Device is now managed");
-
-	case NM_DEVICE_STATE_REASON_NOW_UNMANAGED:
-		return _("Device is now unmanaged");
-
-	case NM_DEVICE_STATE_REASON_CONFIG_FAILED:
-		return _("The device could not be readied for configuration");
-
-	case NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE:
-		return _("IP configuration could not be reserved (no available address, timeout, etc.)");
-
-	case NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED:
-		return _("The IP configuration is no longer valid");
-
-	case NM_DEVICE_STATE_REASON_NO_SECRETS:
-		return _("Secrets were required, but not provided");
-
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT:
-		return _("802.1X supplicant disconnected");
-
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED:
-		return _("802.1X supplicant configuration failed");
-
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED:
-		return _("802.1X supplicant failed");
-
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT:
-		return _("802.1X supplicant took too long to authenticate");
-
-	case NM_DEVICE_STATE_REASON_PPP_START_FAILED:
-		return _("PPP service failed to start");
-
-	case NM_DEVICE_STATE_REASON_PPP_DISCONNECT:
-		return _("PPP service disconnected");
-
-	case NM_DEVICE_STATE_REASON_PPP_FAILED:
-		return _("PPP failed");
-
-	case NM_DEVICE_STATE_REASON_DHCP_START_FAILED:
-		return _("DHCP client failed to start");
-
-	case NM_DEVICE_STATE_REASON_DHCP_ERROR:
-		return _("DHCP client error");
-
-	case NM_DEVICE_STATE_REASON_DHCP_FAILED:
-		return _("DHCP client failed");
-
-	case NM_DEVICE_STATE_REASON_SHARED_START_FAILED:
-		return _("Shared connection service failed to start");
-
-	case NM_DEVICE_STATE_REASON_SHARED_FAILED:
-		return _("Shared connection service failed");
-
-	case NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED:
-		return _("AutoIP service failed to start");
-
-	case NM_DEVICE_STATE_REASON_AUTOIP_ERROR:
-		return _("AutoIP service error");
-
-	case NM_DEVICE_STATE_REASON_AUTOIP_FAILED:
-		return _("AutoIP service failed");
-
-	case NM_DEVICE_STATE_REASON_MODEM_BUSY:
-		return _("The line is busy");
-
-	case NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE:
-		return _("No dial tone");
-
-	case NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER:
-		return _("No carrier could be established");
-
-	case NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT:
-		return _("The dialing request timed out");
-
-	case NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED:
-		return _("The dialing attempt failed");
-
-	case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED:
-		return _("Modem initialization failed");
-
-	case NM_DEVICE_STATE_REASON_GSM_APN_FAILED:
-		return _("Failed to select the specified APN");
-
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING:
-		return _("Not searching for networks");
-
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED:
-		return _("Network registration denied");
-
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT:
-		return _("Network registration timed out");
-
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED:
-		return _("Failed to register with the requested network");
-
-	case NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED:
-		return _("PIN check failed");
-
-	case NM_DEVICE_STATE_REASON_FIRMWARE_MISSING:
-		return _("Necessary firmware for the device may be missing");
-
-	case NM_DEVICE_STATE_REASON_REMOVED:
-		return _("The device was removed");
-
-	case NM_DEVICE_STATE_REASON_SLEEPING:
-		return _("NetworkManager went to sleep");
-
-	case NM_DEVICE_STATE_REASON_CONNECTION_REMOVED:
-		return _("The device's active connection disappeared");
-
-	case NM_DEVICE_STATE_REASON_USER_REQUESTED:
-		return _("Device disconnected by user or client");
-
-	case NM_DEVICE_STATE_REASON_CARRIER:
-		return _("Carrier/link changed");
-
-	case NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED:
-		return _("The device's existing connection was assumed");
-
-	case NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE:
-		return _("The supplicant is now available");
-
-	case NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND:
-		return _("The modem could not be found");
-
-	case NM_DEVICE_STATE_REASON_BT_FAILED:
-		return _("The Bluetooth connection failed or timed out");
-
-	case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED:
-		return _("GSM Modem's SIM card not inserted");
-
-	case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED:
-		return _("GSM Modem's SIM PIN required");
-
-	case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED:
-		return _("GSM Modem's SIM PUK required");
-
-	case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG:
-		return _("GSM Modem's SIM wrong");
-
-	case NM_DEVICE_STATE_REASON_INFINIBAND_MODE:
-		return _("InfiniBand device does not support connected mode");
-
-        case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED:
-		return _("A dependency of the connection failed");
-
-	case NM_DEVICE_STATE_REASON_BR2684_FAILED:
-		return _("A problem with the RFC 2684 Ethernet over ADSL bridge");
-
-	case NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE:
-		return _("ModemManager is unavailable");
-
-	case NM_DEVICE_STATE_REASON_SSID_NOT_FOUND:
-		return _("The Wi-Fi network could not be found");
-
-	case NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED:
-		return _("A secondary connection of the base connection failed");
-
-	case NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED:
-		return _("DCB or FCoE setup failed");
-
-	case NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED:
-		return _("teamd control failed");
-
-	case NM_DEVICE_STATE_REASON_MODEM_FAILED:
-		return _("Modem failed or no longer available");
-
-	case NM_DEVICE_STATE_REASON_MODEM_AVAILABLE:
-		return _("Modem now ready and available");
-
-	case NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT:
-		return _("SIM PIN was incorrect");
-
-	case NM_DEVICE_STATE_REASON_NEW_ACTIVATION:
-		return _("New connection activation was enqueued");
-
-	case NM_DEVICE_STATE_REASON_PARENT_CHANGED:
-		return _("The device's parent changed");
-
-	case NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED:
-		return _("The device parent's management changed");
-
-	default:
-		/* TRANSLATORS: Unknown reason for a device state change (NMDeviceStateReason) */
-		return _("Unknown");
-	}
-}
-
-
-/* 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.
- */
-char **
-nmc_vlan_parse_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;
-}
-
-const char *
-nmc_bond_validate_mode (const char *mode, GError **error)
-{
-	unsigned long mode_int;
-	static const char *valid_modes[] = { "balance-rr",
-	                                     "active-backup",
-	                                     "balance-xor",
-	                                     "broadcast",
-	                                     "802.3ad",
-	                                     "balance-tlb",
-	                                     "balance-alb",
-	                                     NULL };
-	if (nmc_string_to_uint (mode, TRUE, 0, 6, &mode_int)) {
-		/* Translate bonding mode numbers to mode names:
-		 * https://www.kernel.org/doc/Documentation/networking/bonding.txt
-		 */
-		return valid_modes[mode_int];
-	} else
-		return nmc_string_is_valid (mode, valid_modes, error);
-}
-
-/*
- * 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
- */
-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, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-				             _("cannot read team config from file '%s'"),
-				             config);
-				return FALSE;
-			}
-		} else {
-			if (c_len != strlen (contents)) {
-				g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-				             _("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, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("'%s' does not contain a valid team configuration"), filename);
-		} else {
-			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("team configuration must be a JSON object"));
-		}
-		return FALSE;
-	}
-
-	*out_config = (config == config_clone)
-	              ? g_steal_pointer (&config_clone)
-	              : g_strdup (config);
-	return TRUE;
-}
-
-/*
- * 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
- */
-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, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-				             _("cannot read pac-script from file '%s'"),
-				             script);
-				return FALSE;
-			}
-		} else {
-			if (c_len != strlen (contents)) {
-				g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-				             _("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, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("'%s' does not contain a valid PAC Script"), filename);
-		} else {
-			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("Not a valid PAC Script"));
-		}
-		return FALSE;
-	}
-
-	*out_script = (script == script_clone)
-	              ? g_steal_pointer (&script_clone)
-	              : g_strdup (script);
-	return TRUE;
-}
-
-/*
  * nmc_find_connection:
  * @connections: array of NMConnections to search in
  * @filter_type: "id", "uuid", "path" or %NULL
@@ -1261,7 +690,7 @@ nmc_secrets_requested (NMSecretAgentSimple *agent,
 	gboolean success = FALSE;
 	const GPtrArray *connections;
 
-	if (nmc->print_output == NMC_PRINT_PRETTY)
+	if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 		nmc_terminal_erase_line ();
 
 	/* Find the connection for the request */
@@ -1275,8 +704,8 @@ nmc_secrets_requested (NMSecretAgentSimple *agent,
 		g_free (path);
 	}
 
-	success = get_secrets_from_user (request_id, title, msg, connection, nmc->in_editor || nmc->ask,
-	                                 nmc->show_secrets, nmc->pwds_hash, secrets);
+	success = get_secrets_from_user (request_id, title, msg, connection, nmc->nmc_config.in_editor || nmc->ask,
+	                                 nmc->nmc_config.show_secrets, nmc->pwds_hash, secrets);
 	if (success)
 		nm_secret_agent_simple_response (agent, request_id, secrets);
 	else {
@@ -1396,7 +825,7 @@ read_again:
 	if (nmc_seen_sigint ()) {
 		/* Ctrl-C */
 		nmc_clear_sigint ();
-		if (   nm_cli.in_editor
+		if (   nm_cli.nmc_config.in_editor
 		    || (rl_string  && *rl_string)) {
 			/* In editor, or the line is not empty */
 			/* Call readline again to get new prompt (repeat) */
@@ -1503,7 +932,7 @@ nmc_readline_echo (gboolean echo_on, const char *prompt_fmt, ...)
  * See e.g. http://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC49
  */
 char *
-nmc_rl_gen_func_basic (const char *text, int state, const char **words)
+nmc_rl_gen_func_basic (const char *text, int state, const char *const*words)
 {
 	static int list_idx, len;
 	const char *name;
@@ -1523,6 +952,43 @@ nmc_rl_gen_func_basic (const char *text, int state, const char **words)
 	return NULL;
 }
 
+static struct {
+	bool initialized;
+	guint idx;
+	char **values;
+} _rl_compentry_func_wrap = { 0 };
+
+static char *
+_rl_compentry_func_wrap_fcn (const char *text, int state)
+{
+	g_return_val_if_fail (_rl_compentry_func_wrap.initialized, NULL);
+
+	while (   _rl_compentry_func_wrap.values
+	       && _rl_compentry_func_wrap.values[_rl_compentry_func_wrap.idx]
+	       && !g_str_has_prefix (_rl_compentry_func_wrap.values[_rl_compentry_func_wrap.idx], text))
+		_rl_compentry_func_wrap.idx++;
+
+	if (   !_rl_compentry_func_wrap.values
+	    || !_rl_compentry_func_wrap.values[_rl_compentry_func_wrap.idx]) {
+		g_strfreev (_rl_compentry_func_wrap.values);
+		_rl_compentry_func_wrap.values = NULL;
+		_rl_compentry_func_wrap.initialized = FALSE;
+		return NULL;
+	}
+
+	return g_strdup (_rl_compentry_func_wrap.values[_rl_compentry_func_wrap.idx++]);
+}
+
+NmcCompEntryFunc
+nmc_rl_compentry_func_wrap (const char *const*values)
+{
+	g_strfreev (_rl_compentry_func_wrap.values);
+	_rl_compentry_func_wrap.values = g_strdupv ((char **) values);
+	_rl_compentry_func_wrap.idx = 0;
+	_rl_compentry_func_wrap.initialized = TRUE;
+	return _rl_compentry_func_wrap_fcn;
+}
+
 char *
 nmc_rl_gen_func_ifnames (const char *text, int state)
 {
@@ -1608,8 +1074,6 @@ nmc_parse_lldp_capabilities (guint value)
 	return g_string_free (str, FALSE);
 }
 
-extern GMainLoop *loop;
-
 static void
 command_done (GObject *object, GAsyncResult *res, gpointer user_data)
 {
diff --git a/clients/cli/common.h b/clients/cli/common.h
index 3a598f63..354b2a5f 100644
--- a/clients/cli/common.h
+++ b/clients/cli/common.h
@@ -25,26 +25,10 @@
 #include "nmcli.h"
 #include "nm-secret-agent-simple.h"
 
-gboolean print_ip4_config (NMIPConfig *cfg4, NmCli *nmc, const char *group_prefix, const char *one_field);
-gboolean print_ip6_config (NMIPConfig *cfg6, NmCli *nmc, const char *group_prefix, const char *one_field);
-gboolean print_dhcp4_config (NMDhcpConfig *dhcp4, NmCli *nmc, const char *group_prefix, const char *one_field);
-gboolean print_dhcp6_config (NMDhcpConfig *dhcp6, NmCli *nmc, const char *group_prefix, const char *one_field);
-
-NMIPAddress *nmc_parse_and_build_address (int family, const char *ip_str, GError **error);
-NMIPRoute *nmc_parse_and_build_route (int family, const char *str, GError **error);
-
-const char * nmc_device_state_to_string (NMDeviceState state);
-const char * nmc_device_reason_to_string (NMDeviceStateReason reason);
-const char * nmc_device_metered_to_string (NMMetered value);
-
-char **
-nmc_vlan_parse_priority_maps (const char *priority_map,
-                              NMVlanPriorityMap map_type,
-                              GError **error);
-
-const char *nmc_bond_validate_mode (const char *mode, GError **error);
-gboolean nmc_team_check_config (const char *config, char **out_config, GError **error);
-gboolean nmc_proxy_check_script (const char *script, char **out_script, GError **error);
+gboolean print_ip4_config (NMIPConfig *cfg4, const NmcConfig *nmc_config, const char *one_field);
+gboolean print_ip6_config (NMIPConfig *cfg6, const NmcConfig *nmc_config, const char *group_prefix, const char *one_field);
+gboolean print_dhcp4_config (NMDhcpConfig *dhcp4, const NmcConfig *nmc_config, const char *group_prefix, const char *one_field);
+gboolean print_dhcp6_config (NMDhcpConfig *dhcp6, const NmcConfig *nmc_config, const char *group_prefix, const char *one_field);
 
 NMConnection *nmc_find_connection (const GPtrArray *connections,
                                    const char *filter_type,
@@ -65,7 +49,8 @@ char *nmc_unique_connection_name (const GPtrArray *connections,
 void nmc_cleanup_readline (void);
 char *nmc_readline (const char *prompt_fmt, ...) G_GNUC_PRINTF (1, 2);
 char *nmc_readline_echo (gboolean echo_on, const char *prompt_fmt, ...) G_GNUC_PRINTF (2, 3);
-char *nmc_rl_gen_func_basic (const char *text, int state, const char **words);
+NmcCompEntryFunc nmc_rl_compentry_func_wrap (const char *const*values);
+char *nmc_rl_gen_func_basic (const char *text, int state, const char *const*words);
 char *nmc_rl_gen_func_ifnames (const char *text, int state);
 gboolean nmc_get_in_readline (void);
 void nmc_set_in_readline (gboolean in_readline);
@@ -92,9 +77,9 @@ void nmc_complete_bool (const char *prefix);
 
 const char *nmc_error_get_simple_message (GError *error);
 
-extern NmcOutputField nmc_fields_ip4_config[];
-extern NmcOutputField nmc_fields_dhcp4_config[];
-extern NmcOutputField nmc_fields_ip6_config[];
-extern NmcOutputField nmc_fields_dhcp6_config[];
+extern const NmcMetaGenericInfo *const metagen_ip4_config[];
+extern const NmcMetaGenericInfo *const nmc_fields_dhcp4_config[];
+extern const NmcMetaGenericInfo *const nmc_fields_ip6_config[];
+extern const NmcMetaGenericInfo *const nmc_fields_dhcp6_config[];
 
 #endif /* NMC_COMMON_H */
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index a93dc15f..c05a9e82 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -19,6 +19,8 @@
 
 #include "nm-default.h"
 
+#include "connections.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -29,33 +31,35 @@
 #include <readline/readline.h>
 #include <readline/history.h>
 
+#include "nm-utils/nm-hash-utils.h"
+
+#include "nm-client-utils.h"
+#include "nm-vpn-helpers.h"
+#include "nm-meta-setting-access.h"
+#include "nm-secret-agent-simple.h"
+
 #include "utils.h"
 #include "common.h"
 #include "settings.h"
-#include "connections.h"
 #include "devices.h"
-#include "nm-secret-agent-simple.h"
 #include "polkit-agent.h"
-#include "nm-vpn-helpers.h"
+
+typedef enum {
+	PROPERTY_INF_FLAG_NONE                      = 0x0,
+	PROPERTY_INF_FLAG_DISABLED                  = 0x1, /* Don't ask due to runtime decision. */
+	PROPERTY_INF_FLAG_ENABLED                   = 0x2, /* Override NM_META_PROPERTY_INF_FLAG_DONT_ASK due to runtime decision. */
+	PROPERTY_INF_FLAG_ALL                       = 0x3,
+} PropertyInfFlags;
+
+typedef char *(*CompEntryFunc) (const char *, int);
 
 typedef struct _OptionInfo OptionInfo;
 struct _OptionInfo {
-	const char *setting_name;
+	const NMMetaSettingInfoEditor *setting_info;
 	const char *property;
 	const char *option;
-	enum {
-		OPTION_NONE = 0x00,
-		OPTION_REQD = 0x01,	/* Don't ask to ask. */
-		OPTION_DONT_ASK = 0x02,	/* Don't ask interactively by default */
-		OPTION_MULTI = 0x04,	/* Ask multiple times, do an append instead of set. */
-
-		OPTION_DISABLED = 0x10,	/* Don't ask due to runtime decision. */
-		OPTION_ENABLED = 0x20,	/* Override OPTION_DONT_ASK due to runtime decision. */
-	} flags;
-	const char *prompt;
-	const char *def_hint;
-	gboolean (*check_and_set)(NmCli *nmc, NMConnection *connection, OptionInfo *option, const char *value, GError **error);
-	rl_compentry_func_t *generator_func;
+	gboolean (*check_and_set)(NmCli *nmc, NMConnection *connection, const OptionInfo *option, const char *value, GError **error);
+	CompEntryFunc generator_func;
 };
 
 /* define some prompts for connection editor */
@@ -64,59 +68,6 @@ struct _OptionInfo {
 #define EDITOR_PROMPT_CON_TYPE _("Enter connection type: ")
 
 /* define some other prompts */
-#define PROMPT_CON_TYPE    N_("Connection type")
-#define PROMPT_IFNAME      N_("Interface name [*]")
-#define PROMPT_VPN_TYPE    N_("VPN type")
-#define PROMPT_MASTER      N_("Master")
-
-#define PROMPT_IB_MODE     N_("Transport mode")
-#define WORD_DATAGRAM  "datagram"
-#define WORD_CONNECTED "connected"
-#define PROMPT_IB_MODE_CHOICES "(" WORD_DATAGRAM "/" WORD_CONNECTED ") [" WORD_DATAGRAM "]"
-
-#define PROMPT_BT_TYPE N_("Bluetooth type")
-#define WORD_PANU      "panu"
-#define WORD_DUN_GSM   "dun-gsm"
-#define WORD_DUN_CDMA  "dun-cdma"
-#define PROMPT_BT_TYPE_CHOICES "(" WORD_PANU "/" WORD_DUN_GSM "/" WORD_DUN_CDMA ") [" WORD_PANU "]"
-
-#define PROMPT_BOND_MODE N_("Bonding mode")
-
-#define PROMPT_BOND_MON_MODE N_("Bonding monitoring mode")
-#define WORD_MIIMON "miimon"
-#define WORD_ARP    "arp"
-#define PROMPT_BOND_MON_MODE_CHOICES "(" WORD_MIIMON "/" WORD_ARP ") [" WORD_MIIMON "]"
-
-#define PROMPT_ADSL_PROTO N_("Protocol")
-#define PROMPT_ADSL_PROTO_CHOICES "(" NM_SETTING_ADSL_PROTOCOL_PPPOA "/" NM_SETTING_ADSL_PROTOCOL_PPPOE "/" NM_SETTING_ADSL_PROTOCOL_IPOATM ")"
-
-#define PROMPT_WIFI_MODE N_("Wi-Fi mode")
-#define WORD_INFRA  "infrastructure"
-#define WORD_AP     "ap"
-#define WORD_ADHOC  "adhoc"
-#define PROMPT_WIFI_MODE_CHOICES "(" WORD_INFRA "/" WORD_AP "/" WORD_ADHOC ") [" WORD_INFRA "]"
-
-#define PROMPT_ADSL_ENCAP N_("ADSL encapsulation")
-#define PROMPT_ADSL_ENCAP_CHOICES "(" NM_SETTING_ADSL_ENCAPSULATION_VCMUX "/" NM_SETTING_ADSL_ENCAPSULATION_LLC ") [none]"
-
-#define PROMPT_TUN_MODE N_("Tun mode")
-#define WORD_TUN  "tun"
-#define WORD_TAP  "tap"
-#define PROMPT_TUN_MODE_CHOICES "(" WORD_TUN "/" WORD_TAP ") [" WORD_TUN "]"
-
-#define PROMPT_IP_TUNNEL_MODE N_("IP Tunnel mode")
-
-#define PROMPT_MACVLAN_MODE N_("MACVLAN mode")
-
-#define PROMPT_MACSEC_MODE N_("MACsec mode")
-#define WORD_PSK "psk"
-#define WORD_EAP "eap"
-#define PROMPT_MACSEC_MODE_CHOICES "(" WORD_PSK "/" WORD_EAP ")"
-
-#define PROMPT_PROXY_METHOD N_("Proxy method")
-#define WORD_NONE "none"
-#define WORD_AUTO "auto"
-#define PROMPT_PROXY_METHOD_CHOICES "(" WORD_NONE "/" WORD_AUTO ") [" WORD_NONE "]"
 
 #define PROMPT_CONNECTION  _("Connection (name, UUID, or path)")
 #define PROMPT_VPN_CONNECTION  _("VPN connection (name, UUID, or path)")
@@ -125,68 +76,44 @@ struct _OptionInfo {
 
 #define BASE_PROMPT "nmcli> "
 
-/* Available fields for 'connection show' */
-NmcOutputField nmc_fields_con_show[] = {
-	{"NAME",                 N_("NAME")},                  /* 0 */
-	{"UUID",                 N_("UUID")},                  /* 1 */
-	{"TYPE",                 N_("TYPE")},                  /* 2 */
-	{"TIMESTAMP",            N_("TIMESTAMP")},             /* 3 */
-	{"TIMESTAMP-REAL",       N_("TIMESTAMP-REAL")},        /* 4 */
-	{"AUTOCONNECT",          N_("AUTOCONNECT")},           /* 5 */
-	{"AUTOCONNECT-PRIORITY", N_("AUTOCONNECT-PRIORITY")},  /* 6 */
-	{"READONLY",             N_("READONLY")},              /* 7 */
-	{"DBUS-PATH",            N_("DBUS-PATH")},             /* 8 */
-	{"ACTIVE",               N_("ACTIVE")},                /* 9 */
-	{"DEVICE",               N_("DEVICE")},                /* 10 */
-	{"STATE",                N_("STATE")},                 /* 11 */
-	{"ACTIVE-PATH",          N_("ACTIVE-PATH")},           /* 12 */
-	{"SLAVE",                N_("SLAVE")},                 /* 13 */
-	{NULL, NULL}
+/*****************************************************************************/
+
+const NmcMetaGenericInfo *const nmc_fields_con_show[] = {
+	NMC_META_GENERIC ("NAME"),                  /* 0 */
+	NMC_META_GENERIC ("UUID"),                  /* 1 */
+	NMC_META_GENERIC ("TYPE"),                  /* 2 */
+	NMC_META_GENERIC ("TIMESTAMP"),             /* 3 */
+	NMC_META_GENERIC ("TIMESTAMP-REAL"),        /* 4 */
+	NMC_META_GENERIC ("AUTOCONNECT"),           /* 5 */
+	NMC_META_GENERIC ("AUTOCONNECT-PRIORITY"),  /* 6 */
+	NMC_META_GENERIC ("READONLY"),              /* 7 */
+	NMC_META_GENERIC ("DBUS-PATH"),             /* 8 */
+	NMC_META_GENERIC ("ACTIVE"),                /* 9 */
+	NMC_META_GENERIC ("DEVICE"),                /* 10 */
+	NMC_META_GENERIC ("STATE"),                 /* 11 */
+	NMC_META_GENERIC ("ACTIVE-PATH"),           /* 12 */
+	NMC_META_GENERIC ("SLAVE"),                 /* 13 */
+	NULL,
 };
-#define NMC_FIELDS_CON_SHOW_ALL     "NAME,UUID,TYPE,TIMESTAMP,TIMESTAMP-REAL,AUTOCONNECT,AUTOCONNECT-PRIORITY,READONLY,DBUS-PATH,"\
-                                    "ACTIVE,DEVICE,STATE,ACTIVE-PATH,SLAVE"
 #define NMC_FIELDS_CON_SHOW_COMMON  "NAME,UUID,TYPE,DEVICE"
 
-/* Helper macro to define fields */
-#define SETTING_FIELD(setting, props) { setting, N_(setting), 0, props, NULL, FALSE, FALSE, 0 }
-
-/* Available settings for 'connection show <con>' - profile part */
-NmcOutputField nmc_fields_settings_names[] = {
-	SETTING_FIELD (NM_SETTING_CONNECTION_SETTING_NAME,        nmc_fields_setting_connection + 1),        /* 0 */
-	SETTING_FIELD (NM_SETTING_WIRED_SETTING_NAME,             nmc_fields_setting_wired + 1),             /* 1 */
-	SETTING_FIELD (NM_SETTING_802_1X_SETTING_NAME,            nmc_fields_setting_8021X + 1),             /* 2 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SETTING_NAME,          nmc_fields_setting_wireless + 1),          /* 3 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, nmc_fields_setting_wireless_security + 1), /* 4 */
-	SETTING_FIELD (NM_SETTING_IP4_CONFIG_SETTING_NAME,        nmc_fields_setting_ip4_config + 1),        /* 5 */
-	SETTING_FIELD (NM_SETTING_IP6_CONFIG_SETTING_NAME,        nmc_fields_setting_ip6_config + 1),        /* 6 */
-	SETTING_FIELD (NM_SETTING_SERIAL_SETTING_NAME,            nmc_fields_setting_serial + 1),            /* 7 */
-	SETTING_FIELD (NM_SETTING_PPP_SETTING_NAME,               nmc_fields_setting_ppp + 1),               /* 8 */
-	SETTING_FIELD (NM_SETTING_PPPOE_SETTING_NAME,             nmc_fields_setting_pppoe + 1),             /* 9 */
-	SETTING_FIELD (NM_SETTING_GSM_SETTING_NAME,               nmc_fields_setting_gsm + 1),               /* 10 */
-	SETTING_FIELD (NM_SETTING_CDMA_SETTING_NAME,              nmc_fields_setting_cdma + 1),              /* 11 */
-	SETTING_FIELD (NM_SETTING_BLUETOOTH_SETTING_NAME,         nmc_fields_setting_bluetooth + 1),         /* 12 */
-	SETTING_FIELD (NM_SETTING_OLPC_MESH_SETTING_NAME,         nmc_fields_setting_olpc_mesh + 1),         /* 13 */
-	SETTING_FIELD (NM_SETTING_VPN_SETTING_NAME,               nmc_fields_setting_vpn + 1),               /* 14 */
-	SETTING_FIELD (NM_SETTING_WIMAX_SETTING_NAME,             nmc_fields_setting_wimax + 1),             /* 15 */
-	SETTING_FIELD (NM_SETTING_INFINIBAND_SETTING_NAME,        nmc_fields_setting_infiniband + 1),        /* 16 */
-	SETTING_FIELD (NM_SETTING_BOND_SETTING_NAME,              nmc_fields_setting_bond + 1),              /* 17 */
-	SETTING_FIELD (NM_SETTING_VLAN_SETTING_NAME,              nmc_fields_setting_vlan + 1),              /* 18 */
-	SETTING_FIELD (NM_SETTING_ADSL_SETTING_NAME,              nmc_fields_setting_adsl + 1),              /* 19 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_SETTING_NAME,            nmc_fields_setting_bridge + 1),            /* 20 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_PORT_SETTING_NAME,       nmc_fields_setting_bridge_port + 1),       /* 21 */
-	SETTING_FIELD (NM_SETTING_TEAM_SETTING_NAME,              nmc_fields_setting_team + 1),              /* 22 */
-	SETTING_FIELD (NM_SETTING_TEAM_PORT_SETTING_NAME,         nmc_fields_setting_team_port + 1),         /* 23 */
-	SETTING_FIELD (NM_SETTING_DCB_SETTING_NAME,               nmc_fields_setting_dcb + 1),               /* 24 */
-	SETTING_FIELD (NM_SETTING_TUN_SETTING_NAME,               nmc_fields_setting_tun + 1),               /* 25 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_SETTING_NAME,         nmc_fields_setting_ip_tunnel + 1),         /* 26 */
-	SETTING_FIELD (NM_SETTING_MACSEC_SETTING_NAME,            nmc_fields_setting_macsec + 1),            /* 27 */
-	SETTING_FIELD (NM_SETTING_MACVLAN_SETTING_NAME,           nmc_fields_setting_macvlan + 1),           /* 28 */
-	SETTING_FIELD (NM_SETTING_VXLAN_SETTING_NAME,             nmc_fields_setting_vxlan + 1),             /* 29 */
-	SETTING_FIELD (NM_SETTING_PROXY_SETTING_NAME,             nmc_fields_setting_proxy + 1),             /* 30 */
-	SETTING_FIELD (NM_SETTING_DUMMY_SETTING_NAME,             nmc_fields_setting_dummy + 1),             /* 31 */
-	{NULL, NULL, 0, NULL, NULL, FALSE, FALSE, 0}
+const NmcMetaGenericInfo *const nmc_fields_con_active_details_general[] = {
+	NMC_META_GENERIC ("GROUP"),        /* 0 */
+	NMC_META_GENERIC ("NAME"),         /* 1 */
+	NMC_META_GENERIC ("UUID"),         /* 2 */
+	NMC_META_GENERIC ("DEVICES"),      /* 3 */
+	NMC_META_GENERIC ("STATE"),        /* 4 */
+	NMC_META_GENERIC ("DEFAULT"),      /* 5 */
+	NMC_META_GENERIC ("DEFAULT6"),     /* 6 */
+	NMC_META_GENERIC ("SPEC-OBJECT"),  /* 7 */
+	NMC_META_GENERIC ("VPN"),          /* 8 */
+	NMC_META_GENERIC ("DBUS-PATH"),    /* 9 */
+	NMC_META_GENERIC ("CON-PATH"),     /* 10 */
+	NMC_META_GENERIC ("ZONE"),         /* 11 */
+	NMC_META_GENERIC ("MASTER-PATH"),  /* 12 */
+	NULL,
 };
-#define NMC_FIELDS_SETTINGS_NAMES_ALL_X  NM_SETTING_CONNECTION_SETTING_NAME","\
+#define NMC_FIELDS_SETTINGS_NAMES_ALL    NM_SETTING_CONNECTION_SETTING_NAME","\
                                          NM_SETTING_WIRED_SETTING_NAME","\
                                          NM_SETTING_802_1X_SETTING_NAME","\
                                          NM_SETTING_WIRELESS_SETTING_NAME","\
@@ -209,6 +136,10 @@ NmcOutputField nmc_fields_settings_names[] = {
                                          NM_SETTING_BRIDGE_PORT_SETTING_NAME","\
                                          NM_SETTING_TEAM_SETTING_NAME","\
                                          NM_SETTING_TEAM_PORT_SETTING_NAME"," \
+                                         NM_SETTING_OVS_BRIDGE_SETTING_NAME","\
+                                         NM_SETTING_OVS_INTERFACE_SETTING_NAME","\
+                                         NM_SETTING_OVS_PATCH_SETTING_NAME","\
+                                         NM_SETTING_OVS_PORT_SETTING_NAME","\
                                          NM_SETTING_DCB_SETTING_NAME"," \
                                          NM_SETTING_TUN_SETTING_NAME"," \
                                          NM_SETTING_IP_TUNNEL_SETTING_NAME"," \
@@ -216,61 +147,30 @@ NmcOutputField nmc_fields_settings_names[] = {
                                          NM_SETTING_MACVLAN_SETTING_NAME"," \
                                          NM_SETTING_VXLAN_SETTING_NAME"," \
                                          NM_SETTING_PROXY_SETTING_NAME
-#define NMC_FIELDS_SETTINGS_NAMES_ALL    NMC_FIELDS_SETTINGS_NAMES_ALL_X
-
-/* Active connection data */
-/* Available fields for GENERAL group */
-NmcOutputField nmc_fields_con_active_details_general[] = {
-	{"GROUP",         N_("GROUP")},        /* 0 */
-	{"NAME",          N_("NAME")},         /* 1 */
-	{"UUID",          N_("UUID")},         /* 2 */
-	{"DEVICES",       N_("DEVICES")},      /* 3 */
-	{"STATE",         N_("STATE")},        /* 4 */
-	{"DEFAULT",       N_("DEFAULT")},      /* 5 */
-	{"DEFAULT6",      N_("DEFAULT6")},     /* 6 */
-	{"SPEC-OBJECT",   N_("SPEC-OBJECT")},  /* 7 */
-	{"VPN",           N_("VPN")},          /* 8 */
-	{"DBUS-PATH",     N_("DBUS-PATH")},    /* 9 */
-	{"CON-PATH",      N_("CON-PATH")},     /* 10 */
-	{"ZONE",          N_("ZONE")},         /* 11 */
-	{"MASTER-PATH",   N_("MASTER-PATH")},  /* 12 */
-	{NULL, NULL}
-};
-#define NMC_FIELDS_CON_ACTIVE_DETAILS_GENERAL_ALL  "GROUP,NAME,UUID,DEVICES,STATE,DEFAULT,DEFAULT6,"\
-                                                   "VPN,ZONE,DBUS-PATH,CON-PATH,SPEC-OBJECT,MASTER-PATH"
-
-/* IP group is handled by common.c */
-
-/* Available fields for VPN group */
-NmcOutputField nmc_fields_con_active_details_vpn[] = {
-	{"GROUP",     N_("GROUP")},      /* 0 */
-	{"TYPE",      N_("TYPE")},       /* 1 */
-	{"USERNAME",  N_("USERNAME")},   /* 2 */
-	{"GATEWAY",   N_("GATEWAY")},    /* 3 */
-	{"BANNER",    N_("BANNER")},     /* 4 */
-	{"VPN-STATE", N_("VPN-STATE")},  /* 5 */
-	{"CFG",       N_("CFG")},        /* 6 */
-	{NULL, NULL}
+                                         // NM_SETTING_DUMMY_SETTING_NAME
+                                         // NM_SETTING_WIMAX_SETTING_NAME
+
+
+const NmcMetaGenericInfo *const nmc_fields_con_active_details_vpn[] = {
+	NMC_META_GENERIC ("GROUP"),      /* 0 */
+	NMC_META_GENERIC ("TYPE"),       /* 1 */
+	NMC_META_GENERIC ("USERNAME"),   /* 2 */
+	NMC_META_GENERIC ("GATEWAY"),    /* 3 */
+	NMC_META_GENERIC ("BANNER"),     /* 4 */
+	NMC_META_GENERIC ("VPN-STATE"),  /* 5 */
+	NMC_META_GENERIC ("CFG"),        /* 6 */
+	NULL,
 };
-#define NMC_FIELDS_CON_ACTIVE_DETAILS_VPN_ALL  "GROUP,TYPE,USERNAME,GATEWAY,BANNER,VPN-STATE,CFG"
-
-/* defined in common.c */
-extern NmcOutputField nmc_fields_ip4_config[];
-extern NmcOutputField nmc_fields_ip6_config[];
-extern NmcOutputField nmc_fields_dhcp4_config[];
-extern NmcOutputField nmc_fields_dhcp6_config[];
-
-/* Available fields for 'connection show <con>' - active part */
-NmcOutputField nmc_fields_con_active_details_groups[] = {
-	{"GENERAL",  N_("GENERAL"), 0, nmc_fields_con_active_details_general + 1},  /* 0 */
-	{"IP4",      N_("IP4"),     0, nmc_fields_ip4_config + 1                },  /* 1 */
-	{"DHCP4",    N_("DHCP4"),   0, nmc_fields_dhcp4_config + 1              },  /* 2 */
-	{"IP6",      N_("IP6"),     0, nmc_fields_ip6_config + 1                },  /* 3 */
-	{"DHCP6",    N_("DHCP6"),   0, nmc_fields_dhcp6_config + 1              },  /* 4 */
-	{"VPN",      N_("VPN"),     0, nmc_fields_con_active_details_vpn + 1    },  /* 5 */
-	{NULL, NULL, 0, NULL}
+
+const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = {
+	NMC_META_GENERIC_WITH_NESTED ("GENERAL", nmc_fields_con_active_details_general + 1), /* 0 */
+	NMC_META_GENERIC_WITH_NESTED ("IP4",     metagen_ip4_config),                        /* 1 */
+	NMC_META_GENERIC_WITH_NESTED ("DHCP4",   nmc_fields_dhcp4_config + 1),               /* 2 */
+	NMC_META_GENERIC_WITH_NESTED ("IP6",     nmc_fields_ip6_config + 1),                 /* 3 */
+	NMC_META_GENERIC_WITH_NESTED ("DHCP6",   nmc_fields_dhcp6_config + 1),               /* 4 */
+	NMC_META_GENERIC_WITH_NESTED ("VPN",     nmc_fields_con_active_details_vpn + 1),     /* 5 */
+	NULL,
 };
-#define NMC_FIELDS_CON_ACTIVE_DETAILS_ALL  "GENERAL,IP4,DHCP4,IP6,DHCP6,VPN"
 
 /* Pseudo group names for 'connection show <con>' */
 /* e.g.: nmcli -f profile con show my-eth0 */
@@ -278,9 +178,6 @@ NmcOutputField nmc_fields_con_active_details_groups[] = {
 #define CON_SHOW_DETAIL_GROUP_PROFILE "profile"
 #define CON_SHOW_DETAIL_GROUP_ACTIVE  "active"
 
-/* glib main loop variable - defined in nmcli.c */
-extern GMainLoop *loop;
-
 static guint progress_id = 0;  /* ID of event source for displaying progress */
 
 /* for readline TAB completion in editor */
@@ -293,8 +190,6 @@ typedef struct {
 } TabCompletionInfo;
 static TabCompletionInfo nmc_tab_completion = {NULL, NULL, NULL, NULL};
 
-static char *gen_connection_types (const char *text, int state);
-
 static void
 usage (void)
 {
@@ -412,7 +307,7 @@ usage_connection_add (void)
 	              "                  [parent <ifname>]\n"
 	              "                  [p-key <IPoIB P_Key>]\n\n"
 	              "    bluetooth:    [addr <bluetooth address>]\n"
-	              "                  [bt-type panu|dun-gsm|dun-cdma]\n\n"
+	              "                  [bt-type panu|nap|dun-gsm|dun-cdma]\n\n"
 	              "    vlan:         dev <parent device (connection UUID, ifname, or MAC)>\n"
 	              "                  id <VLAN ID>\n"
 	              "                  [flags <VLAN flags>]\n"
@@ -606,7 +501,6 @@ usage_connection_export (void)
 	              "The data are directed to standard output or to a file if a name is given.\n\n"));
 }
 
-/* quit main loop */
 static void
 quit (void)
 {
@@ -616,23 +510,16 @@ quit (void)
 		nmc_terminal_erase_line ();
 	}
 
-	g_main_loop_quit (loop);  /* quit main loop */
+	g_main_loop_quit (loop);
 }
 
-static const char *
+static char *
 construct_header_name (const char *base, const char *spec)
 {
-	static char header_name[128];
-
 	if (spec == NULL)
-		return base;
+		return g_strdup (base);
 
-	g_strlcpy (header_name, base, sizeof (header_name));
-	g_strlcat (header_name, " (", sizeof (header_name));
-	g_strlcat (header_name, spec, sizeof (header_name));
-	g_strlcat (header_name, ")", sizeof (header_name));
-
-	return header_name;
+	return g_strdup_printf ("%s (%s)", base, spec);
 }
 
 static const char *
@@ -736,12 +623,12 @@ update_secrets_in_connection (NMRemoteConnection *remote, NMConnection *local)
 	int i;
 	GError *error = NULL;
 
-	for (i = 0; nmc_fields_settings_names[i].name; i++) {
-		secrets = nm_remote_connection_get_secrets (remote, nmc_fields_settings_names[i].name, NULL, NULL);
+	for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+		secrets = nm_remote_connection_get_secrets (remote, nm_meta_setting_infos[i].setting_name, NULL, NULL);
 		if (secrets) {
 			if (!nm_connection_update_secrets (local, NULL, secrets, &error) && error) {
 				g_printerr (_("Error updating secrets for %s: %s\n"),
-				            nmc_fields_settings_names[i].name,
+				            nm_meta_setting_infos[i].setting_name,
 				            error->message);
 				g_clear_error (&error);
 			}
@@ -751,7 +638,7 @@ update_secrets_in_connection (NMRemoteConnection *remote, NMConnection *local)
 }
 
 static gboolean
-nmc_connection_profile_details (NMConnection *connection, NmCli *nmc, gboolean secrets)
+nmc_connection_profile_details (NMConnection *connection, NmCli *nmc)
 {
 	GError *error = NULL;
 	GArray *print_settings_array;
@@ -770,7 +657,8 @@ nmc_connection_profile_details (NMConnection *connection, NmCli *nmc, gboolean s
 	else
 		fields_str = nmc->required_fields;
 
-	print_settings_array = parse_output_fields (fields_str, nmc_fields_settings_names, TRUE, &prop_array, &error);
+	print_settings_array = parse_output_fields (fields_str, (const NMMetaAbstractInfo *const*) nm_meta_setting_infos_editor_p (),
+	                                            TRUE, &prop_array, &error);
 	if (error) {
 		g_string_printf (nmc->return_text, _("Error: 'connection show': %s"), error->message);
 		g_error_free (error);
@@ -780,12 +668,24 @@ nmc_connection_profile_details (NMConnection *connection, NmCli *nmc, gboolean s
 	g_assert (print_settings_array);
 
 	/* Main header */
-	nmc->print_fields.header_name = (char *) construct_header_name (base_hdr, nm_connection_get_id (connection));
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTINGS_NAMES_ALL,
-	                                                 nmc_fields_settings_names, FALSE, NULL, NULL);
+	{
+		gs_free char *header_name = NULL;
+		gs_free NmcOutputField *row = NULL;
+		gs_unref_array GArray *out_indices = NULL;
+
+		header_name = construct_header_name (base_hdr, nm_connection_get_id (connection));
+		out_indices = parse_output_fields (NMC_FIELDS_SETTINGS_NAMES_ALL,
+		                                   (const NMMetaAbstractInfo *const*) nm_meta_setting_infos_editor_p (),
+		                                   FALSE, NULL, NULL);
 
-	nmc_fields_settings_names[0].flags = NMC_OF_FLAG_MAIN_HEADER_ONLY;
-	print_required_fields (nmc, nmc_fields_settings_names);
+		row = g_new0 (NmcOutputField, _NM_META_SETTING_TYPE_NUM + 1);
+		for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++)
+			row[i].info = (const NMMetaAbstractInfo *) &nm_meta_setting_infos_editor[i];
+
+		print_required_fields (&nmc->nmc_config, NMC_OF_FLAG_MAIN_HEADER_ONLY,
+		                       out_indices, header_name,
+		                       0, row);
+	}
 
 	/* Loop through the required settings and print them. */
 	for (i = 0; i < print_settings_array->len; i++) {
@@ -793,19 +693,15 @@ nmc_connection_profile_details (NMConnection *connection, NmCli *nmc, gboolean s
 		int section_idx = g_array_index (print_settings_array, int, i);
 		const char *prop_name = (const char *) g_ptr_array_index (prop_array, i);
 
-		if (nmc->print_output != NMC_PRINT_TERSE && !nmc->multiline_output && was_output)
+		if (nmc->nmc_config.print_output != NMC_PRINT_TERSE && !nmc->nmc_config.multiline_output && was_output)
 			g_print ("\n"); /* Empty line */
 
 		was_output = FALSE;
 
-		/* Remove any previous data */
-		nmc_empty_output_fields (nmc);
-
-		setting = nm_connection_get_setting_by_name (connection, nmc_fields_settings_names[section_idx].name);
+		setting = nm_connection_get_setting_by_name (connection, nm_meta_setting_infos_editor[section_idx].general->setting_name);
 		if (setting) {
-			setting_details (setting, nmc, prop_name, secrets);
+			setting_details (&nmc->nmc_config, setting, prop_name);
 			was_output = TRUE;
-			continue;
 		}
 	}
 
@@ -894,20 +790,45 @@ found:
 }
 
 void
-nmc_active_connection_state_to_color (NMActiveConnectionState state, NmcTermColor *color)
+nmc_active_connection_state_to_color (NMActiveConnectionState state, NMMetaTermColor *color)
 {
-	*color = NMC_TERM_COLOR_NORMAL;
+	*color = NM_META_TERM_COLOR_NORMAL;
 
 	if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
-		*color = NMC_TERM_COLOR_YELLOW;
+		*color = NM_META_TERM_COLOR_YELLOW;
 	else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
-		*color = NMC_TERM_COLOR_GREEN;
+		*color = NM_META_TERM_COLOR_GREEN;
 	else if (state > NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
-		*color = NMC_TERM_COLOR_RED;
+		*color = NM_META_TERM_COLOR_RED;
+}
+
+/* Essentially a version of nm_setting_connection_get_connection_type() that
+ * prefers an alias instead of the settings name when in pretty print mode.
+ * That is so that we print "wifi" instead of "802-11-wireless" in "nmcli c". */
+static const char *
+connection_type_pretty (const char *type, NMCPrintOutput print_output)
+{
+	const NMMetaSettingInfoEditor *editor;
+	int i;
+
+	if (print_output == NMC_PRINT_TERSE)
+		return type;
+
+	for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+		editor = &nm_meta_setting_infos_editor[i];
+		if (strcmp (type, editor->general->setting_name) == 0) {
+			if (editor->alias)
+				return editor->alias;
+			break;
+		}
+	}
+
+	return type;
 }
 
 static void
-fill_output_connection (NMConnection *connection, NmCli *nmc, gboolean active_only)
+fill_output_connection (NMConnection *connection, NMClient *client, NMCPrintOutput print_output,
+                        GPtrArray *output_data, gboolean active_only)
 {
 	NMSettingConnection *s_con;
 	guint64 timestamp;
@@ -921,12 +842,12 @@ fill_output_connection (NMConnection *connection, NmCli *nmc, gboolean active_on
 	const char *ac_state = NULL;
 	NMActiveConnectionState ac_state_int = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
 	char *ac_dev = NULL;
-	NmcTermColor color;
+	NMMetaTermColor color;
 
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 
-	ac = get_ac_for_connection (nm_client_get_active_connections (nmc->client), connection);
+	ac = get_ac_for_connection (nm_client_get_active_connections (client), connection);
 	if (active_only && !ac)
 		return;
 
@@ -947,9 +868,7 @@ fill_output_connection (NMConnection *connection, NmCli *nmc, gboolean active_on
 	}
 	prio_str = g_strdup_printf ("%u", nm_setting_connection_get_autoconnect_priority (s_con));
 
-	arr = nmc_dup_fields_array (nmc_fields_con_show,
-	                            sizeof (nmc_fields_con_show),
-	                            0);
+	arr = nmc_dup_fields_array ((const NMMetaAbstractInfo *const*) nmc_fields_con_show, 0);
 
 	/* Show active connections in color */
 	nmc_active_connection_state_to_color (ac_state_int, &color);
@@ -957,7 +876,7 @@ fill_output_connection (NMConnection *connection, NmCli *nmc, gboolean active_on
 
 	set_val_strc (arr, 0, nm_setting_connection_get_id (s_con));
 	set_val_strc (arr, 1, nm_setting_connection_get_uuid (s_con));
-	set_val_strc (arr, 2, nm_setting_connection_get_connection_type (s_con));
+	set_val_strc (arr, 2, connection_type_pretty (nm_setting_connection_get_connection_type (s_con), print_output));
 	set_val_str  (arr, 3, timestamp_str);
 	set_val_str  (arr, 4, timestamp ? timestamp_real_str : g_strdup (_("never")));
 	set_val_strc (arr, 5, nm_setting_connection_get_autoconnect (s_con) ? _("yes") : _("no"));
@@ -970,11 +889,11 @@ fill_output_connection (NMConnection *connection, NmCli *nmc, gboolean active_on
 	set_val_strc (arr, 12, ac_path);
 	set_val_strc (arr, 13, nm_setting_connection_get_slave_type (s_con));
 
-	g_ptr_array_add (nmc->output_data, arr);
+	g_ptr_array_add (output_data, arr);
 }
 
 static void
-fill_output_connection_for_invisible (NMActiveConnection *ac, NmCli *nmc)
+fill_output_connection_for_invisible (NMActiveConnection *ac, NMCPrintOutput print_output, GPtrArray *output_data)
 {
 	NmcOutputField *arr;
 	const char *ac_path = NULL;
@@ -986,13 +905,11 @@ fill_output_connection_for_invisible (NMActiveConnection *ac, NmCli *nmc)
 	ac_state = active_connection_state_to_string (nm_active_connection_get_state (ac));
 	ac_dev = get_ac_device_string (ac);
 
-	arr = nmc_dup_fields_array (nmc_fields_con_show,
-	                            sizeof (nmc_fields_con_show),
-	                            0);
+	arr = nmc_dup_fields_array ((const NMMetaAbstractInfo *const*) nmc_fields_con_show, 0);
 
 	set_val_str  (arr, 0, name);
 	set_val_strc (arr, 1, nm_active_connection_get_uuid (ac));
-	set_val_strc (arr, 2, nm_active_connection_get_connection_type (ac));
+	set_val_strc (arr, 2, connection_type_pretty (nm_active_connection_get_connection_type (ac), print_output));
 	set_val_strc (arr, 3, NULL);
 	set_val_strc (arr, 4, NULL);
 	set_val_strc (arr, 5, NULL);
@@ -1005,14 +922,14 @@ fill_output_connection_for_invisible (NMActiveConnection *ac, NmCli *nmc)
 	set_val_strc (arr, 12, ac_path);
 	set_val_strc (arr, 13, NULL);
 
-	set_val_color_fmt_all (arr, NMC_TERM_FORMAT_DIM);
+	set_val_color_fmt_all (arr, NM_META_TERM_FORMAT_DIM);
 
-	g_ptr_array_add (nmc->output_data, arr);
+	g_ptr_array_add (output_data, arr);
 }
 
 static void
 fill_output_active_connection (NMActiveConnection *active,
-                               NmCli *nmc,
+                               GPtrArray *output_data,
                                gboolean with_group,
                                guint32 o_flags)
 {
@@ -1024,8 +941,8 @@ fill_output_active_connection (NMActiveConnection *active,
 	NMDevice *master;
 	const char *con_path = NULL, *con_zone = NULL;
 	int i;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	const NMMetaAbstractInfo *const*tmpl;
+	NmcOutputField *arr;
 	int idx_start = with_group ? 0 : 1;
 
 	con = nm_active_connection_get_connection (active);
@@ -1054,17 +971,14 @@ fill_output_active_connection (NMActiveConnection *active,
 	if (dev_str->len > 0)
 		g_string_truncate (dev_str, dev_str->len - 1);  /* Cut off last ',' */
 
-	tmpl = nmc_fields_con_active_details_general;
-	tmpl_len = sizeof (nmc_fields_con_active_details_general);
-	if (!with_group) {
+	tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_general;
+	if (!with_group)
 		tmpl++;
-		tmpl_len -= sizeof (NmcOutputField);
-	}
 
 	/* Fill field values */
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, o_flags);
+	arr = nmc_dup_fields_array (tmpl, o_flags);
 	if (with_group)
-		set_val_strc (arr, 0, nmc_fields_con_active_details_groups[0].name);
+		set_val_strc (arr, 0, nmc_fields_con_active_details_groups[0]->name);
 	set_val_strc (arr, 1-idx_start, nm_active_connection_get_id (active));
 	set_val_strc (arr, 2-idx_start, nm_active_connection_get_uuid (active));
 	set_val_str  (arr, 3-idx_start, dev_str->str);
@@ -1079,7 +993,7 @@ fill_output_active_connection (NMActiveConnection *active,
 	set_val_strc (arr, 12-idx_start, master ? nm_object_get_path (NM_OBJECT (master)) : NULL);
 	set_val_strc (arr, 13-idx_start, s_con ? nm_setting_connection_get_slave_type (s_con) : NULL);
 
-	g_ptr_array_add (nmc->output_data, arr);
+	g_ptr_array_add (output_data, arr);
 
 	g_string_free (dev_str, FALSE);
 }
@@ -1182,22 +1096,19 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
 	GArray *print_groups;
 	GPtrArray *group_fields = NULL;
 	int i;
-	char *fields_str;
-	char *fields_all =    NMC_FIELDS_CON_ACTIVE_DETAILS_ALL;
-	char *fields_common = NMC_FIELDS_CON_ACTIVE_DETAILS_ALL;
-	NmcOutputField *tmpl, *arr;
+	const char *fields_str = NULL;
+	const NMMetaAbstractInfo *const*tmpl;
+	NmcOutputField *arr;
 	size_t tmpl_len;
 	const char *base_hdr = _("Activate connection details");
 	gboolean was_output = FALSE;
 
-	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
-		fields_str = fields_common;
-	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
-		fields_str = fields_all;
-	else
+	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) {
+	} else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) {
+	} else
 		fields_str = nmc->required_fields;
 
-	print_groups = parse_output_fields (fields_str, nmc_fields_con_active_details_groups, TRUE, &group_fields, &error);
+	print_groups = parse_output_fields (fields_str, (const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_groups, TRUE, &group_fields, &error);
 	if (error) {
 		g_string_printf (nmc->return_text, _("Error: 'connection show': %s"), error->message);
 		g_error_free (error);
@@ -1207,83 +1118,95 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
 	g_assert (print_groups);
 
 	/* Main header */
-	nmc->print_fields.header_name = (char *) construct_header_name (base_hdr, nm_active_connection_get_uuid (acon));
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_CON_ACTIVE_DETAILS_ALL,
-	                                                 nmc_fields_con_active_details_groups, FALSE, NULL, NULL);
+	{
+		gs_free char *header_name = NULL;
+		gs_free NmcOutputField *row = NULL;
+		gs_unref_array GArray *out_indices = NULL;
+
+		header_name = construct_header_name (base_hdr, nm_active_connection_get_uuid (acon));
+		out_indices = parse_output_fields (NULL,
+		                                   (const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_groups,
+		                                   FALSE, NULL, NULL);
 
-	nmc_fields_con_active_details_groups[0].flags = NMC_OF_FLAG_MAIN_HEADER_ONLY;
-	print_required_fields (nmc, nmc_fields_con_active_details_groups);
+		row = g_new0 (NmcOutputField, G_N_ELEMENTS (nmc_fields_con_active_details_groups) + 1);
+		for (i = 0; nmc_fields_con_active_details_groups[i]; i++)
+			row[i].info = (const NMMetaAbstractInfo *) nmc_fields_con_active_details_groups[i];
+
+		print_required_fields (&nmc->nmc_config, NMC_OF_FLAG_MAIN_HEADER_ONLY,
+		                       out_indices, header_name,
+		                       0, row);
+	}
 
 	/* Loop through the groups and print them. */
 	for (i = 0; i < print_groups->len; i++) {
 		int group_idx = g_array_index (print_groups, int, i);
 		char *group_fld = (char *) g_ptr_array_index (group_fields, i);
 
-		if (nmc->print_output != NMC_PRINT_TERSE && !nmc->multiline_output && was_output)
+		if (nmc->nmc_config.print_output != NMC_PRINT_TERSE && !nmc->nmc_config.multiline_output && was_output)
 			g_print ("\n"); /* Empty line */
 
 		was_output = FALSE;
 
-		/* Remove any previous data */
-		nmc_empty_output_fields (nmc);
-
 		/* GENERAL */
-		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx].name, nmc_fields_con_active_details_groups[0].name) == 0) {
+		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx]->name, nmc_fields_con_active_details_groups[0]->name) == 0) {
+			NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+
 			/* Add field names */
-			tmpl = nmc_fields_con_active_details_general;
+			tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_general;
 			tmpl_len = sizeof (nmc_fields_con_active_details_general);
-			nmc->print_fields.indices = parse_output_fields (group_fld ? group_fld : NMC_FIELDS_CON_ACTIVE_DETAILS_GENERAL_ALL,
-			                                                 tmpl, FALSE, NULL, NULL);
-			arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-			g_ptr_array_add (nmc->output_data, arr);
+			out_indices = parse_output_fields (group_fld,
+			                                   tmpl, FALSE, NULL, NULL);
+			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+			g_ptr_array_add (out.output_data, arr);
 
 			/* Fill in values */
-			fill_output_active_connection (acon, nmc, TRUE, NMC_OF_FLAG_SECTION_PREFIX);
+			fill_output_active_connection (acon, out.output_data, TRUE, NMC_OF_FLAG_SECTION_PREFIX);
 
-			print_data (nmc);  /* Print all data */
+			print_data_prepare_width (out.output_data);
+			print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 
 			was_output = TRUE;
 		}
 
 		/* IP4 */
-		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx].name,  nmc_fields_con_active_details_groups[1].name) == 0) {
+		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx]->name,  nmc_fields_con_active_details_groups[1]->name) == 0) {
 			gboolean b1 = FALSE;
 			NMIPConfig *cfg4 = nm_active_connection_get_ip4_config (acon);
 
-			b1 = print_ip4_config (cfg4, nmc, "IP4", group_fld);
+			b1 = print_ip4_config (cfg4, &nmc->nmc_config, group_fld);
 			was_output = was_output || b1;
 		}
 
 		/* DHCP4 */
-		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx].name,  nmc_fields_con_active_details_groups[2].name) == 0) {
+		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx]->name,  nmc_fields_con_active_details_groups[2]->name) == 0) {
 			gboolean b1 = FALSE;
 			NMDhcpConfig *dhcp4 = nm_active_connection_get_dhcp4_config (acon);
 
-			b1 = print_dhcp4_config (dhcp4, nmc, "DHCP4", group_fld);
+			b1 = print_dhcp4_config (dhcp4, &nmc->nmc_config, "DHCP4", group_fld);
 			was_output = was_output || b1;
 		}
 
 		/* IP6 */
-		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx].name,  nmc_fields_con_active_details_groups[3].name) == 0) {
+		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx]->name,  nmc_fields_con_active_details_groups[3]->name) == 0) {
 			gboolean b1 = FALSE;
 			NMIPConfig *cfg6 = nm_active_connection_get_ip6_config (acon);
 
-			b1 = print_ip6_config (cfg6, nmc, "IP6", group_fld);
+			b1 = print_ip6_config (cfg6, &nmc->nmc_config, "IP6", group_fld);
 			was_output = was_output || b1;
 		}
 
 		/* DHCP6 */
-		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx].name,  nmc_fields_con_active_details_groups[4].name) == 0) {
+		if (strcasecmp (nmc_fields_con_active_details_groups[group_idx]->name,  nmc_fields_con_active_details_groups[4]->name) == 0) {
 			gboolean b1 = FALSE;
 			NMDhcpConfig *dhcp6 = nm_active_connection_get_dhcp6_config (acon);
 
-			b1 = print_dhcp6_config (dhcp6, nmc, "DHCP6", group_fld);
+			b1 = print_dhcp6_config (dhcp6, &nmc->nmc_config, "DHCP6", group_fld);
 			was_output = was_output || b1;
 		}
 
 		/* VPN */
 		if (NM_IS_VPN_CONNECTION (acon) &&
-		    strcasecmp (nmc_fields_con_active_details_groups[group_idx].name,  nmc_fields_con_active_details_groups[5].name) == 0) {
+		    strcasecmp (nmc_fields_con_active_details_groups[group_idx]->name,  nmc_fields_con_active_details_groups[5]->name) == 0) {
 			NMConnection *con;
 			NMSettingConnection *s_con;
 			NMSettingVpn *s_vpn;
@@ -1293,18 +1216,18 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
 			const char *username = NULL;
 			char **vpn_data_array = NULL;
 			guint32 items_num;
+			NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
 			con = NM_CONNECTION (nm_active_connection_get_connection (acon));
 
 			s_con = nm_connection_get_setting_connection (con);
 			g_assert (s_con != NULL);
 
-			tmpl = nmc_fields_con_active_details_vpn;
-			tmpl_len = sizeof (nmc_fields_con_active_details_vpn);
-			nmc->print_fields.indices = parse_output_fields (group_fld ? group_fld : NMC_FIELDS_CON_ACTIVE_DETAILS_VPN_ALL,
-			                                                 tmpl, FALSE, NULL, NULL);
-			arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-			g_ptr_array_add (nmc->output_data, arr);
+			tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_vpn;
+			out_indices = parse_output_fields (group_fld,
+			                                   tmpl, FALSE, NULL, NULL);
+			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+			g_ptr_array_add (out.output_data, arr);
 
 			s_vpn = nm_connection_get_setting_vpn (con);
 			if (s_vpn) {
@@ -1329,17 +1252,18 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
 			vpn_state_str = g_strdup_printf ("%d - %s", vpn_state, vpn_connection_state_to_string (vpn_state));
 
 			/* Add values */
-			arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-			set_val_strc (arr, 0, nmc_fields_con_active_details_groups[5].name);
+			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
+			set_val_strc (arr, 0, nmc_fields_con_active_details_groups[5]->name);
 			set_val_str  (arr, 1, type_str);
 			set_val_strc (arr, 2, username ? username : get_vpn_data_item (con, VPN_DATA_ITEM_USERNAME));
 			set_val_strc (arr, 3, get_vpn_data_item (con, VPN_DATA_ITEM_GATEWAY));
 			set_val_str  (arr, 4, banner_str);
 			set_val_str  (arr, 5, vpn_state_str);
 			set_val_arr  (arr, 6, vpn_data_array);
-			g_ptr_array_add (nmc->output_data, arr);
+			g_ptr_array_add (out.output_data, arr);
 
-			print_data (nmc);  /* Print all data */
+			print_data_prepare_width (out.output_data);
+			print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 			was_output = TRUE;
 		}
 	}
@@ -1389,9 +1313,9 @@ split_required_fields_for_con_show (const char *input,
 
 		found = FALSE;
 
-		for (i = 0; nmc_fields_settings_names[i].name; i++) {
+		for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
 			if (   is_all || is_common
-			    || !strcasecmp (*iter, nmc_fields_settings_names[i].name)) {
+			    || !strcasecmp (*iter, nm_meta_setting_infos[i].setting_name)) {
 				if (dot)
 					*dot = '.';
 				g_string_append (str1, *iter);
@@ -1402,9 +1326,9 @@ split_required_fields_for_con_show (const char *input,
 		}
 		if (found)
 			continue;
-		for (i = 0; nmc_fields_con_active_details_groups[i].name; i++) {
+		for (i = 0; nmc_fields_con_active_details_groups[i]; i++) {
 			if (   is_all || is_common
-			    || !strcasecmp (*iter, nmc_fields_con_active_details_groups[i].name)) {
+			    || !strcasecmp (*iter, nmc_fields_con_active_details_groups[i]->name)) {
 				if (dot)
 					*dot = '.';
 				g_string_append (str2, *iter);
@@ -1421,8 +1345,8 @@ split_required_fields_for_con_show (const char *input,
 			else if (!strcasecmp (*iter, CON_SHOW_DETAIL_GROUP_ACTIVE))
 				group_active = TRUE;
 			else {
-				char *allowed1 = nmc_get_allowed_fields (nmc_fields_settings_names, -1);
-				char *allowed2 = nmc_get_allowed_fields (nmc_fields_con_active_details_groups, -1);
+				char *allowed1 = nm_meta_abstract_infos_get_names_str ((const NMMetaAbstractInfo *const*) nm_meta_setting_infos_editor_p (), NULL);
+				char *allowed2 = nm_meta_abstract_infos_get_names_str ((const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_groups, NULL);
 				g_set_error (error, NMCLI_ERROR, 0, _("invalid field '%s'; allowed fields: %s and %s, or %s,%s"),
 				             *iter, allowed1, allowed2, CON_SHOW_DETAIL_GROUP_PROFILE, CON_SHOW_DETAIL_GROUP_ACTIVE);
 				g_free (allowed1);
@@ -1775,49 +1699,49 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
 
 	if (argc == 0) {
 		const GPtrArray *connections;
-		char *fields_str;
-		char *fields_all =    NMC_FIELDS_CON_SHOW_ALL;
+		const char *fields_str = NULL;
 		char *fields_common = NMC_FIELDS_CON_SHOW_COMMON;
-		NmcOutputField *tmpl, *arr;
-		size_t tmpl_len;
+		const NMMetaAbstractInfo *const*tmpl;
+		NmcOutputField *arr;
+		NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
 		if (nmc->complete)
 			goto finish;
 
 		if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
 			fields_str = fields_common;
-		else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
-			fields_str = fields_all;
-		else
+		else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) {
+		} else
 			fields_str = nmc->required_fields;
 
-		tmpl = nmc_fields_con_show;
-		tmpl_len = sizeof (nmc_fields_con_show);
-		nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &err);
+		tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_con_show;
+		out_indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &err);
 		if (err)
 			goto finish;
 
 		/* Add headers */
-		nmc->print_fields.header_name = active_only ? _("NetworkManager active profiles") :
-		                                              _("NetworkManager connection profiles");
-		arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-		g_ptr_array_add (nmc->output_data, arr);
+		arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
+		g_ptr_array_add (out.output_data, arr);
 
 		/* There might be active connections not present in connection list
 		 * (e.g. private connections of a different user). Show them as well. */
 		invisibles = get_invisible_active_connections (nmc);
 		for (i = 0; i < invisibles->len; i++)
-			fill_output_connection_for_invisible (invisibles->pdata[i], nmc);
+			fill_output_connection_for_invisible (invisibles->pdata[i], nmc->nmc_config.print_output, out.output_data);
 		g_ptr_array_free (invisibles, TRUE);
 
 		/* Sort the connections and fill the output data */
 		connections = nm_client_get_connections (nmc->client);
 		sorted_cons = sort_connections (connections, nmc, order);
 		for (i = 0; i < sorted_cons->len; i++)
-			fill_output_connection (sorted_cons->pdata[i], nmc, active_only);
+			fill_output_connection (sorted_cons->pdata[i], nmc->client, nmc->nmc_config.print_output, out.output_data, active_only);
 		g_ptr_array_free (sorted_cons, TRUE);
 
-		print_data (nmc);  /* Print all data */
+		print_data_prepare_width (out.output_data);
+		print_data (&nmc->nmc_config, out_indices,
+		            active_only ? _("NetworkManager active profiles")
+		                        : _("NetworkManager connection profiles"),
+		            0, &out);
 	} else {
 		gboolean new_line = FALSE;
 		gboolean without_fields = (nmc->required_fields == NULL);
@@ -1826,7 +1750,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
 
 		/* multiline mode is default for 'connection show <ID>' */
 		if (!nmc->mode_specified)
-			nmc->multiline_output = TRUE;
+			nmc->nmc_config_mutable.multiline_output = TRUE;
 
 		/* Split required fields into the settings and active ones. */
 		if (!split_required_fields_for_con_show (nmc->required_fields, &profile_flds, &active_flds, &err))
@@ -1836,7 +1760,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
 
 		/* Before printing the connections check if we have a "--show-secret"
 		 * option after the connection ids */
-		if (!nmc->show_secrets && !nmc->complete) {
+		if (!nmc->nmc_config.show_secrets && !nmc->complete) {
 			int argc_cp = argc;
 			char **argv_cp = argv;
 
@@ -1886,7 +1810,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
 				if (acon)
 					con = NM_CONNECTION (nm_active_connection_get_connection (acon));
 			}
-			
+
 			if (!con && !acon) {
 				g_string_printf (nmc->return_text, _("Error: %s - no such connection profile."), *argv);
 				nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
@@ -1920,9 +1844,9 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
 			if (without_fields || profile_flds) {
 				if (con) {
 					nmc->required_fields = profile_flds;
-					if (nmc->show_secrets)
+					if (nmc->nmc_config.show_secrets)
 						update_secrets_in_connection (NM_REMOTE_CONNECTION (con), con);
-					res = nmc_connection_profile_details (con, nmc, nmc->show_secrets);
+					res = nmc_connection_profile_details (con, nmc);
 					nmc->required_fields = NULL;
 					if (!res)
 						goto finish;
@@ -1940,7 +1864,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
 				}
 			}
 			new_line = TRUE;
-			
+
 			/* Take next argument.
 			 * But for pos != NULL we have more connections of the same name,
 			 * so process the same argument again.
@@ -2132,111 +2056,45 @@ typedef struct {
 
 static void activate_connection_info_finish (ActivateConnectionInfo *info);
 
-static const char *
-active_connection_state_reason_to_string (NMActiveConnectionStateReason reason)
-{
-	switch (reason) {
-	case NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN:
-		return _("Unknown reason");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_NONE:
-		return _("The connection was disconnected");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED:
-		return _("Disconnected by user");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED:
-		return _("The base network connection was interrupted");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED:
-		return _("The VPN service stopped unexpectedly");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID:
-		return _("The VPN service returned invalid configuration");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT:
-		return _("The connection attempt timed out");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT:
-		return _("The VPN service did not start in time");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED:
-		return _("The VPN service failed to start");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS:
-		return _("No valid secrets");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED:
-		return _("Invalid secrets");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED:
-		return _("The connection was removed");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED:
-		return _("Master connection failed");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED:
-		return _("Could not create a software link");
-	case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED:
-		return _("The device disappeared");
-	}
-
-	g_return_val_if_reached (_("Invalid reason"));
-}
-
 static void
 check_activated (ActivateConnectionInfo *info)
 {
-	NmCli *nmc = info->nmc;
-	NMDevice *device = info->device;
-	NMActiveConnection *active = info->active;
 	NMActiveConnectionState ac_state;
-	NMActiveConnectionStateReason ac_reason;
-	NMDeviceState dev_state;
-	NMDeviceStateReason dev_reason;
-
-	ac_state = nm_active_connection_get_state (active);
-	ac_reason = nm_active_connection_get_state_reason (active);
-
-	if (device) {
-		dev_state = nm_device_get_state (device);
-		dev_reason = nm_device_get_state_reason (device);
-	}
+	NmCli *nmc = info->nmc;
+	const char *reason = NULL;
 
-	if (ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
-		if (nmc->print_output == NMC_PRINT_PRETTY)
+	ac_state = nmc_activation_get_effective_state (info->active, info->device, &reason);
+	switch (ac_state) {
+	case NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
+		if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 			nmc_terminal_erase_line ();
-		g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
-		         nm_object_get_path (NM_OBJECT (active)));
-		activate_connection_info_finish (info);
-	} else if (ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
-		if (device && ac_reason == NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED) {
-			if (dev_state == NM_DEVICE_STATE_FAILED || dev_state == NM_DEVICE_STATE_DISCONNECTED) {
-				g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s"),
-				                 nmc_device_reason_to_string (dev_reason));
-				nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
-				activate_connection_info_finish (info);
-			} else {
-				/* Just wait for the device to go failed. We'll get a better error message. */
-				return;
-			}
+		if (reason) {
+			g_print (_("Connection successfully activated (%s) (D-Bus active path: %s)\n"),
+			         reason,
+			         nm_object_get_path (NM_OBJECT (info->active)));
 		} else {
-			g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s"),
-			                 active_connection_state_reason_to_string (ac_reason));
-			nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
-			activate_connection_info_finish (info);
+			g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
+			         nm_object_get_path (NM_OBJECT (info->active)));
 		}
-	} else if (ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING) {
-		/* activating master connection does not automatically activate any slaves, so their
-		 * active connection state will not progress beyond ACTIVATING state.
-		 * Monitor the device instead. */
-
+		activate_connection_info_finish (info);
+		break;
+	case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED:
+		nm_assert (reason);
+		g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s"),
+		                 reason);
+		nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
+		activate_connection_info_finish (info);
+		break;
+	case NM_ACTIVE_CONNECTION_STATE_ACTIVATING:
 		if (nmc->secret_agent) {
-			NMRemoteConnection *connection = nm_active_connection_get_connection (active);
+			NMRemoteConnection *connection = nm_active_connection_get_connection (info->active);
 
 			nm_secret_agent_simple_enable (NM_SECRET_AGENT_SIMPLE (nmc->secret_agent),
 			                               nm_connection_get_path (NM_CONNECTION (connection)));
 		}
-
-		if (   device
-		    && (   NM_IS_DEVICE_BOND (device)
-		        || NM_IS_DEVICE_TEAM (device)
-		        || NM_IS_DEVICE_BRIDGE (device))
-	            && dev_state >= NM_DEVICE_STATE_IP_CONFIG
-	            && dev_state <= NM_DEVICE_STATE_ACTIVATED) {
-			if (nmc->print_output == NMC_PRINT_PRETTY)
-				nmc_terminal_erase_line ();
-			g_print (_("Connection successfully activated (master waiting for slaves) (D-Bus active path: %s)\n"),
-			          nm_object_get_path (NM_OBJECT (active)));
-			activate_connection_info_finish (info);
-		}
+		break;
+	default:
+		break;
 	}
 }
 
@@ -2350,7 +2208,7 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
 		activate_connection_info_finish (info);
 	} else {
 		state = nm_active_connection_get_state (active);
-		if (!device) {
+		if (!device && !nm_active_connection_get_vpn (active)) {
 			/* device could be NULL for virtual devices. Fill it here. */
 			ac_devs = nm_active_connection_get_devices (active);
 			device = ac_devs->len > 0 ? g_ptr_array_index (ac_devs, 0) : NULL;
@@ -2361,7 +2219,7 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
 		if (nmc->nowait_flag || state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
 			/* User doesn't want to wait or already activated */
 			if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
-				if (nmc->print_output == NMC_PRINT_PRETTY)
+				if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 					nmc_terminal_erase_line ();
 				g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
 				         nm_object_get_path (NM_OBJECT (active)));
@@ -2380,7 +2238,7 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
 			check_activated (info);
 
 			/* Start progress indication showing VPN states */
-			if (nmc->print_output == NMC_PRINT_PRETTY) {
+			if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) {
 				if (progress_id)
 					g_source_remove (progress_id);
 				progress_id = g_timeout_add (120, progress_active_connection_cb, active);
@@ -2416,7 +2274,7 @@ parse_passwords (const char *passwd_file, GError **error)
 	char *pwd_spec, *pwd, *prop;
 	const char *setting;
 
-	pwds_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+	pwds_hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free);
 
 	if (!passwd_file)
 		return pwds_hash;
@@ -2539,10 +2397,6 @@ nmc_activate_connection (NmCli *nmc,
 		                  NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS,
 		                  G_CALLBACK (nmc_secrets_requested),
 		                  nmc);
-		if (connection) {
-			nm_secret_agent_simple_enable (NM_SECRET_AGENT_SIMPLE (nmc->secret_agent),
-			                               nm_object_get_path (NM_OBJECT (connection)));
-		}
 	}
 
 	info = g_malloc0 (sizeof (ActivateConnectionInfo));
@@ -2672,7 +2526,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
 	}
 
 	/* Start progress indication */
-	if (nmc->print_output == NMC_PRINT_PRETTY)
+	if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 		progress_id = g_timeout_add (120, progress_cb, _("preparing"));
 
 	return nmc->return_value;
@@ -2707,7 +2561,7 @@ down_active_connection_state_cb (NMActiveConnection *active,
 	if (nm_active_connection_get_state (active) < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
 		return;
 
-	if (info->nmc->print_output == NMC_PRINT_PRETTY)
+	if (info->nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 		nmc_terminal_erase_line ();
 	g_print (_("Connection '%s' successfully deactivated (D-Bus active path: %s)\n"),
 	         nm_active_connection_get_id (active), nm_object_get_path (NM_OBJECT (active)));
@@ -2896,254 +2750,29 @@ finish:
 	return nmc->return_value;
 }
 
-/*----------------------------------------------------------------------------*/
-
-typedef struct NameItem {
-	const char *name;
-	const char *alias;
-	const struct NameItem *settings;
-	gboolean mandatory;
-} NameItem;
-
-static const NameItem nmc_generic_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_ethernet_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet", NULL, TRUE  },
-	{ NM_SETTING_802_1X_SETTING_NAME,     NULL,       NULL, FALSE },
-	{ NM_SETTING_DCB_SETTING_NAME,        NULL,       NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_infiniband_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL, NULL, TRUE  },
-	{ NM_SETTING_INFINIBAND_SETTING_NAME, NULL, NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_wifi_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME,        NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,          "wifi",     NULL, TRUE  },
-	{ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, "wifi-sec", NULL, FALSE },
-	{ NM_SETTING_802_1X_SETTING_NAME,            NULL,       NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_wimax_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,   NULL, TRUE  },
-	{ NM_SETTING_WIMAX_SETTING_NAME,      NULL,   NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_gsm_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_GSM_SETTING_NAME,        NULL,       NULL, TRUE  },
-	{ NM_SETTING_SERIAL_SETTING_NAME,     NULL,       NULL, FALSE },
-	{ NM_SETTING_PPP_SETTING_NAME,        NULL,       NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_cdma_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_CDMA_SETTING_NAME,       NULL,       NULL, TRUE  },
-	{ NM_SETTING_SERIAL_SETTING_NAME,     NULL,       NULL, FALSE },
-	{ NM_SETTING_PPP_SETTING_NAME,        NULL,       NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_bluetooth_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,   NULL, TRUE  },
-	{ NM_SETTING_BLUETOOTH_SETTING_NAME,  NULL,   NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_adsl_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,   NULL, TRUE  },
-	{ NM_SETTING_ADSL_SETTING_NAME,       NULL,   NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-/* PPPoE is a base connection type from historical reasons.
- * See libnm-core/nm-setting.c:_nm_setting_is_base_type()
- */
-static const NameItem nmc_pppoe_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet", NULL, TRUE  },
-	{ NM_SETTING_PPPOE_SETTING_NAME,      NULL,       NULL, TRUE  },
-	{ NM_SETTING_PPP_SETTING_NAME,        NULL,       NULL, FALSE },
-	{ NM_SETTING_802_1X_SETTING_NAME,     NULL,       NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_olpc_mesh_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,        NULL, TRUE  },
-	{ NM_SETTING_OLPC_MESH_SETTING_NAME,  "olpc-mesh", NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_vpn_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,   NULL, TRUE  },
-	{ NM_SETTING_VPN_SETTING_NAME,        NULL,   NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_vlan_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet", NULL, FALSE },
-	{ NM_SETTING_VLAN_SETTING_NAME,       NULL,       NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_bond_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_BOND_SETTING_NAME,       NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet", NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_team_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_TEAM_SETTING_NAME,       NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet", NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_bridge_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,     NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet", NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_bond_slave_settings [] = {
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_team_slave_settings [] = {
-	{ NM_SETTING_TEAM_PORT_SETTING_NAME,  NULL,       NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_bridge_slave_settings [] = {
-	{ NM_SETTING_BRIDGE_PORT_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_no_slave_settings [] = {
-	{ NM_SETTING_IP4_CONFIG_SETTING_NAME, NULL,   NULL, FALSE },
-	{ NM_SETTING_IP6_CONFIG_SETTING_NAME, NULL,   NULL, FALSE },
-	{ NM_SETTING_PROXY_SETTING_NAME,      NULL,   NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_tun_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_TUN_SETTING_NAME,        NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet", NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_ip_tunnel_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_IP_TUNNEL_SETTING_NAME,  NULL,       NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_macsec_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet", NULL, FALSE },
-	{ NM_SETTING_802_1X_SETTING_NAME,     NULL,       NULL, FALSE },
-	{ NM_SETTING_MACSEC_SETTING_NAME,     NULL,       NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_macvlan_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME, NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet", NULL, FALSE },
-	{ NM_SETTING_MACVLAN_SETTING_NAME,    NULL,       NULL, TRUE  },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_vxlan_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME,  NULL,       NULL, TRUE  },
-	{ NM_SETTING_VXLAN_SETTING_NAME,       NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,       "ethernet", NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-static const NameItem nmc_dummy_settings [] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME,  NULL,       NULL, TRUE  },
-	{ NM_SETTING_DUMMY_SETTING_NAME,       NULL,       NULL, TRUE  },
-	{ NM_SETTING_WIRED_SETTING_NAME,       "ethernet", NULL, FALSE },
-	{ NULL, NULL, NULL, FALSE }
-};
-
-/* Available connection types */
-static const NameItem nmc_valid_connection_types[] = {
-	{ NM_SETTING_GENERIC_SETTING_NAME,    NULL,        nmc_generic_settings      }, /* Needs to be first. */
-	{ NM_SETTING_WIRED_SETTING_NAME,      "ethernet",  nmc_ethernet_settings     },
-	{ NM_SETTING_PPPOE_SETTING_NAME,      NULL,        nmc_pppoe_settings        },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,   "wifi",      nmc_wifi_settings         },
-	{ NM_SETTING_WIMAX_SETTING_NAME,      NULL,        nmc_wimax_settings        },
-	{ NM_SETTING_GSM_SETTING_NAME,        NULL,        nmc_gsm_settings          },
-	{ NM_SETTING_CDMA_SETTING_NAME,       NULL,        nmc_cdma_settings         },
-	{ NM_SETTING_INFINIBAND_SETTING_NAME, NULL,        nmc_infiniband_settings   },
-	{ NM_SETTING_ADSL_SETTING_NAME,       NULL,        nmc_adsl_settings         },
-	{ NM_SETTING_BLUETOOTH_SETTING_NAME,  NULL,        nmc_bluetooth_settings    },
-	{ NM_SETTING_VPN_SETTING_NAME,        NULL,        nmc_vpn_settings          },
-	{ NM_SETTING_OLPC_MESH_SETTING_NAME,  "olpc-mesh", nmc_olpc_mesh_settings    },
-	{ NM_SETTING_VLAN_SETTING_NAME,       NULL,        nmc_vlan_settings         },
-	{ NM_SETTING_BOND_SETTING_NAME,       NULL,        nmc_bond_settings         },
-	{ NM_SETTING_TEAM_SETTING_NAME,       NULL,        nmc_team_settings         },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,     NULL,        nmc_bridge_settings       },
-	{ "bond-slave",                       NULL,        nmc_bond_slave_settings   },
-	{ "team-slave",                       NULL,        nmc_team_slave_settings   },
-	{ "bridge-slave",                     NULL,        nmc_bridge_slave_settings },
-	{ "no-slave",                         NULL,        nmc_no_slave_settings     },
-	{ NM_SETTING_TUN_SETTING_NAME,        NULL,        nmc_tun_settings          },
-	{ NM_SETTING_IP_TUNNEL_SETTING_NAME,  NULL,        nmc_ip_tunnel_settings    },
-	{ NM_SETTING_MACSEC_SETTING_NAME,     NULL,        nmc_macsec_settings       },
-	{ NM_SETTING_MACVLAN_SETTING_NAME,    NULL,        nmc_macvlan_settings      },
-	{ NM_SETTING_VXLAN_SETTING_NAME,      NULL,        nmc_vxlan_settings        },
-	{ NM_SETTING_DUMMY_SETTING_NAME,      NULL,        nmc_dummy_settings        },
-	{ NULL, NULL, NULL }
-};
+/*****************************************************************************/
 
 /*
  * Return the most appropriate name for the connection of a type 'name' possibly with given 'slave_type'
  * if exists, else return the 'name'. The returned string must not be freed.
  */
 static const char *
-get_name_alias (const char *name, const char *slave_type, const NameItem array[])
+get_name_alias_toplevel (const char *name, const char *slave_type)
 {
-	const NameItem *iter = &array[0];
+	const NMMetaSettingInfoEditor *setting_info;
 
 	if (slave_type) {
-		while (iter && iter->name) {
-			if (   g_str_has_prefix (iter->name, slave_type)
-			    && g_str_has_suffix (iter->name, "-slave"))
-				break;
-			iter++;
-		}
-	} else if (name) {
-		while (iter && iter->name) {
-			if (!strcmp (name, iter->name))
-				break;
-			iter++;
-		}
-	} else
-		return NULL;
+		const char *slave_name;
 
-	if (iter) {
-		if (iter->alias)
-			return iter->alias;
-		else
-			return iter->name;
+		if (nm_meta_setting_info_valid_parts_for_slave_type (slave_type, &slave_name))
+			return slave_name ?: name;
+		return name;
 	}
 
+	setting_info = nm_meta_setting_info_editor_find_by_name (name, FALSE);
+	if (setting_info)
+		return setting_info->alias ?: setting_info->general->setting_name;
+
 	return name;
 }
 
@@ -3154,44 +2783,70 @@ get_name_alias (const char *name, const char *slave_type, const NameItem array[]
  * Returns: string; the caller is responsible for freeing it.
  */
 static char *
-get_valid_options_string (const NameItem *array, const NameItem *array_slv)
+get_valid_options_string (const NMMetaSettingValidPartItem *const*array, const NMMetaSettingValidPartItem *const*array_slv)
 {
-	const NameItem *iter = array;
+	const NMMetaSettingValidPartItem *const*iter = array;
 	GString *str;
 	int i;
 
 	str = g_string_sized_new (150);
 
 	for (i = 0; i < 2; i++, iter = array_slv) {
-		while (iter && iter->name) {
+		for (; iter && *iter; iter++) {
+			const NMMetaSettingInfoEditor *setting_info = (*iter)->setting_info;
+
 			if (str->len)
 				g_string_append (str, ", ");
-			if (iter->alias)
-				g_string_append_printf (str, "%s (%s)", iter->name, iter->alias);
+			if (setting_info->alias)
+				g_string_append_printf (str, "%s (%s)", setting_info->general->setting_name, setting_info->alias);
 			else
-				g_string_append (str, iter->name);
-			iter++;
+				g_string_append (str, setting_info->general->setting_name);
 		}
 	}
 	return g_string_free (str, FALSE);
 }
 
-static const NameItem *
+static char *
+get_valid_options_string_toplevel (void)
+{
+	GString *str;
+	int i;
+
+	str = g_string_sized_new (150);
+	for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+		const NMMetaSettingInfoEditor *setting_info = &nm_meta_setting_infos_editor[i];
+
+		if (!setting_info->valid_parts)
+			continue;
+
+		if (str->len)
+			g_string_append (str, ", ");
+		if (setting_info->alias)
+			g_string_append_printf (str, "%s (%s)", setting_info->general->setting_name, setting_info->alias);
+		else
+			g_string_append (str, setting_info->general->setting_name);
+	}
+
+	if (str->len)
+		g_string_append (str, ", ");
+	g_string_append (str, "bond-slave, bridge-slave, team-slave");
+
+	return g_string_free (str, FALSE);
+}
+
+static const NMMetaSettingValidPartItem *const*
 get_valid_settings_array (const char *con_type)
 {
-	guint i, num;
+	const NMMetaSettingInfoEditor *setting_info;
 
 	/* No connection type yet? Return settings for a generic connection
 	 * (just the "connection" setting), which always makes sense. */
 	if (!con_type)
-		return nmc_valid_connection_types[0].settings;
-
-	num = G_N_ELEMENTS (nmc_valid_connection_types);
-	for (i = 0; i < num; i++) {
-		if (nm_streq0 (con_type, nmc_valid_connection_types[i].name))
-			return nmc_valid_connection_types[i].settings;
-	}
+		return nm_meta_setting_info_valid_parts_default;
 
+	setting_info = nm_meta_setting_info_editor_find_by_name (con_type, FALSE);
+	if (setting_info)
+		return setting_info->valid_parts ?: NM_PTRARRAY_EMPTY (const NMMetaSettingValidPartItem *);
 	return NULL;
 }
 
@@ -3210,14 +2865,13 @@ get_valid_settings_array (const char *con_type)
  * Returns: list of property.arg elements
  */
 static char *
-get_valid_properties_string (const NameItem *array,
-                             const NameItem *array_slv,
+get_valid_properties_string (const NMMetaSettingValidPartItem *const*array,
+                             const NMMetaSettingValidPartItem *const*array_slv,
                              char modifier,
                              const char *prefix,
                              const char *postfix)
 {
-	const NameItem *iter = array;
-	const NmcOutputField *field_iter;
+	const NMMetaSettingValidPartItem *const*iter = array;
 	const char *prop_name = NULL;
 	GString *str;
 	int i, j;
@@ -3228,69 +2882,60 @@ get_valid_properties_string (const NameItem *array,
 	str = g_string_sized_new (1024);
 
 	for (i = 0; i < 2; i++, iter = array_slv) {
-		while (!full_match && iter && iter->name) {
-			if (   !(g_str_has_prefix (iter->name, prefix))
-			    && (!(iter->alias) || !g_str_has_prefix (iter->alias, prefix))) {
-				iter++;
+		for(; !full_match && iter && *iter; iter++) {
+			const NMMetaSettingInfoEditor *setting_info = (*iter)->setting_info;
+
+			if (   !(g_str_has_prefix (setting_info->general->setting_name, prefix))
+			    && (   !setting_info->alias
+			        || !g_str_has_prefix (setting_info->alias, prefix))) {
 				continue;
 			}
+
 			/* If postix (so prefix is terminated by a dot), check
 			 * that prefix is not ambiguous */
 			if (postfix) {
 				/* If we have a perfect match, no need to look for others
 				 * prefix and no check on ambiguity should be performed.
 				 * Moreover, erase previous matches from output string */
-				if (   nm_streq (prefix, iter->name)
-				    || nm_streq0 (prefix, iter->alias)) {
+				if (   nm_streq (prefix, setting_info->general->setting_name)
+				    || nm_streq0 (prefix, setting_info->alias)) {
 					g_string_erase (str, 0, -1);
 					full_match = TRUE;
-				} else if (prop_name) {
+				} else if (prop_name)
 					return g_string_free (str, TRUE);
-				}
 				prop_name = prefix;
-			} else {
-				prop_name = iter->name;
-			}
+			} else
+				prop_name = setting_info->general->setting_name;
 
 			/* Search the array with the arguments of the current property */
-			j = 0;
-			while (!nm_streq0 (iter->name, nmc_fields_settings_names[j].name)) {
-				g_assert (nmc_fields_settings_names[j].name);
-				j++;
-			}
-			field_iter = nmc_fields_settings_names[j].group;
-
-			j = 0;
-			while (field_iter[j].name) {
+			for (j = 0; j < setting_info->properties_num; j++) {
 				gchar *new;
-				const char *arg_name = field_iter[j].name;
+				const char *arg_name;
+
+				arg_name = setting_info->properties[j]->property_name;
 
 				/* If required, expand the alias too */
-				if (!postfix && iter->alias) {
+				if (!postfix && setting_info->alias) {
 					if (modifier)
 						g_string_append_c (str, modifier);
 					new = g_strdup_printf ("%s.%s\n",
-							       iter->alias,
-							       arg_name);
+					                       setting_info->alias,
+					                       arg_name);
 					g_string_append (str, new);
 					g_free (new);
 				}
 
-				if (postfix && !g_str_has_prefix (arg_name, postfix)) {
-					j++;
+				if (postfix && !g_str_has_prefix (arg_name, postfix))
 					continue;
-				}
 
 				if (modifier)
 					g_string_append_c (str, modifier);
 				new = g_strdup_printf ("%s.%s\n",
-						       prop_name,
-						       arg_name);
+				                       prop_name,
+				                       arg_name);
 				g_string_append (str, new);
 				g_free (new);
-				j++;
 			}
-			iter++;
 		}
 	}
 	return g_string_free (str, FALSE);
@@ -3306,9 +2951,9 @@ get_valid_properties_string (const NameItem *array,
  * The returned string must not be freed.
  */
 static const char *
-check_valid_name (const char *val, const NameItem *array, const NameItem *array_slv, GError **error)
+check_valid_name (const char *val, const NMMetaSettingValidPartItem *const*array, const NMMetaSettingValidPartItem *const*array_slv, GError **error)
 {
-	const NameItem *iter;
+	const NMMetaSettingValidPartItem *const*iter;
 	gs_unref_ptrarray GPtrArray *tmp_arr = NULL;
 	const char *str;
 	GError *tmp_err = NULL;
@@ -3320,11 +2965,12 @@ check_valid_name (const char *val, const NameItem *array, const NameItem *array_
 	tmp_arr = g_ptr_array_sized_new (32);
 	iter = array;
 	for (i = 0; i < 2; i++, iter = array_slv) {
-		while (iter && iter->name) {
-			g_ptr_array_add (tmp_arr, (gpointer) iter->name);
-			if (iter->alias)
-				g_ptr_array_add (tmp_arr, (gpointer) iter->alias);
-			iter++;
+		for (; iter && *iter; iter++) {
+			const NMMetaSettingInfoEditor *setting_info = (*iter)->setting_info;
+
+			g_ptr_array_add (tmp_arr, (gpointer) setting_info->general->setting_name);
+			if (setting_info->alias)
+				g_ptr_array_add (tmp_arr, (gpointer) setting_info->alias);
 		}
 	}
 	g_ptr_array_add (tmp_arr, (gpointer) NULL);
@@ -3336,10 +2982,10 @@ check_valid_name (const char *val, const NameItem *array, const NameItem *array_
 			g_propagate_error (error, tmp_err);
 		else {
 			/* We want to handle aliases, so construct own error message */
-			char *err_str = get_valid_options_string (array, array_slv);
+			gs_free char *err_str = NULL;
 
+			err_str = get_valid_options_string (array, array_slv);
 			g_set_error (error, 1, 0, _("'%s' not among [%s]"), val, err_str);
-			g_free (err_str);
 			g_clear_error (&tmp_err);
 		}
 		return NULL;
@@ -3348,12 +2994,13 @@ check_valid_name (const char *val, const NameItem *array, const NameItem *array_
 	/* Return a pointer to the found string in passed 'array' */
 	iter = array;
 	for (i = 0; i < 2; i++, iter = array_slv) {
-		while (iter && iter->name) {
-			if (   nm_streq (iter->name, str)
-			    || nm_streq0 (iter->alias, str)) {
-				return iter->name;
+		for (; iter && *iter; iter++) {
+			const NMMetaSettingInfoEditor *setting_info = (*iter)->setting_info;
+
+			if (   nm_streq (setting_info->general->setting_name, str)
+			    || nm_streq0 (setting_info->alias, str)) {
+				return setting_info->general->setting_name;
 			}
-			iter++;
 		}
 	}
 
@@ -3362,44 +3009,98 @@ check_valid_name (const char *val, const NameItem *array, const NameItem *array_
 	return NULL;
 }
 
+static const char *
+check_valid_name_toplevel (const char *val, const char **slave_type, GError **error)
+{
+	gs_unref_ptrarray GPtrArray *tmp_arr = NULL;
+	const char *str;
+	GError *tmp_err = NULL;
+	int i;
+	const NMMetaSettingInfoEditor *setting_info;
+
+	NM_SET_OUT (slave_type, NULL);
+
+	/* Create a temporary array that can be used in nmc_string_is_valid() */
+	tmp_arr = g_ptr_array_sized_new (32);
+	for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+		setting_info = &nm_meta_setting_infos_editor[i];
+		g_ptr_array_add (tmp_arr, (gpointer) setting_info->general->setting_name);
+		if (setting_info->alias)
+			g_ptr_array_add (tmp_arr, (gpointer) setting_info->alias);
+	}
+	g_ptr_array_add (tmp_arr, "bond-slave");
+	g_ptr_array_add (tmp_arr, "bridge-slave");
+	g_ptr_array_add (tmp_arr, "team-slave");
+	g_ptr_array_add (tmp_arr, (gpointer) NULL);
+
+	/* Check string validity */
+	str = nmc_string_is_valid (val, (const char **) tmp_arr->pdata, &tmp_err);
+	if (!str) {
+		if (tmp_err->code == 1)
+			g_propagate_error (error, tmp_err);
+		else {
+			/* We want to handle aliases, so construct own error message */
+			char *err_str = get_valid_options_string_toplevel ();
+
+			g_set_error (error, 1, 0, _("'%s' not among [%s]"), val, err_str);
+			g_free (err_str);
+			g_clear_error (&tmp_err);
+		}
+		return NULL;
+	}
+
+	if (nm_streq (str, "bond-slave")) {
+		NM_SET_OUT (slave_type, NM_SETTING_BOND_SETTING_NAME);
+		return NM_SETTING_WIRED_SETTING_NAME;
+	} else if (nm_streq (str, "bridge-slave")) {
+		NM_SET_OUT (slave_type, NM_SETTING_BRIDGE_SETTING_NAME);
+		return NM_SETTING_WIRED_SETTING_NAME;
+	} else if (nm_streq (str, "team-slave")) {
+		NM_SET_OUT (slave_type, NM_SETTING_TEAM_SETTING_NAME);
+		return NM_SETTING_WIRED_SETTING_NAME;
+	}
+
+	setting_info = nm_meta_setting_info_editor_find_by_name (str, TRUE);
+	if (setting_info)
+		return setting_info->general->setting_name;
+
+	/* We should not really come here */
+	g_set_error (error, 1, 0, _("Unknown error"));
+	return NULL;
+}
+
 static gboolean
 is_setting_mandatory (NMConnection *connection, NMSetting *setting)
 {
 	NMSettingConnection *s_con;
 	const char *c_type;
-	const NameItem *item;
+	const NMMetaSettingValidPartItem *const*item;
 	const char *name;
 	const char *s_type;
-	char *slv_type;
+	guint i;
 
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	c_type = nm_setting_connection_get_connection_type (s_con);
+	s_type = nm_setting_connection_get_slave_type (s_con);
 
 	name = nm_setting_get_name (setting);
 
-	item = get_valid_settings_array (c_type);
-	while (item && item->name) {
-		if (!strcmp (name, item->name))
-			return item->mandatory;
-		item++;
-	}
-
-	/* Let's give a try to parameters related to slave type */
-	s_type = nm_setting_connection_get_slave_type (s_con);
-	slv_type = g_strdup_printf ("%s-slave", s_type ? s_type : "no");
-	item = get_valid_settings_array (slv_type);
-	g_free (slv_type);
-	while (item && item->name) {
-		if (!strcmp (name, item->name))
-			return item->mandatory;
-		item++;
+	for (i = 0; i < 2; i++) {
+		if (i == 0)
+			item = get_valid_settings_array (c_type);
+		else
+			item = nm_meta_setting_info_valid_parts_for_slave_type (s_type, NULL);
+		for (; item && *item; item++) {
+			if (!strcmp (name, (*item)->setting_info->general->setting_name))
+				return (*item)->mandatory;
+		}
 	}
 
 	return FALSE;
 }
 
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
 
 static const char *
 _strip_master_prefix (const char *master, const char *(**func)(NMConnection *))
@@ -3509,8 +3210,6 @@ normalized_master_for_slave (const GPtrArray *connections,
 
 #define WORD_YES "yes"
 #define WORD_NO  "no"
-#define WORD_LOC_YES _("yes")
-#define WORD_LOC_NO  _("no")
 static const char *
 prompt_yes_no (gboolean default_yes, char *delim)
 {
@@ -3520,14 +3219,14 @@ prompt_yes_no (gboolean default_yes, char *delim)
 		delim = "";
 
 	snprintf (prompt, sizeof (prompt), "(%s/%s) [%s]%s ",
-	          WORD_LOC_YES, WORD_LOC_NO,
-	          default_yes ? WORD_LOC_YES : WORD_LOC_NO, delim);
+	          WORD_YES, WORD_NO,
+	          default_yes ? WORD_YES : WORD_NO, delim);
 
 	return prompt;
 }
 
 static NMSetting *
-is_setting_valid (NMConnection *connection, const NameItem *valid_settings_main, const NameItem *valid_settings_slave, char *setting)
+is_setting_valid (NMConnection *connection, const NMMetaSettingValidPartItem *const*valid_settings_main, const NMMetaSettingValidPartItem *const*valid_settings_slave, char *setting)
 {
 	const char *setting_name;
 
@@ -3600,9 +3299,94 @@ set_default_interface_name (NmCli *nmc, NMSettingConnection *s_con)
 	g_free (ifname);
 }
 
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
 
-static OptionInfo option_info[];
+static PropertyInfFlags
+_dynamic_options_set (const NMMetaAbstractInfo *abstract_info,
+                      PropertyInfFlags mask, PropertyInfFlags set)
+{
+	static GHashTable *cache = NULL;
+	gpointer p;
+	PropertyInfFlags v, v2;
+
+	if (G_UNLIKELY (!cache))
+		cache = g_hash_table_new (NULL, NULL);
+
+	if (g_hash_table_lookup_extended (cache, (gpointer) abstract_info, NULL, &p))
+		v = GPOINTER_TO_UINT (p);
+	else
+		v = 0;
+
+	v2 = (v & ~mask) | (mask & set);
+	if (v != v2)
+		g_hash_table_insert (cache, (gpointer) abstract_info, GUINT_TO_POINTER (v2));
+
+	return v2;
+}
+
+static PropertyInfFlags
+_dynamic_options_get (const NMMetaAbstractInfo *abstract_info)
+{
+	return _dynamic_options_set (abstract_info, 0, 0);
+}
+
+/*****************************************************************************/
+
+static gboolean
+_meta_property_needs_bond_hack (const NMMetaPropertyInfo *property_info)
+{
+	/* hack: the bond property data is handled special and not generically.
+	 * Eventually, get rid of explicitly checking whether we handle a bond. */
+	if (!property_info)
+		g_return_val_if_reached (FALSE);
+	return    property_info->property_typ_data
+	       && property_info->property_typ_data->nested == &nm_meta_property_typ_data_bond;
+
+}
+
+static char **
+_meta_abstract_complete (const NMMetaAbstractInfo *abstract_info, const char *text)
+{
+	const char *const*values;
+	char **values_to_free = NULL;
+	const NMMetaOperationContext ctx = {
+		.connection = nmc_tab_completion.connection,
+	};
+
+	values = nm_meta_abstract_info_complete (abstract_info,
+	                                         nmc_meta_environment,
+	                                         nmc_meta_environment_arg,
+	                                         &ctx,
+	                                         text,
+	                                         &values_to_free);
+	if (values)
+		return values_to_free ?: g_strdupv ((char **) values);
+	return NULL;
+}
+
+static void
+_meta_abstract_get (const NMMetaAbstractInfo *abstract_info,
+                    const NMMetaSettingInfoEditor **out_setting_info,
+                    const char **out_setting_name,
+                    const char **out_property_name,
+                    const char **out_option,
+                    NMMetaPropertyInfFlags *out_inf_flags,
+                    const char **out_prompt,
+                    const char **out_def_hint)
+{
+	const NMMetaPropertyInfo *info = (const NMMetaPropertyInfo *) abstract_info;
+
+	NM_SET_OUT (out_option, info->property_alias);
+	NM_SET_OUT (out_setting_info, info->setting_info);
+	NM_SET_OUT (out_setting_name, info->setting_info->general->setting_name);
+	NM_SET_OUT (out_property_name, info->property_name);
+	NM_SET_OUT (out_option, info->property_alias);
+	NM_SET_OUT (out_inf_flags, info->inf_flags);
+	NM_SET_OUT (out_prompt, info->prompt);
+	NM_SET_OUT (out_def_hint, info->def_hint);
+}
+
+static const OptionInfo *_meta_abstract_get_option_info (const NMMetaAbstractInfo *abstract_info);
 
 /*
  * Mark options in option_info as relevant.
@@ -3611,17 +3395,34 @@ static OptionInfo option_info[];
 static void
 enable_options (const gchar *setting_name, const gchar *property, const gchar * const *opts)
 {
-	OptionInfo *candidate;
+	const NMMetaPropertyInfo *property_info;
+
+	property_info = nm_meta_property_info_find_by_name (setting_name, property);
+
+	if (!property_info)
+		g_return_if_reached ();
+
+	if (_meta_property_needs_bond_hack (property_info)) {
+		guint i;
+
+		for (i = 0; i < nm_meta_property_typ_data_bond.nested_len; i++) {
+			const NMMetaNestedPropertyInfo *bi = &nm_meta_property_typ_data_bond.nested[i];
 
-	for (candidate = option_info; candidate->setting_name; candidate++) {
-		if (   strcmp (candidate->setting_name, setting_name) == 0
-		    && strcmp (candidate->property, property) == 0
-		    && (candidate->flags & OPTION_DONT_ASK)
-		    && candidate->option
-		    && g_strv_contains (opts, candidate->option)) {
-			candidate->flags |= OPTION_ENABLED;
+			if (   bi->base.inf_flags & NM_META_PROPERTY_INF_FLAG_DONT_ASK
+			    && bi->base.property_alias
+			    && g_strv_contains (opts, bi->base.property_alias))
+				_dynamic_options_set ((const NMMetaAbstractInfo *) bi, PROPERTY_INF_FLAG_ENABLED, PROPERTY_INF_FLAG_ENABLED);
 		}
+		return;
 	}
+
+	if (!property_info->is_cli_option)
+		g_return_if_reached ();
+
+	if (   property_info->inf_flags & NM_META_PROPERTY_INF_FLAG_DONT_ASK
+	    && property_info->property_alias
+	    && g_strv_contains (opts, property_info->property_alias))
+		_dynamic_options_set ((const NMMetaAbstractInfo *) property_info, PROPERTY_INF_FLAG_ENABLED, PROPERTY_INF_FLAG_ENABLED);
 }
 
 /*
@@ -3632,12 +3433,49 @@ enable_options (const gchar *setting_name, const gchar *property, const gchar *
 static void
 disable_options (const gchar *setting_name, const gchar *property)
 {
-	OptionInfo *candidate;
+	const NMMetaPropertyInfo *property_infos_local[2];
+	const NMMetaPropertyInfo *const*property_infos;
+	guint p;
+
+	if (property) {
+		const NMMetaPropertyInfo *pi;
+
+		pi = nm_meta_property_info_find_by_name (setting_name, property);
+		if (!pi)
+			g_return_if_reached ();
+		if (   !_meta_property_needs_bond_hack (pi)
+		    && !pi->is_cli_option)
+			return;
+		property_infos_local[0] = pi;
+		property_infos_local[1] = NULL;
+		property_infos = property_infos_local;
+	} else {
+		const NMMetaSettingInfoEditor *setting_info;
+
+		setting_info = nm_meta_setting_info_editor_find_by_name (setting_name, FALSE);
+		if (!setting_info)
+			g_return_if_reached ();
+		property_infos = setting_info->properties;
+		if (!property_infos)
+			return;
+	}
 
-	for (candidate = option_info; candidate->setting_name; candidate++) {
-		if (   strcmp (candidate->setting_name, setting_name) == 0
-		    && (!property || strcmp (candidate->property, property) == 0))
-		candidate->flags |= OPTION_DISABLED;
+	for (p = 0; property_infos[p]; p++) {
+		const NMMetaPropertyInfo *property_info = property_infos[p];
+
+		if (_meta_property_needs_bond_hack (property_info)) {
+			guint i;
+
+			for (i = 0; i < nm_meta_property_typ_data_bond.nested_len; i++) {
+				const NMMetaNestedPropertyInfo *bi = &nm_meta_property_typ_data_bond.nested[i];
+
+				_dynamic_options_set ((const NMMetaAbstractInfo *) bi, PROPERTY_INF_FLAG_DISABLED, PROPERTY_INF_FLAG_DISABLED);
+			}
+			nm_assert (p == 0 && !property_infos[1]);
+		} else {
+			if (property_info->is_cli_option)
+				_dynamic_options_set ((const NMMetaAbstractInfo *) property_info, PROPERTY_INF_FLAG_DISABLED, PROPERTY_INF_FLAG_DISABLED);
+		}
 	}
 }
 
@@ -3649,11 +3487,31 @@ disable_options (const gchar *setting_name, const gchar *property)
 static void
 reset_options (void)
 {
-	OptionInfo *candidate;
+	NMMetaSettingType s;
+
+	for (s = 0; s < _NM_META_SETTING_TYPE_NUM; s++) {
+		const NMMetaPropertyInfo *const*property_infos;
+		guint p;
+
+		property_infos = nm_meta_setting_infos_editor[s].properties;
+		if (!property_infos)
+			continue;
+		for (p = 0; property_infos[p]; p++) {
+			const NMMetaPropertyInfo *property_info = property_infos[p];
+
+			if (_meta_property_needs_bond_hack (property_info)) {
+				guint i;
+
+				for (i = 0; i < nm_meta_property_typ_data_bond.nested_len; i++) {
+					const NMMetaNestedPropertyInfo *bi = &nm_meta_property_typ_data_bond.nested[i];
 
-	for (candidate = option_info; candidate->setting_name; candidate++) {
-		candidate->flags &= ~OPTION_DISABLED;
-		candidate->flags &= ~OPTION_ENABLED;
+					_dynamic_options_set ((const NMMetaAbstractInfo *) bi, PROPERTY_INF_FLAG_ALL, 0);
+				}
+			} else {
+				if (property_info->is_cli_option)
+					_dynamic_options_set ((const NMMetaAbstractInfo *) property_info, PROPERTY_INF_FLAG_ALL, 0);
+			}
+		}
 	}
 }
 
@@ -3666,17 +3524,12 @@ set_property (NMConnection *connection,
 	NMSetting *setting;
 	GError *local = NULL;
 
+	g_assert (setting_name && setting_name[0]);
+
 	setting = nm_connection_get_setting_by_name (connection, setting_name);
 	if (!setting) {
-		setting = nmc_setting_new_for_name (setting_name);
-		if (!setting) {
-			/* This should really not happen */
-			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_UNKNOWN,
-			             _("Error: don't know how to create '%s' setting."),
-			             setting_name);
-			return FALSE;
-		}
-		nmc_setting_custom_init (setting);
+		setting = nm_meta_setting_info_editor_new_setting (nm_meta_setting_info_editor_find_by_name (setting_name, FALSE),
+		                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
 		nm_connection_add_setting (connection, setting);
 	}
 
@@ -3735,17 +3588,25 @@ set_property (NMConnection *connection,
 }
 
 static gboolean
-set_option (NmCli *nmc, NMConnection *connection, OptionInfo *option, const gchar *value, GError **error)
+set_option (NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abstract_info, const gchar *value, GError **error)
 {
-	option->flags |= OPTION_DISABLED;
-	if (option->check_and_set) {
+	const char *setting_name, *property_name, *option_name;
+	NMMetaPropertyInfFlags inf_flags;
+	const OptionInfo *option;
+
+	option = _meta_abstract_get_option_info (abstract_info);
+
+	_dynamic_options_set (abstract_info, PROPERTY_INF_FLAG_DISABLED, PROPERTY_INF_FLAG_DISABLED);
+
+	_meta_abstract_get (abstract_info, NULL, &setting_name, &property_name, &option_name, &inf_flags, NULL, NULL);
+	if (option && option->check_and_set) {
 		return option->check_and_set (nmc, connection, option, value, error);
 	} else if (value) {
-		return set_property (connection, option->setting_name, option->property,
-		                     value, option->flags & OPTION_MULTI ? '+' : '\0', error);
-	} else if (option->flags & OPTION_REQD) {
+		return set_property (connection, setting_name, property_name,
+		                     value, inf_flags & NM_META_PROPERTY_INF_FLAG_MULTI ? '+' : '\0', error);
+	} else if (inf_flags & NM_META_PROPERTY_INF_FLAG_REQD) {
 		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-	                     _("Error: '%s' is mandatory."), option->option);
+	                     _("Error: '%s' is mandatory."), option_name);
 		return FALSE;
 	}
 
@@ -3757,10 +3618,9 @@ set_option (NmCli *nmc, NMConnection *connection, OptionInfo *option, const gcha
  * and slave type.
  */
 static gboolean
-con_settings (NMConnection *connection, const NameItem **type_settings, const NameItem **slv_settings, GError **error)
+con_settings (NMConnection *connection, const NMMetaSettingValidPartItem *const**type_settings, const NMMetaSettingValidPartItem *const**slv_settings, GError **error)
 {
 	const char *con_type;
-	gs_free char *slv_type = NULL;
 	NMSettingConnection *s_con;
 
 	g_return_val_if_fail (type_settings, FALSE);
@@ -3770,23 +3630,14 @@ con_settings (NMConnection *connection, const NameItem **type_settings, const Na
 	g_assert (s_con);
 
 	con_type = nm_setting_connection_get_slave_type (s_con);
-	if (!con_type)
-		con_type = "no";
-	slv_type = g_strdup_printf ("%s-slave", con_type);
-	if (slv_type) {
-		*slv_settings = get_valid_settings_array (slv_type);
-		if (!*slv_settings) {
-			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("Error: invalid slave type; %s."), slv_type);
-			return FALSE;
-		}
-	} else {
-		*slv_settings = NULL;
+	*slv_settings = nm_meta_setting_info_valid_parts_for_slave_type (con_type, NULL);
+	if (!*slv_settings) {
+		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
+		             _("Error: invalid slave type; %s."), con_type);
+		return FALSE;
 	}
 
 	con_type = nm_setting_connection_get_connection_type (s_con);
-	if (!con_type)
-		con_type = NM_SETTING_GENERIC_SETTING_NAME;
 	*type_settings = get_valid_settings_array (con_type);
 	if (!*type_settings) {
 		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
@@ -3802,67 +3653,34 @@ con_settings (NMConnection *connection, const NameItem **type_settings, const Na
  * it's possible that a type is aready set).
  */
 static void
-ensure_settings (NMConnection *connection, const NameItem *item)
+ensure_settings (NMConnection *connection, const NMMetaSettingValidPartItem *const*item)
 {
-	const NameItem *setting_item;
 	NMSetting *setting;
 
-	for (setting_item = item; setting_item->name; setting_item++) {
-		if (!setting_item->mandatory)
+	for (; item && *item; item++) {
+		if (!(*item)->mandatory)
 			continue;
-		if (nm_connection_get_setting_by_name (connection, setting_item->name))
+		if (nm_connection_get_setting_by_name (connection, (*item)->setting_info->general->setting_name))
 			continue;
-		setting = nmc_setting_new_for_name (setting_item->name);
-		if (setting) {
-			nmc_setting_custom_init (setting);
-			nm_connection_add_setting (connection, setting);
-		}
+		setting = nm_meta_setting_info_editor_new_setting ((*item)->setting_info,
+		                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
+		nm_connection_add_setting (connection, setting);
 	}
 }
 
-/*----------------------------------------------------------------------------*/
-
-static char *
-gen_func_slave_type (const char *text, int state)
-{
-	const char *words[] = { "bond", "team", "bridge", NULL };
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_vpn_types (const char *text, int state)
-{
-	gs_strfreev char **plugin_names = NULL;
-
-	plugin_names = nm_vpn_plugin_info_list_get_service_types (nm_vpn_get_plugin_infos (), FALSE, TRUE);
-	return nmc_rl_gen_func_basic (text, state, (const char **) plugin_names);
-}
+/*****************************************************************************/
 
 static char *
 gen_func_bool_values_l10n (const char *text, int state)
 {
-	const char *words[] = { WORD_LOC_YES, WORD_LOC_NO, NULL };
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_wifi_mode (const char *text, int state)
-{
-	const char *words[] = { "infrastructure", "ap", "adhoc", NULL };
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_ib_type (const char *text, int state)
-{
-	const char *words[] = { "datagram", "connected", NULL };
+	const char *words[] = { WORD_YES, WORD_NO, NULL };
 	return nmc_rl_gen_func_basic (text, state, words);
 }
 
 static char *
 gen_func_bt_type (const char *text, int state)
 {
-	const char *words[] = { "panu", "dun-gsm", "dun-cdma", NULL };
+	const char *words[] = { "panu", "nap", "dun-gsm", "dun-cdma", NULL };
 	return nmc_rl_gen_func_basic (text, state, words);
 }
 
@@ -3886,144 +3704,28 @@ gen_func_bond_lacp_rate (const char *text, int state)
 	return nmc_rl_gen_func_basic (text, state, words);
 }
 
-static char *
-gen_func_adsl_proto (const char *text, int state)
-{
-	const char *words[] = { "pppoe", "pppoa", "ipoatm", NULL };
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_adsl_encap (const char *text, int state)
-{
-	const char *words[] = { "vcmux", "llc", NULL };
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_tun_mode (const char *text, int state)
-{
-	const char *words[] = { "tun", "tap", NULL };
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_ip_tunnel_mode (const char *text, int state)
-{
-	gs_free const char **words = NULL;
-
-	words = nm_utils_enum_get_values (nm_ip_tunnel_mode_get_type (),
-	                                  NM_IP_TUNNEL_MODE_UNKNOWN + 1,
-	                                  G_MAXINT);
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_macsec_mode (const char *text, int state)
-{
-	gs_free const char **words = NULL;
-
-	words = nm_utils_enum_get_values (nm_setting_macsec_mode_get_type (),
-	                                  G_MININT,
-	                                  G_MAXINT);
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_macvlan_mode (const char *text, int state)
-{
-	gs_free const char **words = NULL;
-
-	words = nm_utils_enum_get_values (nm_setting_macvlan_mode_get_type(),
-	                                  NM_SETTING_MACVLAN_MODE_UNKNOWN + 1,
-	                                  G_MAXINT);
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_proxy_method (const char *text, int state)
-{
-	gs_free const char **words = NULL;
-
-	words = nm_utils_enum_get_values (nm_setting_proxy_method_get_type (),
-	                                  G_MININT,
-	                                  G_MAXINT);
-	return nmc_rl_gen_func_basic (text, state, words);
-}
-
-static char *
-gen_func_master_ifnames (const char *text, int state)
-{
-	int i;
-	GPtrArray *ifnames;
-	char *ret;
-	NMConnection *con;
-	NMSettingConnection *s_con;
-	const char *con_type, *ifname;
-	const GPtrArray *connections;
-
-	connections = nm_client_get_connections (nm_cli.client);
-
-	/* Disable appending space after completion */
-	rl_completion_append_character = '\0';
-
-	ifnames = g_ptr_array_sized_new (20);
-	for (i = 0; i < connections->len; i++) {
-		con = NM_CONNECTION (connections->pdata[i]);
-		s_con = nm_connection_get_setting_connection (con);
-		g_assert (s_con);
-		con_type = nm_setting_connection_get_connection_type (s_con);
-		if (g_strcmp0 (con_type, nmc_tab_completion.con_type) != 0)
-			continue;
-		ifname = nm_connection_get_interface_name (con);
-		g_ptr_array_add (ifnames, (gpointer) ifname);
-	}
-	g_ptr_array_add (ifnames, (gpointer) NULL);
-
-	ret = nmc_rl_gen_func_basic (text, state, (const char **) ifnames->pdata);
-
-	g_ptr_array_free (ifnames, TRUE);
-	return ret;
-}
-
-
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
 
 static gboolean
-set_connection_type (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *value, GError **error)
+set_connection_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error)
 {
-	const NameItem *type_settings, *slv_settings;
+	const NMMetaSettingValidPartItem *const*type_settings;
+	const NMMetaSettingValidPartItem *const*slv_settings;
 	GError *local = NULL;
 	const gchar *master[] = { "master", NULL };
+	const char *slave_type = NULL;
 
-	value = check_valid_name (value, nmc_valid_connection_types, NULL, &local);
+	value = check_valid_name_toplevel (value, &slave_type, &local);
 	if (!value) {
 		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-		             _("Error: bad connection type: %s."), local->message);
+		             _("Error: bad connection type: %s"), local->message);
 		g_clear_error (&local);
 		return FALSE;
 	}
 
-	if (g_strcmp0 (value, "bond-slave") == 0) {
-		value = NM_SETTING_WIRED_SETTING_NAME;
-		if (!set_property (con, NM_SETTING_CONNECTION_SETTING_NAME,
-		                   NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BOND_SETTING_NAME,
-		                   '\0', error)) {
-			return FALSE;
-		}
-		enable_options (NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_MASTER, master);
-	} else if (g_strcmp0 (value, "bridge-slave") == 0) {
-		value = NM_SETTING_WIRED_SETTING_NAME;
-		if (!set_property (con, NM_SETTING_CONNECTION_SETTING_NAME,
-		                   NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BRIDGE_SETTING_NAME,
-		                   '\0', error)) {
-			return FALSE;
-		}
-		enable_options (NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_MASTER, master);
-	} else if (g_strcmp0 (value, "team-slave") == 0) {
-		value = NM_SETTING_WIRED_SETTING_NAME;
+	if (slave_type) {
 		if (!set_property (con, NM_SETTING_CONNECTION_SETTING_NAME,
-		                   NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_TEAM_SETTING_NAME,
+		                   NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type,
 		                   '\0', error)) {
 			return FALSE;
 		}
@@ -4039,7 +3741,7 @@ set_connection_type (NmCli *nmc, NMConnection *con, OptionInfo *option, const ch
 		                 NM_SETTING_CONNECTION_INTERFACE_NAME);
 	}
 
-	if (!set_property (con, option->setting_name, option->property, value, '\0', error))
+	if (!set_property (con, option->setting_info->general->setting_name, option->property, value, '\0', error))
 		return FALSE;
 
 	if (!con_settings (con, &type_settings, &slv_settings, error))
@@ -4052,7 +3754,7 @@ set_connection_type (NmCli *nmc, NMConnection *con, OptionInfo *option, const ch
 }
 
 static gboolean
-set_connection_iface (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *value, GError **error)
+set_connection_iface (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error)
 {
 	GError *tmp_error = NULL;
 
@@ -4068,11 +3770,11 @@ set_connection_iface (NmCli *nmc, NMConnection *con, OptionInfo *option, const c
 		}
 	}
 
-	return set_property (con, option->setting_name, option->property, value, '\0', error);
+	return set_property (con, option->setting_info->general->setting_name, option->property, value, '\0', error);
 }
 
 static gboolean
-set_connection_master (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *value, GError **error)
+set_connection_master (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error)
 {
 	const GPtrArray *connections;
 	NMSettingConnection *s_con;
@@ -4097,11 +3799,11 @@ set_connection_master (NmCli *nmc, NMConnection *con, OptionInfo *option, const
 		return FALSE;
 	}
 
-	return set_property (con, option->setting_name, option->property, value, '\0', error);
+	return set_property (con, option->setting_info->general->setting_name, option->property, value, '\0', error);
 }
 
 static gboolean
-set_bond_option (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *value, GError **error)
+set_bond_option (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error)
 {
 	NMSettingBond *s_bond;
 	gboolean success;
@@ -4150,7 +3852,7 @@ set_bond_option (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *
 }
 
 static gboolean
-set_bond_monitoring_mode (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *value, GError **error)
+set_bond_monitoring_mode (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error)
 {
 	NMSettingBond *s_bond;
 	gs_free gchar *monitor_mode = NULL;
@@ -4164,17 +3866,17 @@ set_bond_monitoring_mode (NmCli *nmc, NMConnection *con, OptionInfo *option, con
 		monitor_mode = g_strdup (value);
 		g_strstrip (monitor_mode);
 	} else {
-		monitor_mode = g_strdup (WORD_MIIMON);
+		monitor_mode = g_strdup (NM_META_TEXT_WORD_MIIMON);
 	}
 
-	if (matches (monitor_mode, WORD_MIIMON))
+	if (matches (monitor_mode, NM_META_TEXT_WORD_MIIMON))
 		enable_options (NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS, miimon_opts);
-	else if (matches (monitor_mode, WORD_ARP))
+	else if (matches (monitor_mode, NM_META_TEXT_WORD_ARP))
 		enable_options (NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS, arp_opts);
 	else {
 		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
 		             _("Error: '%s' is not a valid monitoring mode; use '%s' or '%s'.\n"),
-		             monitor_mode, WORD_MIIMON, WORD_ARP);
+		             monitor_mode, NM_META_TEXT_WORD_MIIMON, NM_META_TEXT_WORD_ARP);
 		return FALSE;
 	}
 
@@ -4182,7 +3884,7 @@ set_bond_monitoring_mode (NmCli *nmc, NMConnection *con, OptionInfo *option, con
 }
 
 static gboolean
-set_bluetooth_type (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *value, GError **error)
+set_bluetooth_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error)
 {
 	NMSetting *setting;
 
@@ -4193,39 +3895,29 @@ set_bluetooth_type (NmCli *nmc, NMConnection *con, OptionInfo *option, const cha
 	if (   !strcmp (value, NM_SETTING_BLUETOOTH_TYPE_DUN)
 	    || !strcmp (value, NM_SETTING_BLUETOOTH_TYPE_DUN"-gsm")) {
 		value = NM_SETTING_BLUETOOTH_TYPE_DUN;
-		setting = nm_setting_gsm_new ();
-		nmc_setting_custom_init (setting);
+		setting = nm_meta_setting_info_editor_new_setting (&nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_GSM],
+		                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
 		nm_connection_add_setting (con, setting);
 	} else if (!strcmp (value, NM_SETTING_BLUETOOTH_TYPE_DUN"-cdma")) {
 		value = NM_SETTING_BLUETOOTH_TYPE_DUN;
 		setting = nm_setting_cdma_new ();
 		nm_connection_add_setting (con, setting);
-	} else if (!strcmp (value, NM_SETTING_BLUETOOTH_TYPE_PANU)) {
+	} else if (!strcmp (value, NM_SETTING_BLUETOOTH_TYPE_PANU) || !strcmp (value, NM_SETTING_BLUETOOTH_TYPE_NAP)) {
 		/* no op */
 	} else {
 		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-		             _("Error: 'bt-type': '%s' not valid; use [%s, %s (%s), %s]."),
-		             value, NM_SETTING_BLUETOOTH_TYPE_PANU, NM_SETTING_BLUETOOTH_TYPE_DUN,
-		             NM_SETTING_BLUETOOTH_TYPE_DUN"-gsm", NM_SETTING_BLUETOOTH_TYPE_DUN"-cdma");
+		             _("Error: 'bt-type': '%s' not valid; use [%s, %s, %s (%s), %s]."),
+		             value, NM_SETTING_BLUETOOTH_TYPE_PANU, NM_SETTING_BLUETOOTH_TYPE_NAP,
+		             NM_SETTING_BLUETOOTH_TYPE_DUN, NM_SETTING_BLUETOOTH_TYPE_DUN"-gsm",
+		             NM_SETTING_BLUETOOTH_TYPE_DUN"-cdma");
 		return FALSE;
 	}
 
-	return set_property (con, option->setting_name, option->property, value, '\0', error);
-}
-
-static gboolean
-set_yes_no (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *value, GError **error)
-{
-	if (g_strcmp0 (value, _(WORD_LOC_YES)))
-		value = WORD_YES;
-	if (g_strcmp0 (value, _(WORD_LOC_NO)))
-		value = WORD_NO;
-
-	return set_property (con, option->setting_name, option->property, value, '\0', error);
+	return set_property (con, option->setting_info->general->setting_name, option->property, value, '\0', error);
 }
 
 static gboolean
-set_ip4_address (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *value, GError **error)
+set_ip4_address (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error)
 {
 	NMSettingIPConfig *s_ip4;
 
@@ -4240,12 +3932,12 @@ set_ip4_address (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *
 		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
 		              NULL);
 	}
-	return set_property (con, option->setting_name, option->property, value,
-	                     option->flags & OPTION_MULTI ? '+' : '\0', error);
+	return set_property (con, option->setting_info->general->setting_name, option->property, value,
+	                     '+', error);
 }
 
 static gboolean
-set_ip6_address (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *value, GError **error)
+set_ip6_address (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error)
 {
 	NMSettingIPConfig *s_ip6;
 
@@ -4260,187 +3952,97 @@ set_ip6_address (NmCli *nmc, NMConnection *con, OptionInfo *option, const char *
 		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
 		              NULL);
 	}
-	return set_property (con, option->setting_name, option->property, value,
-	                     option->flags & OPTION_MULTI ? '+' : '\0', error);
-}
-
-
-/*----------------------------------------------------------------------------*/
-
-static OptionInfo option_info[] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME,   NM_SETTING_CONNECTION_TYPE,             "type",         OPTION_REQD, PROMPT_CON_TYPE, NULL,
-                                                                                                        set_connection_type, gen_connection_types },
-	{ NM_SETTING_CONNECTION_SETTING_NAME,   NM_SETTING_CONNECTION_ID,               "con-name",     OPTION_DONT_ASK, NULL, NULL, NULL, NULL },
-	{ NM_SETTING_CONNECTION_SETTING_NAME,   NM_SETTING_CONNECTION_AUTOCONNECT,      "autoconnect",  OPTION_DONT_ASK, NULL, NULL, NULL,
-                                                                                                        gen_func_bool_values_l10n },
-	{ NM_SETTING_CONNECTION_SETTING_NAME,   NM_SETTING_CONNECTION_INTERFACE_NAME,   "ifname",       OPTION_REQD, PROMPT_IFNAME, NULL,
-                                                                                                        set_connection_iface, nmc_rl_gen_func_ifnames },
-	{ NM_SETTING_CONNECTION_SETTING_NAME,   NM_SETTING_CONNECTION_MASTER,           "master",       OPTION_DONT_ASK, PROMPT_MASTER, NULL,
-                                                                                                        set_connection_master, gen_func_master_ifnames },
-	{ NM_SETTING_CONNECTION_SETTING_NAME,   NM_SETTING_CONNECTION_SLAVE_TYPE,       "slave-type",   OPTION_DONT_ASK, NULL, NULL, NULL,
-                                                                                                        gen_func_slave_type },
-	{ NM_SETTING_PPPOE_SETTING_NAME,        NM_SETTING_PPPOE_USERNAME,              "username",     OPTION_REQD, N_("PPPoE username"), NULL, NULL, NULL },
-	{ NM_SETTING_PPPOE_SETTING_NAME,        NM_SETTING_PPPOE_PASSWORD,              "password",     OPTION_NONE, N_("Password [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_PPPOE_SETTING_NAME,        NM_SETTING_PPPOE_SERVICE,               "service",      OPTION_NONE, N_("Service [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_WIRED_SETTING_NAME,        NM_SETTING_WIRED_MTU,                   "mtu",          OPTION_NONE, N_("MTU [auto]"), NULL, NULL, NULL },
-	{ NM_SETTING_WIRED_SETTING_NAME,        NM_SETTING_WIRED_MAC_ADDRESS,           "mac",          OPTION_NONE, N_("MAC [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_WIRED_SETTING_NAME,        NM_SETTING_WIRED_CLONED_MAC_ADDRESS,    "cloned-mac",   OPTION_NONE, N_("Cloned MAC [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_INFINIBAND_SETTING_NAME,   NM_SETTING_INFINIBAND_MTU,              "mtu",          OPTION_NONE, N_("MTU [auto]"), NULL, NULL, NULL },
-	{ NM_SETTING_INFINIBAND_SETTING_NAME,   NM_SETTING_INFINIBAND_MAC_ADDRESS,      "mac",          OPTION_NONE, N_("MAC [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_INFINIBAND_SETTING_NAME,   NM_SETTING_INFINIBAND_TRANSPORT_MODE,   "transport-mode", OPTION_NONE, PROMPT_IB_MODE, PROMPT_IB_MODE_CHOICES,
-                                                                                                        NULL, gen_func_ib_type },
-	{ NM_SETTING_INFINIBAND_SETTING_NAME,   NM_SETTING_INFINIBAND_PARENT,           "parent",       OPTION_NONE, N_("Parent interface [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_INFINIBAND_SETTING_NAME,   NM_SETTING_INFINIBAND_P_KEY,            "p-key",        OPTION_NONE, N_("P_KEY [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,     NM_SETTING_WIRELESS_SSID,               "ssid",         OPTION_REQD, N_("SSID"), NULL, NULL, NULL },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,     NM_SETTING_WIRELESS_MODE,               "mode",         OPTION_NONE, PROMPT_WIFI_MODE, PROMPT_WIFI_MODE_CHOICES,
-                                                                                                        NULL, gen_func_wifi_mode },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,     NM_SETTING_WIRELESS_MTU,                "mtu",          OPTION_NONE, N_("MTU [auto]"), NULL, NULL, NULL },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,     NM_SETTING_WIRELESS_MAC_ADDRESS,        "mac",          OPTION_NONE, N_("MAC [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,     NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "cloned-mac",   OPTION_NONE, N_("Cloned MAC [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_WIMAX_SETTING_NAME,        NM_SETTING_WIMAX_NETWORK_NAME,          "nsp",          OPTION_REQD, N_("WiMAX NSP name"), NULL, NULL, NULL },
-	{ NM_SETTING_WIMAX_SETTING_NAME,        NM_SETTING_WIMAX_MAC_ADDRESS,           "mac",          OPTION_NONE, N_("MAC [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_GSM_SETTING_NAME,          NM_SETTING_GSM_APN,                     "apn",          OPTION_REQD, N_("APN"), NULL, NULL, NULL },
-	{ NM_SETTING_GSM_SETTING_NAME,          NM_SETTING_GSM_USERNAME,                "user",         OPTION_NONE, N_("Username [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_GSM_SETTING_NAME,          NM_SETTING_GSM_PASSWORD,                "password",     OPTION_NONE, N_("Password [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_CDMA_SETTING_NAME,         NM_SETTING_CDMA_USERNAME,               "user",         OPTION_NONE, N_("Username [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_CDMA_SETTING_NAME,         NM_SETTING_CDMA_PASSWORD,               "password",     OPTION_NONE, N_("Password [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_BLUETOOTH_SETTING_NAME,    NM_SETTING_BLUETOOTH_BDADDR,            "addr",         OPTION_REQD, N_("Bluetooth device address"), NULL, NULL, NULL },
-	{ NM_SETTING_BLUETOOTH_SETTING_NAME,    NM_SETTING_BLUETOOTH_TYPE,              "bt-type",      OPTION_NONE, PROMPT_BT_TYPE, PROMPT_BT_TYPE_CHOICES,
-                                                                                                        set_bluetooth_type, gen_func_bt_type },
-	{ NM_SETTING_VLAN_SETTING_NAME,         NM_SETTING_VLAN_PARENT,                 "dev",          OPTION_REQD, N_("VLAN parent device or connection UUID"), NULL,
-                                                                                                        NULL, nmc_rl_gen_func_ifnames },
-	{ NM_SETTING_VLAN_SETTING_NAME,         NM_SETTING_VLAN_ID,                     "id",           OPTION_REQD, N_("VLAN ID (<0-4094>)"), NULL, NULL, NULL },
-	{ NM_SETTING_VLAN_SETTING_NAME,         NM_SETTING_VLAN_FLAGS,                  "flags",        OPTION_NONE, N_("VLAN flags (<0-7>) [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_VLAN_SETTING_NAME,         NM_SETTING_VLAN_INGRESS_PRIORITY_MAP,   "ingress",      OPTION_NONE, N_("Ingress priority maps [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_VLAN_SETTING_NAME,         NM_SETTING_VLAN_EGRESS_PRIORITY_MAP,    "egress",       OPTION_NONE, N_("Egress priority maps [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_BOND_SETTING_NAME,         NM_SETTING_BOND_OPTIONS,                "mode",         OPTION_NONE, PROMPT_BOND_MODE, "[balance-rr]",
-                                                                                                        set_bond_option, gen_func_bond_mode },
-	{ NM_SETTING_BOND_SETTING_NAME,         NM_SETTING_BOND_OPTIONS,                "primary",      OPTION_DONT_ASK, N_("Bonding primary interface [none]"),
-                                                                                                        NULL, set_bond_option, nmc_rl_gen_func_ifnames },
-	{ NM_SETTING_BOND_SETTING_NAME,         NM_SETTING_BOND_OPTIONS,                NULL,           OPTION_NONE, N_("Bonding monitoring mode"), PROMPT_BOND_MON_MODE_CHOICES,
-                                                                                                        set_bond_monitoring_mode, gen_func_bond_mon_mode },
-	{ NM_SETTING_BOND_SETTING_NAME,         NM_SETTING_BOND_OPTIONS,                "miimon",       OPTION_DONT_ASK, N_("Bonding miimon [100]"), NULL, set_bond_option, NULL },
-	{ NM_SETTING_BOND_SETTING_NAME,         NM_SETTING_BOND_OPTIONS,                "downdelay",    OPTION_DONT_ASK, N_("Bonding downdelay [0]"), NULL, set_bond_option, NULL },
-	{ NM_SETTING_BOND_SETTING_NAME,         NM_SETTING_BOND_OPTIONS,                "updelay",      OPTION_DONT_ASK, N_("Bonding updelay [0]"), NULL, set_bond_option, NULL },
-	{ NM_SETTING_BOND_SETTING_NAME,         NM_SETTING_BOND_OPTIONS,                "arp-interval", OPTION_DONT_ASK, N_("Bonding arp-interval [0]"), NULL,
-                                                                                                        set_bond_option, NULL },
-	{ NM_SETTING_BOND_SETTING_NAME,         NM_SETTING_BOND_OPTIONS,                "arp-ip-target", OPTION_DONT_ASK, N_("Bonding arp-ip-target [none]"),
-                                                                                                        NULL, set_bond_option, NULL },
-	{ NM_SETTING_BOND_SETTING_NAME,         NM_SETTING_BOND_OPTIONS,                "lacp-rate",    OPTION_DONT_ASK, N_("LACP rate ('slow' or 'fast') [slow]"), NULL,
-                                                                                                        set_bond_option, gen_func_bond_lacp_rate },
-	{ NM_SETTING_TEAM_SETTING_NAME,         NM_SETTING_TEAM_CONFIG,                 "config",       OPTION_NONE, N_("Team JSON configuration [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_TEAM_PORT_SETTING_NAME,    NM_SETTING_TEAM_PORT_CONFIG,            "config",       OPTION_NONE, N_("Team JSON configuration [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,       NM_SETTING_BRIDGE_STP,                  "stp",          OPTION_NONE, N_("Enable STP [no]"), NULL,
-                                                                                                        set_yes_no, gen_func_bool_values_l10n },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,       NM_SETTING_BRIDGE_PRIORITY,             "priority",     OPTION_NONE, N_("STP priority [32768]"), NULL, NULL, NULL },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,       NM_SETTING_BRIDGE_FORWARD_DELAY,        "forward-delay", OPTION_NONE, N_("Forward delay [15]"), NULL, NULL, NULL },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,       NM_SETTING_BRIDGE_HELLO_TIME,           "hello-time",   OPTION_NONE, N_("Hello time [2]"), NULL, NULL, NULL },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,       NM_SETTING_BRIDGE_MAX_AGE,              "max-age",      OPTION_NONE, N_("Max age [20]"), NULL, NULL, NULL },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,       NM_SETTING_BRIDGE_AGEING_TIME,          "ageing-time",  OPTION_NONE, N_("MAC address ageing time [300]"), NULL, NULL, NULL },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,       NM_SETTING_BRIDGE_MULTICAST_SNOOPING,   "multicast-snooping", OPTION_NONE, N_("Enable IGMP snooping [no]"), NULL,
-                                                                                                        set_yes_no, gen_func_bool_values_l10n },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,       NM_SETTING_BRIDGE_MAC_ADDRESS,          "mac",          OPTION_NONE, N_("MAC [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_BRIDGE_PORT_SETTING_NAME,  NM_SETTING_BRIDGE_PORT_PRIORITY,        "priority",     OPTION_NONE, N_("Bridge port priority [32]"), NULL, NULL, NULL },
-	{ NM_SETTING_BRIDGE_PORT_SETTING_NAME,  NM_SETTING_BRIDGE_PORT_PATH_COST,       "path-cost",    OPTION_NONE, N_("Bridge port STP path cost [100]"), NULL, NULL, NULL },
-	{ NM_SETTING_BRIDGE_PORT_SETTING_NAME,  NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE,    "hairpin",      OPTION_NONE, N_("Hairpin [no]"), NULL,
-                                                                                                        set_yes_no, gen_func_bool_values_l10n },
-	{ NM_SETTING_VPN_SETTING_NAME,          NM_SETTING_VPN_SERVICE_TYPE,            "vpn-type",     OPTION_REQD, PROMPT_VPN_TYPE, NULL, NULL, gen_func_vpn_types },
-	{ NM_SETTING_VPN_SETTING_NAME,          NM_SETTING_VPN_USER_NAME,               "user",         OPTION_NONE, N_("Username [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_OLPC_MESH_SETTING_NAME,    NM_SETTING_OLPC_MESH_SSID,              "ssid",         OPTION_REQD, N_("SSID"), NULL, NULL, NULL },
-	{ NM_SETTING_OLPC_MESH_SETTING_NAME,    NM_SETTING_OLPC_MESH_CHANNEL,           "channel",      OPTION_NONE, N_("OLPC Mesh channel [1]"), NULL, NULL, NULL },
-	{ NM_SETTING_OLPC_MESH_SETTING_NAME,    NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, "dhcp-anycast", OPTION_NONE, N_("DHCP anycast MAC address [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_ADSL_SETTING_NAME,         NM_SETTING_ADSL_USERNAME,               "username",     OPTION_REQD, N_("Username"), NULL, NULL, NULL },
-	{ NM_SETTING_ADSL_SETTING_NAME,         NM_SETTING_ADSL_PROTOCOL,               "protocol",     OPTION_REQD, PROMPT_ADSL_PROTO, PROMPT_ADSL_PROTO_CHOICES,
-                                                                                                        NULL, gen_func_adsl_proto },
-	{ NM_SETTING_ADSL_SETTING_NAME,         NM_SETTING_ADSL_PASSWORD,               "password",     OPTION_NONE, N_("Password [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_ADSL_SETTING_NAME,         NM_SETTING_ADSL_ENCAPSULATION,          "encapsulation", OPTION_NONE, PROMPT_ADSL_ENCAP, PROMPT_ADSL_ENCAP_CHOICES,
-                                                                                                        NULL, gen_func_adsl_encap },
-	{ NM_SETTING_MACSEC_SETTING_NAME,       NM_SETTING_MACSEC_PARENT,               "dev",          OPTION_REQD, N_("MACsec parent device or connection UUID"), NULL, NULL, NULL },
-	{ NM_SETTING_MACSEC_SETTING_NAME,       NM_SETTING_MACSEC_MODE,                 "mode",         OPTION_REQD, PROMPT_MACSEC_MODE, PROMPT_MACSEC_MODE_CHOICES, NULL, gen_func_macsec_mode },
-	{ NM_SETTING_MACSEC_SETTING_NAME,       NM_SETTING_MACSEC_ENCRYPT,              "encrypt",      OPTION_NONE, N_("Enable encryption [yes]"), NULL, set_yes_no, gen_func_bool_values_l10n },
-	{ NM_SETTING_MACSEC_SETTING_NAME,       NM_SETTING_MACSEC_MKA_CAK,              "cak",          OPTION_NONE, N_("MKA CAK"), NULL, NULL, NULL },
-	{ NM_SETTING_MACSEC_SETTING_NAME,       NM_SETTING_MACSEC_MKA_CKN,              "ckn",          OPTION_NONE, N_("MKA_CKN"), NULL, NULL, NULL },
-	{ NM_SETTING_MACSEC_SETTING_NAME,       NM_SETTING_MACSEC_PORT,                 "port",         OPTION_NONE, N_("SCI port [1]"), NULL, NULL, NULL },
-
-	{ NM_SETTING_MACVLAN_SETTING_NAME,      NM_SETTING_MACVLAN_PARENT,              "dev",          OPTION_REQD, N_("MACVLAN parent device or connection UUID"), NULL,
-                                                                                                        NULL, nmc_rl_gen_func_ifnames },
-	{ NM_SETTING_MACVLAN_SETTING_NAME,      NM_SETTING_MACVLAN_MODE,                "mode",         OPTION_REQD, PROMPT_MACVLAN_MODE, NULL,
-                                                                                                        NULL, gen_func_macvlan_mode },
-	{ NM_SETTING_MACVLAN_SETTING_NAME,      NM_SETTING_MACVLAN_TAP,                 "tap",          OPTION_NONE, N_("Tap [no]"), NULL,
-                                                                                                        set_yes_no, gen_func_bool_values_l10n },
-	{ NM_SETTING_VXLAN_SETTING_NAME,        NM_SETTING_VXLAN_ID,                    "id",           OPTION_REQD, N_("VXLAN ID"), NULL, NULL, NULL },
-	{ NM_SETTING_VXLAN_SETTING_NAME,        NM_SETTING_VXLAN_REMOTE,                "remote",       OPTION_REQD, N_("Remote"), NULL, NULL, NULL },
-	{ NM_SETTING_VXLAN_SETTING_NAME,        NM_SETTING_VXLAN_PARENT,                "dev",          OPTION_NONE, N_("Parent device [none]"), NULL,
-                                                                                                        NULL, nmc_rl_gen_func_ifnames },
-	{ NM_SETTING_VXLAN_SETTING_NAME,        NM_SETTING_VXLAN_LOCAL,                 "local",        OPTION_NONE, N_("Local address [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_VXLAN_SETTING_NAME,        NM_SETTING_VXLAN_SOURCE_PORT_MIN,       "source-port-min", OPTION_NONE, N_("Minimum source port [0]"), NULL, NULL, NULL },
-	{ NM_SETTING_VXLAN_SETTING_NAME,        NM_SETTING_VXLAN_SOURCE_PORT_MAX,       "source-port-max", OPTION_NONE, N_("Maximum source port [0]"), NULL, NULL, NULL },
-	{ NM_SETTING_VXLAN_SETTING_NAME,        NM_SETTING_VXLAN_DESTINATION_PORT,      "destination-port", OPTION_NONE, N_("Destination port [8472]"), NULL, NULL, NULL },
-	{ NM_SETTING_TUN_SETTING_NAME,          NM_SETTING_TUN_MODE,                    "mode",         OPTION_NONE, PROMPT_TUN_MODE, PROMPT_TUN_MODE_CHOICES,
-                                                                                                        NULL, gen_func_tun_mode },
-	{ NM_SETTING_TUN_SETTING_NAME,          NM_SETTING_TUN_OWNER,                   "owner",        OPTION_NONE, N_("User ID [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_TUN_SETTING_NAME,          NM_SETTING_TUN_GROUP,                   "group",        OPTION_NONE, N_("Group ID [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_TUN_SETTING_NAME,          NM_SETTING_TUN_PI,                      "pi",           OPTION_NONE, N_("Enable PI [no]"), NULL,
-                                                                                                        set_yes_no, gen_func_bool_values_l10n },
-	{ NM_SETTING_TUN_SETTING_NAME,          NM_SETTING_TUN_VNET_HDR,                "vnet-hdr",     OPTION_NONE, N_("Enable VNET header [no]"), NULL,
-                                                                                                        set_yes_no, gen_func_bool_values_l10n },
-	{ NM_SETTING_TUN_SETTING_NAME,          NM_SETTING_TUN_MULTI_QUEUE,             "multi-queue",  OPTION_NONE, N_("Enable multi queue [no]"), NULL,
-                                                                                                        set_yes_no, gen_func_bool_values_l10n },
-	{ NM_SETTING_IP_TUNNEL_SETTING_NAME,    NM_SETTING_IP_TUNNEL_MODE,              "mode",         OPTION_REQD, PROMPT_IP_TUNNEL_MODE, NULL, NULL, gen_func_ip_tunnel_mode },
-	{ NM_SETTING_IP_TUNNEL_SETTING_NAME,    NM_SETTING_IP_TUNNEL_LOCAL,             "local",        OPTION_NONE, N_("Local endpoint [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_IP_TUNNEL_SETTING_NAME,    NM_SETTING_IP_TUNNEL_REMOTE,            "remote",       OPTION_REQD, N_("Remote"), NULL, NULL, NULL },
-	{ NM_SETTING_IP_TUNNEL_SETTING_NAME,    NM_SETTING_IP_TUNNEL_PARENT,            "dev",          OPTION_NONE, N_("Parent device [none]"), NULL,
-                                                                                                        NULL, nmc_rl_gen_func_ifnames },
-	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,   NM_SETTING_IP_CONFIG_ADDRESSES,         "ip4",          OPTION_MULTI, N_("IPv4 address (IP[/plen]) [none]"), NULL,
-	                                                                                                set_ip4_address, NULL },
-	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,   NM_SETTING_IP_CONFIG_GATEWAY,           "gw4",          OPTION_NONE, N_("IPv4 gateway [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,   NM_SETTING_IP_CONFIG_ADDRESSES,         "ip6",          OPTION_MULTI, N_("IPv6 address (IP[/plen]) [none]"), NULL,
-	                                                                                                set_ip6_address, NULL },
-	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,   NM_SETTING_IP_CONFIG_GATEWAY,           "gw6",          OPTION_NONE, N_("IPv6 gateway [none]"), NULL, NULL, NULL },
-	{ NM_SETTING_PROXY_SETTING_NAME,        NM_SETTING_PROXY_METHOD,                "method",       OPTION_NONE, PROMPT_PROXY_METHOD, PROMPT_PROXY_METHOD_CHOICES, NULL, gen_func_proxy_method },
-	{ NM_SETTING_PROXY_SETTING_NAME,        NM_SETTING_PROXY_BROWSER_ONLY,          "browser-only", OPTION_NONE, N_("Browser only [no]"), NULL,
-                                                                                                        set_yes_no, gen_func_bool_values_l10n },
-	{ NM_SETTING_PROXY_SETTING_NAME,        NM_SETTING_PROXY_PAC_URL,               "pac-url",      OPTION_NONE, N_("PAC URL"), NULL, NULL, NULL },
-	{ NM_SETTING_PROXY_SETTING_NAME,        NM_SETTING_PROXY_PAC_SCRIPT,            "pac-script",   OPTION_NONE, N_("PAC script"), NULL, NULL, NULL },
-	{ NULL, NULL, NULL, OPTION_NONE, NULL, NULL, NULL, NULL },
-};
+	return set_property (con, option->setting_info->general->setting_name, option->property, value,
+	                     '+', error);
+}
+
+/*****************************************************************************/
+
+static const OptionInfo *
+_meta_abstract_get_option_info (const NMMetaAbstractInfo *abstract_info)
+{
+	static const OptionInfo option_info[] = {
+#define OPTION_INFO(name, property_name_, property_alias_, check_and_set_, generator_func_) \
+		{ \
+			.setting_info =        &nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_##name], \
+			.property =            property_name_, \
+			.option =              property_alias_, \
+			.check_and_set =       check_and_set_, \
+			.generator_func =      generator_func_, \
+		}
+		OPTION_INFO (CONNECTION,   NM_SETTING_CONNECTION_TYPE,                  "type",               set_connection_type,       NULL),
+		OPTION_INFO (CONNECTION,   NM_SETTING_CONNECTION_INTERFACE_NAME,        "ifname",             set_connection_iface,      NULL),
+		OPTION_INFO (CONNECTION,   NM_SETTING_CONNECTION_MASTER,                "master",             set_connection_master,     NULL),
+		OPTION_INFO (BLUETOOTH,    NM_SETTING_BLUETOOTH_TYPE,                   "bt-type",            set_bluetooth_type,        gen_func_bt_type),
+		OPTION_INFO (BOND,         NM_SETTING_BOND_OPTIONS,                     "mode",               set_bond_option,           gen_func_bond_mode),
+		OPTION_INFO (BOND,         NM_SETTING_BOND_OPTIONS,                     "primary",            set_bond_option,           nmc_rl_gen_func_ifnames),
+		OPTION_INFO (BOND,         NM_SETTING_BOND_OPTIONS,                     NULL,                 set_bond_monitoring_mode,  gen_func_bond_mon_mode),
+		OPTION_INFO (BOND,         NM_SETTING_BOND_OPTIONS,                     "miimon",             set_bond_option,           NULL),
+		OPTION_INFO (BOND,         NM_SETTING_BOND_OPTIONS,                     "downdelay",          set_bond_option,           NULL),
+		OPTION_INFO (BOND,         NM_SETTING_BOND_OPTIONS,                     "updelay",            set_bond_option,           NULL),
+		OPTION_INFO (BOND,         NM_SETTING_BOND_OPTIONS,                     "arp-interval",       set_bond_option,           NULL),
+		OPTION_INFO (BOND,         NM_SETTING_BOND_OPTIONS,                     "arp-ip-target",      set_bond_option,           NULL),
+		OPTION_INFO (BOND,         NM_SETTING_BOND_OPTIONS,                     "lacp-rate",          set_bond_option,           gen_func_bond_lacp_rate),
+		OPTION_INFO (IP4_CONFIG,   NM_SETTING_IP_CONFIG_ADDRESSES,              "ip4",                set_ip4_address,           NULL),
+		OPTION_INFO (IP6_CONFIG,   NM_SETTING_IP_CONFIG_ADDRESSES,              "ip6",                set_ip6_address,           NULL),
+		{ 0 },
+	};
+	const char *property_name, *option;
+	const NMMetaSettingInfoEditor *setting_info;
+	const OptionInfo *candidate;
+
+	_meta_abstract_get (abstract_info, &setting_info, NULL, &property_name, &option, NULL, NULL, NULL);
+
+	for (candidate = option_info; candidate->setting_info; candidate++) {
+		if (   candidate->setting_info == setting_info
+		    && nm_streq0 (candidate->property, property_name)
+		    && nm_streq0 (candidate->option, option)) {
+			return candidate;
+		}
+	}
+	return NULL;
+}
 
 static gboolean
-option_relevant (NMConnection *connection, OptionInfo *option)
+option_relevant (NMConnection *connection, const NMMetaAbstractInfo *abstract_info)
 {
-	if (option->flags & OPTION_DONT_ASK && !(option->flags & OPTION_ENABLED))
+	const char *setting_name;
+	NMMetaPropertyInfFlags inf_flags;
+
+	_meta_abstract_get (abstract_info, NULL, &setting_name, NULL, NULL, &inf_flags, NULL, NULL);
+
+	if (   (inf_flags & NM_META_PROPERTY_INF_FLAG_DONT_ASK)
+	    && !(_dynamic_options_get (abstract_info) & PROPERTY_INF_FLAG_ENABLED))
 		return FALSE;
-	if (option->flags & OPTION_DISABLED)
+	if (_dynamic_options_get (abstract_info) & PROPERTY_INF_FLAG_DISABLED)
 		return FALSE;
-	if (!nm_connection_get_setting_by_name (connection, option->setting_name))
+	if (!nm_connection_get_setting_by_name (connection, setting_name))
 		return FALSE;
 	return TRUE;
 }
 
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
 
 static void
 complete_property_name (NmCli *nmc, NMConnection *connection,
-			 char modifier,
-			 const gchar *prefix,
-			 const gchar *postfix)
+                        char modifier,
+                        const gchar *prefix,
+                        const gchar *postfix)
 {
 	NMSettingConnection *s_con;
-	const NameItem *valid_settings_main = NULL;
-	const NameItem *valid_settings_slave = NULL;
+	const NMMetaSettingValidPartItem *const*valid_settings_main;
+	const NMMetaSettingValidPartItem *const*valid_settings_slave;
 	const char *connection_type = NULL;
 	const char *slave_type = NULL;
-	gs_free char *slv_type = NULL;
 	gs_free char *word_list = NULL;
-	OptionInfo *candidate;
+	NMMetaSettingType s;
 
 	connection_type = nm_connection_get_connection_type (connection);
 	s_con = nm_connection_get_setting_connection (connection);
 	if (s_con)
 		slave_type = nm_setting_connection_get_slave_type (s_con);
-	slv_type = g_strdup_printf ("%s-slave", slave_type ? slave_type : "no");
 	valid_settings_main = get_valid_settings_array (connection_type);
-	valid_settings_slave = get_valid_settings_array (slv_type);
+	valid_settings_slave = nm_meta_setting_info_valid_parts_for_slave_type (slave_type, NULL);
 
 	word_list = get_valid_properties_string (valid_settings_main, valid_settings_slave, modifier, prefix, postfix);
 	if (word_list)
@@ -4449,14 +4051,39 @@ complete_property_name (NmCli *nmc, NMConnection *connection,
 	if (modifier != '\0')
 		return;
 
-	for (candidate = option_info; candidate->setting_name; candidate++) {
-		if (!nm_connection_get_setting_by_name (connection, candidate->setting_name))
-			continue;
-		if (!candidate->option)
+	for (s = 0; s < _NM_META_SETTING_TYPE_NUM; s++) {
+		const NMMetaPropertyInfo *const*property_infos;
+		guint p;
+
+		if (!nm_connection_get_setting_by_name (connection, nm_meta_setting_infos_editor[s].general->setting_name))
 			continue;
-		if (!g_str_has_prefix (candidate->option, prefix))
+
+		property_infos = nm_meta_setting_infos_editor[s].properties;
+		if (!property_infos)
 			continue;
-		g_print ("%s\n", candidate->option);
+		for (p = 0; property_infos[p]; p++) {
+			const NMMetaPropertyInfo *property_info = property_infos[p];
+
+			if (_meta_property_needs_bond_hack (property_info)) {
+				guint i;
+
+				for (i = 0; i < nm_meta_property_typ_data_bond.nested_len; i++) {
+					const NMMetaNestedPropertyInfo *bi = &nm_meta_property_typ_data_bond.nested[i];
+
+					if (   !bi->base.property_alias
+					    || !g_str_has_prefix (bi->base.property_alias, prefix))
+						continue;
+					g_print ("%s\n", bi->base.property_alias);
+				}
+			} else {
+				if (!property_info->is_cli_option)
+					continue;
+				if (   !property_info->property_alias
+				    || !g_str_has_prefix (property_info->property_alias, prefix))
+					continue;
+				g_print ("%s\n", property_info->property_alias);
+			}
+		}
 	}
 }
 
@@ -4474,62 +4101,54 @@ run_rl_generator (rl_compentry_func_t *generator_func, const char *prefix)
 	}
 }
 
-static void
-complete_option (OptionInfo *option, const gchar *prefix)
+static gboolean
+complete_option (const NMMetaAbstractInfo *abstract_info, const gchar *prefix, NMConnection *context_connection)
 {
-	if (option->generator_func)
-		run_rl_generator (option->generator_func, prefix);
+	const OptionInfo *candidate;
+	const char *const*values;
+	gs_strfreev char **values_to_free = NULL;
+	const NMMetaOperationContext ctx = {
+		.connection = context_connection,
+	};
+
+	values = nm_meta_abstract_info_complete (abstract_info,
+	                                         nmc_meta_environment,
+	                                         nmc_meta_environment_arg,
+	                                         &ctx,
+	                                         prefix,
+	                                         &values_to_free);
+	if (values) {
+		for (; values[0]; values++)
+			g_print ("%s\n", values[0]);
+		return TRUE;
+	}
+
+	candidate = _meta_abstract_get_option_info (abstract_info);
+	if (candidate && candidate->generator_func) {
+		run_rl_generator (candidate->generator_func, prefix);
+		return TRUE;
+	}
+
+	return FALSE;
 }
 
 static void
-complete_property (const gchar *setting_name, const gchar *property, const gchar *prefix)
-{
-	if (strcmp (setting_name, NM_SETTING_CONNECTION_SETTING_NAME) == 0) {
-		if (strcmp (property, NM_SETTING_CONNECTION_TYPE) == 0)
-			run_rl_generator (gen_connection_types, prefix);
-		else if (strcmp (property, NM_SETTING_CONNECTION_MASTER) == 0)
-			run_rl_generator (gen_func_master_ifnames, prefix);
-		else if (strcmp (property, NM_SETTING_CONNECTION_INTERFACE_NAME) == 0)
-			run_rl_generator (nmc_rl_gen_func_ifnames, prefix);
-	} else if (   strcmp (setting_name, NM_SETTING_VPN_SETTING_NAME) == 0
-	           && strcmp (property, NM_SETTING_VPN_SERVICE_TYPE) == 0)
-		run_rl_generator (gen_func_vpn_types, prefix);
-	else if (   strcmp (setting_name, NM_SETTING_WIRELESS_SETTING_NAME) == 0
-	         && strcmp (property, NM_SETTING_WIRELESS_MODE) == 0)
-		run_rl_generator (gen_func_wifi_mode, prefix);
-	else if (   strcmp (setting_name, NM_SETTING_INFINIBAND_SETTING_NAME) == 0
-	         && strcmp (property, NM_SETTING_INFINIBAND_TRANSPORT_MODE) == 0)
-		run_rl_generator (gen_func_ib_type, prefix);
-	else if (   strcmp (setting_name, NM_SETTING_BLUETOOTH_SETTING_NAME) == 0
+complete_property (const gchar *setting_name, const gchar *property, const gchar *prefix, NMConnection *connection)
+{
+	const NMMetaPropertyInfo *property_info;
+
+	property_info = nm_meta_property_info_find_by_name (setting_name, property);
+	if (property_info) {
+		if (complete_option ((const NMMetaAbstractInfo *) property_info, prefix, connection))
+			return;
+	}
+
+	if (   strcmp (setting_name, NM_SETTING_BLUETOOTH_SETTING_NAME) == 0
 	         && strcmp (property, NM_SETTING_BLUETOOTH_TYPE) == 0)
 		run_rl_generator (gen_func_bt_type, prefix);
-	else if (strcmp (setting_name, NM_SETTING_ADSL_SETTING_NAME) == 0) {
-		if (strcmp (property, NM_SETTING_ADSL_PROTOCOL) == 0)
-			run_rl_generator (gen_func_adsl_proto, prefix);
-		else if (strcmp (property, NM_SETTING_ADSL_ENCAPSULATION) == 0)
-			run_rl_generator (gen_func_adsl_encap, prefix);
-	} else if (   strcmp (setting_name, NM_SETTING_TUN_SETTING_NAME) == 0
-	           && strcmp (property, NM_SETTING_TUN_MODE) == 0)
-		run_rl_generator (gen_func_tun_mode, prefix);
-	else if (strcmp (setting_name, NM_SETTING_IP_TUNNEL_SETTING_NAME) == 0) {
-		if (strcmp (property, NM_SETTING_IP_TUNNEL_MODE) == 0)
-			run_rl_generator (gen_func_ip_tunnel_mode, prefix);
-		else if (strcmp (property, NM_SETTING_IP_TUNNEL_PARENT) == 0)
-			run_rl_generator (nmc_rl_gen_func_ifnames, prefix);
-	} else if (strcmp (setting_name, NM_SETTING_MACVLAN_SETTING_NAME) == 0) {
-		if (strcmp (property, NM_SETTING_MACVLAN_MODE) == 0)
-			run_rl_generator (gen_func_macvlan_mode, prefix);
-		else if (strcmp (property, NM_SETTING_MACVLAN_PARENT) == 0)
-			run_rl_generator (nmc_rl_gen_func_ifnames, prefix);
-		else if (strcmp (property, NM_SETTING_MACVLAN_TAP) == 0)
-			run_rl_generator (gen_func_bool_values_l10n, prefix);
-	} else if (   strcmp (setting_name, NM_SETTING_VXLAN_SETTING_NAME) == 0
-	           && strcmp (property, NM_SETTING_VXLAN_PARENT) == 0)
-		run_rl_generator (nmc_rl_gen_func_ifnames, prefix);
-
-}
-
-/*----------------------------------------------------------------------------*/
+}
+
+/*****************************************************************************/
 
 static gboolean
 get_value (const char **value, int *argc, char ***argv, const char *option, GError **error)
@@ -4567,10 +4186,10 @@ nmc_read_connection_properties (NmCli *nmc,
 	 */
 	/* Go through arguments and set properties */
 	do {
-		OptionInfo *candidate;
-		OptionInfo *chosen = NULL;
+		const NMMetaAbstractInfo *chosen = NULL;
 		gs_strfreev gchar **strv = NULL;
-		const NameItem *type_settings, *slv_settings;
+		const NMMetaSettingValidPartItem *const*type_settings;
+		const NMMetaSettingValidPartItem *const*slv_settings;
 		char modifier = '\0';
 
 		if (!con_settings (connection, &type_settings, &slv_settings, error))
@@ -4617,25 +4236,66 @@ nmc_read_connection_properties (NmCli *nmc,
 				return FALSE;
 
 			if (!*argc && nmc->complete)
-				complete_property (setting, strv[1], value ? value : "");
+				complete_property (setting, strv[1], value ? value : "", connection);
 
 			if (!set_property (connection, setting_name, strv[1], value, modifier, error))
 				return FALSE;
 		} else {
+			NMMetaSettingType s;
+			const char *chosen_setting_name = NULL;
+			const char *chosen_option = NULL;
+
 			/* Let's see if this is an property alias (such as "id", "mode", "type" or "con-name")*/
-			for (candidate = option_info; candidate->setting_name; candidate++) {
-				if (g_strcmp0 (candidate->option, option))
+			for (s = 0; s < _NM_META_SETTING_TYPE_NUM; s++) {
+				const NMMetaPropertyInfo *const*property_infos;
+				guint p;
+
+				if (!check_valid_name (nm_meta_setting_infos[s].setting_name,
+				                       type_settings, slv_settings, NULL))
 					continue;
-				if (!check_valid_name (candidate->setting_name, type_settings, slv_settings, NULL))
+
+				property_infos = nm_meta_setting_infos_editor[s].properties;
+				if (!property_infos)
 					continue;
-				if (chosen) {
-					g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-						     _("Error: '%s' is ambiguous (%s.%s or %s.%s)."), option,
-						     chosen->setting_name, chosen->property,
-						     candidate->setting_name, candidate->property);
-					return FALSE;
+				for (p = 0; property_infos[p]; p++) {
+					const NMMetaPropertyInfo *property_info = property_infos[p];
+
+					if (_meta_property_needs_bond_hack (property_info)) {
+						guint i;
+
+						for (i = 0; i < nm_meta_property_typ_data_bond.nested_len; i++) {
+							const NMMetaNestedPropertyInfo *bi = &nm_meta_property_typ_data_bond.nested[i];
+
+							if (!nm_streq0 (bi->base.property_alias, option))
+								continue;
+							if (chosen) {
+								g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
+								             _("Error: '%s' is ambiguous (%s.%s or %s.%s)."), option,
+								             chosen_setting_name, chosen_option,
+								             nm_meta_setting_infos[s].setting_name, option);
+								return FALSE;
+							}
+							chosen_setting_name = nm_meta_setting_infos[s].setting_name;
+							chosen_option = option;
+							chosen = (const NMMetaAbstractInfo *) bi;
+						}
+					} else {
+						if (!property_info->is_cli_option)
+							continue;
+						if (!nm_streq0 (property_info->property_alias, option))
+							continue;
+						if (chosen) {
+							g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
+							             _("Error: '%s' is ambiguous (%s.%s or %s.%s)."), option,
+							             chosen_setting_name, chosen_option,
+							             nm_meta_setting_infos[s].setting_name, option);
+							return FALSE;
+						}
+						chosen_setting_name = nm_meta_setting_infos[s].setting_name;
+						chosen_option = option;
+						chosen = (const NMMetaAbstractInfo *) property_info;
+					}
 				}
-				chosen = candidate;
 			}
 
 			if (!chosen) {
@@ -4644,7 +4304,7 @@ nmc_read_connection_properties (NmCli *nmc,
 				if (*argc == 1 && nmc->complete)
 					complete_property_name (nmc, connection, modifier, option, NULL);
 				g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-					     _("Error: invalid <setting>.<property> '%s'."), option);
+				             _("Error: invalid <setting>.<property> '%s'."), option);
 				return FALSE;
 			}
 
@@ -4657,7 +4317,7 @@ nmc_read_connection_properties (NmCli *nmc,
 				return FALSE;
 
 			if (!*argc && nmc->complete)
-				complete_option (chosen, value ? value : "");
+				complete_option (chosen, value ? value : "", connection);
 
 			if (!set_option (nmc, connection, chosen, value, error))
 				return FALSE;
@@ -4682,6 +4342,8 @@ add_connection_cb (GObject *client,
 	NmCli *nmc = info->nmc;
 	NMRemoteConnection *connection;
 	GError *error = NULL;
+	const GPtrArray *connections;
+	guint i, found;
 
 	connection = nm_client_add_connection_finish (NM_CLIENT (client), result, &error);
 	if (error) {
@@ -4691,6 +4353,28 @@ add_connection_cb (GObject *client,
 		g_error_free (error);
 		nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
 	} else {
+		connections = nm_client_get_connections (nmc->client);
+		if (connections) {
+			found = 0;
+			for (i = 0; i < connections->len; i++) {
+				NMConnection *candidate = NM_CONNECTION (connections->pdata[i]);
+
+				if ((NMConnection *) connection == candidate)
+					continue;
+				if (nm_streq0 (nm_connection_get_id (candidate), info->con_name))
+					found++;
+			}
+			if (found > 0) {
+				g_printerr (g_dngettext (GETTEXT_PACKAGE,
+				                         "Warning: There is another connection with the name '%1$s'. Reference the connection by its uuid '%2$s'\n",
+				                         "Warning: There are %3$u other connections with the name '%1$s'. Reference the connection by its uuid '%2$s'\n",
+				                         found),
+				            info->con_name,
+				            nm_connection_get_uuid (NM_CONNECTION (connection)),
+				            found);
+			}
+		}
+
 		g_print (_("Connection '%s' (%s) successfully added.\n"),
 		         nm_connection_get_id (NM_CONNECTION (connection)),
 		         nm_connection_get_uuid (NM_CONNECTION (connection)));
@@ -4741,6 +4425,7 @@ is_single_word (const char* line)
 static char **
 nmcli_con_add_tab_completion (const char *text, int start, int end)
 {
+	NMMetaSettingType s;
 	char **match_array = NULL;
 	rl_compentry_func_t *generator_func = NULL;
 	gs_free char *no = g_strdup_printf ("[%s]: ", gettext ("no"));
@@ -4755,38 +4440,48 @@ nmcli_con_add_tab_completion (const char *text, int start, int end)
 	if (!is_single_word (rl_line_buffer))
 		return NULL;
 
-	if (g_str_has_prefix (rl_prompt, PROMPT_CON_TYPE))
-		generator_func = gen_connection_types;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_IFNAME))
-		generator_func = nmc_rl_gen_func_ifnames;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_VPN_TYPE))
-		generator_func = gen_func_vpn_types;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_MASTER))
-		generator_func = gen_func_master_ifnames;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_WIFI_MODE))
-		generator_func = gen_func_wifi_mode;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_IB_MODE))
-		generator_func = gen_func_ib_type;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_BT_TYPE))
+	for (s = 0; s < _NM_META_SETTING_TYPE_NUM; s++) {
+		const NMMetaPropertyInfo *const*property_infos;
+		guint p;
+
+		property_infos = nm_meta_setting_infos_editor[s].properties;
+		if (!property_infos)
+			continue;
+		for (p = 0; property_infos[p]; p++) {
+			const NMMetaPropertyInfo *property_info = property_infos[p];
+
+			if (_meta_property_needs_bond_hack (property_info)) {
+				guint i;
+
+				for (i = 0; i < nm_meta_property_typ_data_bond.nested_len; i++) {
+					const NMMetaNestedPropertyInfo *bi = &nm_meta_property_typ_data_bond.nested[i];
+
+					if (   bi->base.prompt
+					    && g_str_has_prefix (rl_prompt, bi->base.prompt)) {
+						goto next;
+					}
+				}
+			} else {
+				if (   property_info->prompt
+				    && g_str_has_prefix (rl_prompt, property_info->prompt)) {
+					char **values;
+
+					values = _meta_abstract_complete ((const NMMetaAbstractInfo *) property_info, text);
+					if (values)
+						return values;
+					goto next;
+				}
+			}
+		}
+	}
+
+next:
+	if (g_str_has_prefix (rl_prompt, NM_META_TEXT_PROMPT_BT_TYPE))
 		generator_func = gen_func_bt_type;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_BOND_MODE))
+	else if (g_str_has_prefix (rl_prompt, NM_META_TEXT_PROMPT_BOND_MODE))
 		generator_func = gen_func_bond_mode;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_BOND_MON_MODE))
+	else if (g_str_has_prefix (rl_prompt, NM_META_TEXT_PROMPT_BOND_MON_MODE))
 		generator_func = gen_func_bond_mon_mode;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_ADSL_PROTO))
-		generator_func = gen_func_adsl_proto;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_ADSL_ENCAP))
-		generator_func = gen_func_adsl_encap;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_TUN_MODE))
-		generator_func = gen_func_tun_mode;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_IP_TUNNEL_MODE))
-		generator_func = gen_func_ip_tunnel_mode;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_MACVLAN_MODE))
-		generator_func = gen_func_macvlan_mode;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_MACSEC_MODE))
-		generator_func = gen_func_macsec_mode;
-	else if (g_str_has_prefix (rl_prompt, PROMPT_PROXY_METHOD))
-		generator_func = gen_func_proxy_method;
 	else if (   g_str_has_suffix (rl_prompt, yes)
 	         || g_str_has_suffix (rl_prompt, no))
 		generator_func = gen_func_bool_values_l10n;
@@ -4798,20 +4493,25 @@ nmcli_con_add_tab_completion (const char *text, int start, int end)
 }
 
 static void
-ask_option (NmCli *nmc, NMConnection *connection, OptionInfo *option)
+ask_option (NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abstract_info)
 {
 	gchar *value;
 	GError *error = NULL;
 	gs_free gchar *prompt = NULL;
-	gboolean multi = option->flags & OPTION_MULTI;
+	gboolean multi;
+	const char *opt_prompt, *opt_def_hint;
+	NMMetaPropertyInfFlags inf_flags;
 
+	_meta_abstract_get (abstract_info, NULL, NULL, NULL, NULL, &inf_flags, &opt_prompt, &opt_def_hint);
 	prompt = g_strjoin ("",
-	                    gettext (option->prompt),
-	                    option->def_hint ? " " : "",
-	                    option->def_hint ? option->def_hint : "",
+	                    gettext (opt_prompt),
+	                    opt_def_hint ? " " : "",
+	                    opt_def_hint ?: "",
 	                    ": ",
 	                    NULL);
 
+	multi = NM_FLAGS_HAS (inf_flags, NM_META_PROPERTY_INF_FLAG_MULTI);
+
 	if (multi)
 		g_print (_("You can specify this option more than once. Press <Enter> when you're done.\n"));
 
@@ -4820,7 +4520,7 @@ again:
 	if (multi && !value)
 		return;
 
-	if (!set_option (nmc, connection, option, value, &error)) {
+	if (!set_option (nmc, connection, abstract_info, value, &error)) {
 		g_printerr ("%s\n", error->message);
 		g_clear_error (&error);
 		goto again;
@@ -4830,17 +4530,78 @@ again:
 		goto again;
 }
 
+static NMMetaSettingType
+connection_get_base_meta_setting_type (NMConnection *connection)
+{
+	const char *connection_type;
+	NMSetting *base_setting;
+	const NMMetaSettingInfoEditor *editor;
+
+	connection_type = nm_connection_get_connection_type (connection);
+	nm_assert (connection_type);
+	base_setting = nm_connection_get_setting_by_name (connection, connection_type);
+	nm_assert (base_setting);
+	editor = nm_meta_setting_info_editor_find_by_setting (base_setting);
+	nm_assert (editor);
+
+	return editor - nm_meta_setting_infos_editor;
+}
+
+static void
+questionnaire_mandatory_ask_setting (NmCli *nmc, NMConnection *connection, NMMetaSettingType type)
+{
+	const NMMetaSettingInfoEditor *editor;
+	const NMMetaPropertyInfo *property_info;
+	guint p;
+
+	editor = &nm_meta_setting_infos_editor[type];
+	if (!editor->properties)
+		return;
+
+	for (p = 0; editor->properties[p]; p++) {
+		property_info = editor->properties[p];
+
+		if (_meta_property_needs_bond_hack (property_info)) {
+			guint i;
+
+			for (i = 0; i < nm_meta_property_typ_data_bond.nested_len; i++) {
+				const NMMetaNestedPropertyInfo *bi = &nm_meta_property_typ_data_bond.nested[i];
+
+				if (!option_relevant (connection, (const NMMetaAbstractInfo *) bi))
+					continue;
+				if (   (bi->base.inf_flags & NM_META_PROPERTY_INF_FLAG_REQD)
+				    || (_dynamic_options_get ((const NMMetaAbstractInfo *) bi) & PROPERTY_INF_FLAG_ENABLED))
+					ask_option (nmc, connection, (const NMMetaAbstractInfo *) bi);
+			}
+		} else {
+			if (!property_info->is_cli_option)
+				continue;
+
+			if (!option_relevant (connection, (const NMMetaAbstractInfo *) property_info))
+				continue;
+			if (   (property_info->inf_flags & NM_META_PROPERTY_INF_FLAG_REQD)
+			    || (_dynamic_options_get ((const NMMetaAbstractInfo *) property_info) & PROPERTY_INF_FLAG_ENABLED))
+				ask_option (nmc, connection, (const NMMetaAbstractInfo *) property_info);
+		}
+	}
+}
+
 static void
 questionnaire_mandatory (NmCli *nmc, NMConnection *connection)
 {
-	OptionInfo *candidate;
+	NMMetaSettingType s, base;
 
-	/* Mandatory settings. */
-	for (candidate = option_info; candidate->setting_name; candidate++) {
-		if (!option_relevant (connection, candidate))
-			continue;
-		if (candidate->flags & OPTION_REQD || candidate->flags & OPTION_ENABLED)
-			ask_option (nmc, connection, candidate);
+	/* First ask connection properties */
+	questionnaire_mandatory_ask_setting (nmc, connection, NM_META_SETTING_TYPE_CONNECTION);
+
+	/* Ask properties of the base setting */
+	base = connection_get_base_meta_setting_type (connection);
+	questionnaire_mandatory_ask_setting (nmc, connection, base);
+
+	/* Remaining settings */
+	for (s = 0; s < _NM_META_SETTING_TYPE_NUM; s++) {
+		if (!NM_IN_SET (s, NM_META_SETTING_TYPE_CONNECTION, base))
+			questionnaire_mandatory_ask_setting (nmc, connection, s);
 	}
 }
 
@@ -4858,104 +4619,93 @@ want_provide_opt_args (const char *type, int num)
 	                                 "Do you want to provide them? %s", num),
 	                       prompt_yes_no (TRUE, NULL));
 	answer = answer ? g_strstrip (answer) : NULL;
-	if (answer && !matches (answer, WORD_LOC_YES))
+	if (answer && !matches (answer, WORD_YES))
 		ret = FALSE;
 	g_free (answer);
 	return ret;
 }
 
-static const char *
-setting_name_to_name (const char *name)
-{
-	if (strcmp (name, NM_SETTING_WIRED_SETTING_NAME) == 0)
-		return _("Wired Ethernet");
-	if (strcmp (name, NM_SETTING_INFINIBAND_SETTING_NAME) == 0)
-		return _("InfiniBand connection");
-	if (strcmp (name, NM_SETTING_WIRELESS_SETTING_NAME) == 0)
-		return _("Wi-Fi connection");
-	if (strcmp (name, NM_SETTING_WIMAX_SETTING_NAME) == 0)
-		return _("WiMAX connection");
-	if (strcmp (name, NM_SETTING_PPPOE_SETTING_NAME) == 0)
-		return _("PPPoE");
-	if (strcmp (name, NM_SETTING_CDMA_SETTING_NAME) == 0)
-		return _("CDMA mobile broadband connection");
-	if (strcmp (name, NM_SETTING_GSM_SETTING_NAME) == 0)
-		return _("GSM mobile broadband connection");
-	if (strcmp (name, NM_SETTING_BLUETOOTH_SETTING_NAME) == 0)
-		return _("bluetooth connection");
-	if (strcmp (name, NM_SETTING_VLAN_SETTING_NAME) == 0)
-		return _("VLAN connection");
-	if (strcmp (name, NM_SETTING_BOND_SETTING_NAME) == 0)
-		return _("Bond device");
-	if (strcmp (name, NM_SETTING_TEAM_SETTING_NAME) == 0)
-		return _("Team device");
-	if (strcmp (name, NM_SETTING_TEAM_PORT_SETTING_NAME) == 0)
-		return _("Team port");
-	if (strcmp (name, NM_SETTING_BRIDGE_SETTING_NAME) == 0)
-		return _("Bridge device");
-	if (strcmp (name, NM_SETTING_BRIDGE_PORT_SETTING_NAME) == 0)
-		return _("Bridge port");
-	if (strcmp (name, NM_SETTING_VPN_SETTING_NAME) == 0)
-		return _("VPN connection");
-	if (strcmp (name, NM_SETTING_OLPC_MESH_SETTING_NAME) == 0)
-		return _("OLPC Mesh connection");
-	if (strcmp (name, NM_SETTING_ADSL_SETTING_NAME) == 0)
-		return _("ADSL connection");
-	if (strcmp (name, NM_SETTING_MACSEC_SETTING_NAME) == 0)
-		return _("MACsec connection");
-	if (strcmp (name, NM_SETTING_MACVLAN_SETTING_NAME) == 0)
-		return _("macvlan connection");
-	if (strcmp (name, NM_SETTING_VXLAN_SETTING_NAME) == 0)
-		return _("VXLAN connection");
-	if (strcmp (name, NM_SETTING_TUN_SETTING_NAME) == 0)
-		return _("Tun device");
-	if (strcmp (name, NM_SETTING_IP4_CONFIG_SETTING_NAME) == 0)
-		return _("IPv4 protocol");
-	if (strcmp (name, NM_SETTING_IP6_CONFIG_SETTING_NAME) == 0)
-		return _("IPv6 protocol");
-	if (strcmp (name, NM_SETTING_PROXY_SETTING_NAME) == 0)
-		return _("Proxy");
-
-	/* Should not happen; but let's still try to be somewhat sensible. */
-	return name;
-}
-
 static gboolean
 questionnaire_one_optional (NmCli *nmc, NMConnection *connection)
 {
-	OptionInfo *candidate;
+	NMMetaSettingType base;
+	gs_unref_ptrarray GPtrArray *infos = NULL;
+	guint i, j;
+	gboolean already_confirmed = FALSE;
+	NMMetaSettingType s_asking = NM_META_SETTING_TYPE_UNKNOWN;
+	NMMetaSettingType settings[_NM_META_SETTING_TYPE_NUM];
+
+	base = connection_get_base_meta_setting_type (connection);
+
+	i = 0;
+	settings[i++] = NM_META_SETTING_TYPE_CONNECTION;
+	settings[i++] = base;
+	for (j = 0; j < _NM_META_SETTING_TYPE_NUM; j++) {
+		if (!NM_IN_SET (j, NM_META_SETTING_TYPE_CONNECTION, base))
+			settings[i++] = j;
+	}
 
-	/* Optional settings. */
-	const gchar *setting_name = NULL;
-	int count = 0;
+	infos = g_ptr_array_new ();
 
 	/* Find first setting with relevant options and count them. */
-	for (candidate = option_info; candidate->setting_name; candidate++) {
-		if (!option_relevant (connection, candidate))
+again:
+	for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+		const NMMetaPropertyInfo *const*property_infos;
+		guint p;
+
+		if (   s_asking != NM_META_SETTING_TYPE_UNKNOWN
+		    && settings[i] != s_asking)
 			continue;
-		if (!setting_name)
-			setting_name = candidate->setting_name;
-		else if (strcmp (setting_name, candidate->setting_name))
+
+		property_infos = nm_meta_setting_infos_editor[settings[i]].properties;
+		if (!property_infos)
+			continue;
+		for (p = 0; property_infos[p]; p++) {
+			const NMMetaPropertyInfo *property_info = property_infos[p];
+
+			if (_meta_property_needs_bond_hack (property_info)) {
+				for (j = 0; j < nm_meta_property_typ_data_bond.nested_len; j++) {
+					const NMMetaNestedPropertyInfo *bi = &nm_meta_property_typ_data_bond.nested[j];
+
+					if (!option_relevant (connection, (const NMMetaAbstractInfo *) bi))
+						continue;
+					g_ptr_array_add (infos, (gpointer) bi);
+				}
+			} else {
+				if (!property_info->is_cli_option)
+					continue;
+				if (!option_relevant (connection, (const NMMetaAbstractInfo *) property_info))
+					continue;
+				g_ptr_array_add (infos, (gpointer) property_info);
+			}
+		}
+		if (infos->len) {
+			s_asking = settings[i];
 			break;
-		count++;
+		}
 	}
-	if (!setting_name)
-		return FALSE;
 
-	/* Now ask for the settings. */
-	if (want_provide_opt_args (setting_name_to_name (setting_name), count)) {
-		for (candidate = option_info; candidate->setting_name; candidate++) {
-			if (!option_relevant (connection, candidate))
-				continue;
-			if (strcmp (setting_name, candidate->setting_name))
-				continue;
-			ask_option (nmc, connection, candidate);
+	if (infos->len) {
+		const NMMetaSettingInfoEditor *setting_info = NULL;
+
+		_meta_abstract_get (infos->pdata[0], &setting_info, NULL, NULL, NULL, NULL, NULL, NULL);
+
+		/* Now ask for the settings. */
+		if (   already_confirmed
+			|| want_provide_opt_args (_(setting_info->pretty_name), infos->len)) {
+			ask_option (nmc, connection, infos->pdata[0]);
+			already_confirmed = TRUE;
+			/* asking for an option may enable other options. Create the list again. */
+			g_ptr_array_set_size (infos, 0);
+			goto again;
 		}
 	}
 
-	/* Make sure we won't ask again. */
-	disable_options (setting_name, NULL);
+	if (s_asking == NM_META_SETTING_TYPE_UNKNOWN)
+		return FALSE;
 
+	/* Make sure we won't ask again. */
+	disable_options (nm_meta_setting_infos[s_asking].setting_name, NULL);
 	return TRUE;
 }
 
@@ -4967,8 +4717,8 @@ do_connection_add (NmCli *nmc, int argc, char **argv)
 	GError *error = NULL;
 	AddConnectionInfo *info = NULL;
 	gboolean save_bool = TRUE;
-	OptionInfo *candidate;
 	gboolean seen_dash_dash = FALSE;
+	NMMetaSettingType s;
 
 	next_arg (nmc, &argc, &argv, NULL);
 
@@ -5052,8 +4802,9 @@ read_properties:
 			const GPtrArray *connections;
 
 			connections = nm_client_get_connections (nmc->client);
-			try_name = ifname ? g_strdup_printf ("%s-%s", get_name_alias (type, slave_type, nmc_valid_connection_types), ifname)
-					  : g_strdup (get_name_alias (type, slave_type, nmc_valid_connection_types));
+			try_name = ifname
+			           ? g_strdup_printf ("%s-%s", get_name_alias_toplevel (type, slave_type), ifname)
+			           : g_strdup (get_name_alias_toplevel (type, slave_type));
 			default_name = nmc_unique_connection_name (connections, try_name);
 			g_free (try_name);
 			g_object_set (s_con, NM_SETTING_CONNECTION_ID, default_name, NULL);
@@ -5075,13 +4826,41 @@ read_properties:
 	 * from doing something that's not likely to make sense (such as missing ifname
 	 * on a bond/bridge/team, etc.). Added just to preserve traditional behavior, it
 	 * perhaps is a good idea to just remove this. */
-	for (candidate = option_info; candidate->setting_name; candidate++) {
-		if (!option_relevant (connection, candidate))
+	for (s = 0; s < _NM_META_SETTING_TYPE_NUM; s++) {
+		const NMMetaPropertyInfo *const*property_infos;
+		guint p;
+
+		property_infos = nm_meta_setting_infos_editor[s].properties;
+		if (!property_infos)
 			continue;
-		if (candidate->flags & OPTION_REQD) {
-			g_string_printf (nmc->return_text, _("Error: '%s' argument is required."), candidate->option);
-			nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-			goto finish;
+		for (p = 0; property_infos[p]; p++) {
+			const NMMetaPropertyInfo *property_info = property_infos[p];
+
+			if (_meta_property_needs_bond_hack (property_info)) {
+				guint i;
+
+				for (i = 0; i < nm_meta_property_typ_data_bond.nested_len; i++) {
+					const NMMetaNestedPropertyInfo *bi = &nm_meta_property_typ_data_bond.nested[i];
+
+					if (!option_relevant (connection, (const NMMetaAbstractInfo *) bi))
+						continue;
+					if (bi->base.inf_flags & NM_META_PROPERTY_INF_FLAG_REQD) {
+						g_string_printf (nmc->return_text, _("Error: '%s' argument is required."), bi->base.property_alias);
+						nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+						goto finish;
+					}
+				}
+			} else {
+				if (!property_info->is_cli_option)
+					continue;
+				if (!option_relevant (connection, (const NMMetaAbstractInfo *) property_info))
+					continue;
+				if (property_info->inf_flags & NM_META_PROPERTY_INF_FLAG_REQD) {
+					g_string_printf (nmc->return_text, _("Error: '%s' argument is required."), property_info->property_alias);
+					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+					goto finish;
+				}
+			}
 		}
 	}
 
@@ -5106,7 +4885,7 @@ finish:
 	return nmc->return_value;
 }
 
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
 /* Functions for readline TAB completion in editor */
 
 static void
@@ -5226,28 +5005,33 @@ gen_cmd_save (const char *text, int state)
 	return nmc_rl_gen_func_basic (text, state, words);
 }
 
-static char *
-gen_connection_types (const char *text, int state)
+static rl_compentry_func_t *
+gen_connection_types (const char *text)
 {
-	static int list_idx, len;
-	const char *c_type, *a_type;
+	gs_free char **values = NULL;
+	const NMMetaSettingInfoEditor *editor;
+	GPtrArray *array;
+	int i;
 
-	if (!state) {
-		list_idx = 0;
-		len = strlen (text);
-	}
+	array = g_ptr_array_new ();
 
-	while (nmc_valid_connection_types[list_idx].name) {
-		a_type = nmc_valid_connection_types[list_idx].alias;
-		c_type = nmc_valid_connection_types[list_idx].name;
-		list_idx++;
-		if (a_type && !strncmp (text, a_type, len))
-			return g_strdup (a_type);
-		if (c_type && !strncmp (text, c_type, len))
-			return g_strdup (c_type);
+	for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+		editor = &nm_meta_setting_infos_editor[i];
+		if (!editor->valid_parts)
+			continue;
+		g_ptr_array_add (array, (gpointer) nm_meta_setting_infos[i].setting_name);
+		if (editor->alias)
+			g_ptr_array_add (array, (gpointer) editor->alias);
 	}
 
-	return NULL;
+	g_ptr_array_add (array, "bond-slave");
+	g_ptr_array_add (array, "bridge-slave");
+	g_ptr_array_add (array, "team-slave");
+	g_ptr_array_add (array, NULL);
+
+	values = (char **) g_ptr_array_free (array, FALSE);
+
+	return nmc_rl_compentry_func_wrap ((const char *const*) values);
 }
 
 static char *
@@ -5255,10 +5039,9 @@ gen_setting_names (const char *text, int state)
 {
 	static int list_idx, len, is_slv;
 	const char *s_name, *a_name;
-	const NameItem *valid_settings_arr;
+	const NMMetaSettingValidPartItem *const*valid_settings_arr;
 	NMSettingConnection *s_con;
 	const char *s_type = NULL;
-	char *slv_type;
 
 	if (!state) {
 		list_idx = 0;
@@ -5268,11 +5051,13 @@ gen_setting_names (const char *text, int state)
 
 	if (!is_slv) {
 		valid_settings_arr = get_valid_settings_array (nmc_tab_completion.con_type);
-		if (!valid_settings_arr)
+		if (list_idx >= NM_PTRARRAY_LEN (valid_settings_arr))
 			return NULL;
-		while (valid_settings_arr[list_idx].name) {
-			a_name = valid_settings_arr[list_idx].alias;
-			s_name = valid_settings_arr[list_idx].name;
+		for (; valid_settings_arr[list_idx];) {
+			const NMMetaSettingInfoEditor *setting_info = valid_settings_arr[list_idx]->setting_info;
+
+			a_name = setting_info->alias;
+			s_name = setting_info->general->setting_name;
 			list_idx++;
 			if (len == 0 && a_name)
 				return g_strdup_printf ("%s (%s)", s_name, a_name);
@@ -5291,20 +5076,22 @@ gen_setting_names (const char *text, int state)
 	s_con = nm_connection_get_setting_connection (nmc_tab_completion.connection);
 	if (s_con)
 		s_type = nm_setting_connection_get_slave_type (s_con);
-	slv_type = g_strdup_printf ("%s-slave", s_type ? s_type : "no");
-	valid_settings_arr = get_valid_settings_array (slv_type);
-	g_free (slv_type);
-
-	while (valid_settings_arr[list_idx].name) {
-		a_name = valid_settings_arr[list_idx].alias;
-		s_name = valid_settings_arr[list_idx].name;
-		list_idx++;
-		if (len == 0 && a_name)
-			return g_strdup_printf ("%s (%s)", s_name, a_name);
-		if (a_name && !strncmp (text, a_name, len))
-			return g_strdup (a_name);
-		if (s_name && !strncmp (text, s_name, len))
-			return g_strdup (s_name);
+	valid_settings_arr = nm_meta_setting_info_valid_parts_for_slave_type (s_type, NULL);
+
+	if (list_idx < NM_PTRARRAY_LEN (valid_settings_arr)) {
+		while (valid_settings_arr[list_idx]) {
+			const NMMetaSettingInfoEditor *setting_info = valid_settings_arr[list_idx]->setting_info;
+
+			a_name = setting_info->alias;
+			s_name = setting_info->general->setting_name;
+			list_idx++;
+			if (len == 0 && a_name)
+				return g_strdup_printf ("%s (%s)", s_name, a_name);
+			if (a_name && !strncmp (text, a_name, len))
+				return g_strdup (a_name);
+			if (s_name && !strncmp (text, s_name, len))
+				return g_strdup (s_name);
+		}
 	}
 
 	return NULL;
@@ -5319,8 +5106,8 @@ gen_property_names (const char *text, int state)
 	const char *line = rl_line_buffer;
 	const char *setting_name;
 	char **strv = NULL;
-	const NameItem *valid_settings_main;
-	const NameItem *valid_settings_slave;
+	const NMMetaSettingValidPartItem *const*valid_settings_main;
+	const NMMetaSettingValidPartItem *const*valid_settings_slave;
 	const char *p1;
 	const char *slv_type;
 
@@ -5330,7 +5117,7 @@ gen_property_names (const char *text, int state)
 		while (p1 > line && !g_ascii_isspace (*p1))
 			p1--;
 
-		strv = g_strsplit (p1+1, ".", 2);
+		strv = g_strsplit (p1 + 1, ".", 2);
 
 		valid_settings_main = get_valid_settings_array (nmc_tab_completion.con_type);
 
@@ -5338,19 +5125,24 @@ gen_property_names (const char *text, int state)
 		 * guessing the slave type from the setting name already
 		 * typed (or autocompleted) */
 		if (nm_streq0 (strv[0], NM_SETTING_TEAM_PORT_SETTING_NAME))
-			slv_type = "team-slave";
+			slv_type = NM_SETTING_TEAM_SETTING_NAME;
 		else if (nm_streq0 (strv[0], NM_SETTING_BRIDGE_PORT_SETTING_NAME))
-			slv_type = "bridge-slave";
+			slv_type = NM_SETTING_BRIDGE_SETTING_NAME;
 		else
-			slv_type = "no-slave";
-		valid_settings_slave = get_valid_settings_array (slv_type);
+			slv_type = NULL;
+		valid_settings_slave = nm_meta_setting_info_valid_parts_for_slave_type (slv_type, NULL);
 
 		setting_name = check_valid_name (strv[0],
 		                                 valid_settings_main,
 		                                 valid_settings_slave,
 		                                 NULL);
-		setting = nmc_setting_new_for_name (setting_name);
-	} else {
+		if (setting_name) {
+			setting = nm_meta_setting_info_editor_new_setting (nm_meta_setting_info_editor_find_by_name (setting_name, FALSE),
+			                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_DEFAULT);
+		}
+	}
+
+	if (!setting) {
 		/* Else take the current setting, if any */
 		setting = nmc_tab_completion.setting ? g_object_ref (nmc_tab_completion.setting) : NULL;
 	}
@@ -5628,15 +5420,14 @@ static void
 get_setting_and_property (const char *prompt, const char *line,
                           NMSetting **setting_out, char**property_out)
 {
-	const NameItem *valid_settings_main;
-	const NameItem *valid_settings_slave;
+	const NMMetaSettingValidPartItem *const*valid_settings_main;
+	const NMMetaSettingValidPartItem *const*valid_settings_slave;
 	const char *setting_name;
 	NMSetting *setting = NULL;
 	char *property = NULL;
 	char *sett = NULL, *prop = NULL;
 	NMSettingConnection *s_con;
 	const char *s_type = NULL;
-	char *slv_type;
 
 	extract_setting_and_property (prompt, line, &sett, &prop);
 	if (sett) {
@@ -5644,15 +5435,14 @@ get_setting_and_property (const char *prompt, const char *line,
 		s_con = nm_connection_get_setting_connection (nmc_tab_completion.connection);
 		if (s_con)
 			s_type = nm_setting_connection_get_slave_type (s_con);
-		slv_type = g_strdup_printf ("%s-slave", s_type ? s_type : "no");
 
 		valid_settings_main = get_valid_settings_array (nmc_tab_completion.con_type);
-		valid_settings_slave = get_valid_settings_array (slv_type);
-		g_free (slv_type);
+		valid_settings_slave = nm_meta_setting_info_valid_parts_for_slave_type (s_type, NULL);
 
 		setting_name = check_valid_name (sett, valid_settings_main,
 		                                 valid_settings_slave,  NULL);
-		setting = nmc_setting_new_for_name (setting_name);
+		setting = nm_meta_setting_info_editor_new_setting (nm_meta_setting_info_editor_find_by_name (setting_name, FALSE),
+		                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_DEFAULT);
 	} else
 		setting = nmc_tab_completion.setting ? g_object_ref (nmc_tab_completion.setting) : NULL;
 
@@ -5723,27 +5513,24 @@ should_complete_vpn_uuids (const char *prompt, const char *line)
 	return _get_and_check_property (prompt, line, uuid_properties, NULL, NULL);
 }
 
-static const char **
-get_allowed_property_values (void)
+static const char *const*
+get_allowed_property_values (char ***out_to_free)
 {
-	NMSetting *setting;
-	char *property;
-	const char **avals = NULL;
+	gs_unref_object NMSetting *setting = NULL;
+	gs_free char *property = NULL;
+	const char *const*avals = NULL;
 
 	get_setting_and_property (rl_prompt, rl_line_buffer, &setting, &property);
 	if (setting && property)
-		avals = nmc_setting_get_property_allowed_values (setting, property);
-
-	if (setting)
-		g_object_unref (setting);
-	g_free (property);
-
+		avals = nmc_setting_get_property_allowed_values (setting, property, out_to_free);
 	return avals;
 }
 
 static gboolean
 should_complete_property_values (const char *prompt, const char *line, gboolean *multi)
 {
+	gs_strfreev char **to_free = NULL;
+
 	/* properties allowing multiple values */
 	const char *multi_props[] = {
 		/* '802-1x' properties */
@@ -5759,10 +5546,9 @@ should_complete_property_values (const char *prompt, const char *line, gboolean
 		NULL
 	};
 	_get_and_check_property (prompt, line, NULL, multi_props, multi);
-	return get_allowed_property_values () != NULL;
+	return !!get_allowed_property_values (&to_free);
 }
 
-//FIXME: this helper should go to libnm later
 static gboolean
 _setting_property_is_boolean (NMSetting *setting, const char *property_name)
 {
@@ -5798,13 +5584,13 @@ should_complete_boolean (const char *prompt, const char *line)
 static char *
 gen_property_values (const char *text, int state)
 {
-	char *ret = NULL;
-	const char **avals;
+	gs_strfreev char **to_free = NULL;
+	const char *const*avals;
 
-	avals = get_allowed_property_values ();
-	if (avals)
-		ret = nmc_rl_gen_func_basic (text, state, avals);
-	return ret;
+	avals = get_allowed_property_values (&to_free);
+	if (!avals)
+		return NULL;
+	return nmc_rl_gen_func_basic (text, state, avals);
 }
 
 /* from readline */
@@ -5847,7 +5633,7 @@ nmcli_editor_tab_completion (const char *text, int start, int end)
 
 	/* Choose the right generator function */
 	if (strcmp (prompt_tmp, EDITOR_PROMPT_CON_TYPE) == 0)
-		generator_func = gen_connection_types;
+		generator_func = gen_connection_types (text);
 	else if (strcmp (prompt_tmp, EDITOR_PROMPT_SETTING) == 0)
 		generator_func = gen_setting_names;
 	else if (strcmp (prompt_tmp, EDITOR_PROMPT_PROPERTY) == 0)
@@ -6033,19 +5819,16 @@ save_history_cmds (const char *uuid)
 	}
 }
 
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
 
 static void
 editor_show_connection (NMConnection *connection, NmCli *nmc)
 {
-	nmc->print_output = NMC_PRINT_PRETTY;
-	nmc->multiline_output = TRUE;
-	nmc->escape_values = 0;
-
-	/* Remove any previous data */
-	nmc_empty_output_fields (nmc);
+	nmc->nmc_config_mutable.print_output = NMC_PRINT_PRETTY;
+	nmc->nmc_config_mutable.multiline_output = TRUE;
+	nmc->nmc_config_mutable.escape_values = 0;
 
-	nmc_connection_profile_details (connection, nmc, nmc->editor_show_secrets);
+	nmc_connection_profile_details (connection, nmc);
 }
 
 static void
@@ -6054,14 +5837,11 @@ editor_show_setting (NMSetting *setting, NmCli *nmc)
 	g_print (_("['%s' setting values]\n"),
 	         nm_setting_get_name (setting));
 
-	nmc->print_output = NMC_PRINT_NORMAL;
-	nmc->multiline_output = TRUE;
-	nmc->escape_values = 0;
+	nmc->nmc_config_mutable.print_output = NMC_PRINT_NORMAL;
+	nmc->nmc_config_mutable.multiline_output = TRUE;
+	nmc->nmc_config_mutable.escape_values = 0;
 
-	/* Remove any previous data */
-	nmc_empty_output_fields (nmc);
-
-	setting_details (setting, nmc, NULL, nmc->editor_show_secrets);
+	setting_details (&nmc->nmc_config, setting, NULL);
 }
 
 typedef enum {
@@ -6392,12 +6172,13 @@ editor_sub_usage (const char *command)
 	}
 }
 
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
 
 typedef struct {
 	NMDevice *device;
 	NMActiveConnection *ac;
 	guint monitor_id;
+	NmCli *nmc;
 } MonitorACInfo;
 
 static gboolean nmc_editor_cb_called;
@@ -6475,6 +6256,14 @@ progress_activation_editor_cb (gpointer user_data)
 		goto finish; /* we are done */
 	}
 
+	if (info->nmc->secret_agent) {
+		NMRemoteConnection *connection;
+
+		connection = nm_active_connection_get_connection (ac);
+		nm_secret_agent_simple_enable (NM_SECRET_AGENT_SIMPLE (info->nmc->secret_agent),
+		                               nm_object_get_path (NM_OBJECT (connection)));
+	}
+
 	return TRUE;
 
 finish:
@@ -6510,6 +6299,7 @@ activate_connection_editor_cb (GObject *client,
 			monitor_ac_info->device = g_object_ref (device);
 			monitor_ac_info->ac = active;
 			monitor_ac_info->monitor_id = g_timeout_add (120, progress_activation_editor_cb, monitor_ac_info);
+			monitor_ac_info->nmc = info->nmc;
 		} else
 			g_object_unref (active);
 	}
@@ -6517,7 +6307,7 @@ activate_connection_editor_cb (GObject *client,
 	g_clear_error (&error);
 }
 
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
 
 static void
 print_property_description (NMSetting *setting, const char *prop_name)
@@ -6525,8 +6315,10 @@ print_property_description (NMSetting *setting, const char *prop_name)
 	char *desc;
 
 	desc = nmc_setting_get_property_desc (setting, prop_name);
-	g_print ("\n=== [%s] ===\n%s\n", prop_name, desc);
-	g_free (desc);
+	if (desc) {
+		g_print ("\n=== [%s] ===\n%s\n", prop_name, desc);
+		g_free (desc);
+	}
 }
 
 static void
@@ -6613,7 +6405,7 @@ confirm_quit (void)
 	                         "Do you really want to quit? %s"),
 	                       prompt_yes_no (FALSE, NULL));
 	answer = answer ? g_strstrip (answer) : NULL;
-	if (answer && matches (answer, WORD_LOC_YES))
+	if (answer && matches (answer, WORD_YES))
 		want_quit = TRUE;
 
 	g_free (answer);
@@ -6647,7 +6439,7 @@ property_edit_submenu (NmCli *nmc,
 	/* Set global variable for use in TAB completion */
 	nmc_tab_completion.property = prop_name;
 
-	prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
+	prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NM_META_TERM_FORMAT_NORMAL,
 	                       "nmcli %s.%s> ",
 	                       nm_setting_get_name (curr_setting), prop_name);
 
@@ -6680,12 +6472,16 @@ property_edit_submenu (NmCli *nmc,
 			 * single values:  : both SET and ADD sets the new value
 			 */
 			if (!cmd_property_arg) {
-				const char **avals = nmc_setting_get_property_allowed_values (curr_setting, prop_name);
+				gs_strfreev char **to_free = NULL;
+				const char *const*avals;
+
+				avals = nmc_setting_get_property_allowed_values (curr_setting, prop_name, &to_free);
 				if (avals) {
-					char *avals_str = nmc_util_strv_for_display (avals, FALSE);
+					gs_free char *avals_str = NULL;
+
+					avals_str = nmc_util_strv_for_display (avals, FALSE);
 					g_print (_("Allowed values for '%s' property: %s\n"),
 					         prop_name, avals_str);
-					g_free (avals_str);
 				}
 				prop_val_user = nmc_readline (_("Enter '%s' value: "), prop_name);
 			} else
@@ -6851,7 +6647,7 @@ split_editor_main_cmd_args (const char *str, char **setting, char **property, ch
 }
 
 static NMSetting *
-create_setting_by_name (const char *name, const NameItem *valid_settings_main, const NameItem *valid_settings_slave)
+create_setting_by_name (const char *name, const NMMetaSettingValidPartItem *const*valid_settings_main, const NMMetaSettingValidPartItem *const*valid_settings_slave)
 {
 	const char *setting_name;
 	NMSetting *setting = NULL;
@@ -6860,18 +6656,16 @@ create_setting_by_name (const char *name, const NameItem *valid_settings_main, c
 	setting_name = check_valid_name (name, valid_settings_main, valid_settings_slave, NULL);
 
 	if (setting_name) {
-		setting = nmc_setting_new_for_name (setting_name);
-		if (!setting)
-			return NULL; /* This should really not happen */
-		nmc_setting_custom_init (setting);
+		setting = nm_meta_setting_info_editor_new_setting (nm_meta_setting_info_editor_find_by_name (setting_name, FALSE),
+		                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
 	}
 	return setting;
 }
 
 static const char *
 ask_check_setting (const char *arg,
-                   const NameItem *valid_settings_main,
-                   const NameItem *valid_settings_slave,
+                   const NMMetaSettingValidPartItem *const*valid_settings_main,
+                   const NMMetaSettingValidPartItem *const*valid_settings_slave,
                    const char *valid_settings_str)
 {
 	char *setting_name_user;
@@ -6961,7 +6755,7 @@ confirm_connection_saving (NMConnection *local, NMConnection *remote)
 		                         "That might result in an immediate activation of the connection.\n"
 		                         "Do you still want to save? %s"), prompt_yes_no (TRUE, NULL));
 		answer = answer ? g_strstrip (answer) : NULL;
-		if (!answer || matches (answer, WORD_LOC_YES))
+		if (!answer || matches (answer, WORD_YES))
 			confirmed = TRUE;
 		else
 			confirmed = FALSE;
@@ -6979,14 +6773,14 @@ typedef	struct {
 } NmcEditorMenuContext;
 
 static void
-menu_switch_to_level0 (NmCli *nmc,
+menu_switch_to_level0 (NmcColorOption color_option,
                        NmcEditorMenuContext *menu_ctx,
                        const char *prompt,
-                       NmcTermColor prompt_color)
+                       NMMetaTermColor prompt_color)
 {
 	menu_ctx->level = 0;
 	g_free (menu_ctx->main_prompt);
-	menu_ctx->main_prompt = nmc_colorize (nmc, prompt_color, NMC_TERM_FORMAT_NORMAL, "%s", prompt);
+	menu_ctx->main_prompt = nmc_colorize (color_option, prompt_color, NM_META_TERM_FORMAT_NORMAL, "%s", prompt);
 	menu_ctx->curr_setting = NULL;
 	g_strfreev (menu_ctx->valid_props);
 	menu_ctx->valid_props = NULL;
@@ -6995,15 +6789,15 @@ menu_switch_to_level0 (NmCli *nmc,
 }
 
 static void
-menu_switch_to_level1 (NmCli *nmc,
+menu_switch_to_level1 (NmcColorOption color_option,
                        NmcEditorMenuContext *menu_ctx,
                        NMSetting *setting,
                        const char *setting_name,
-                       NmcTermColor prompt_color)
+                       NMMetaTermColor prompt_color)
 {
 	menu_ctx->level = 1;
 	g_free (menu_ctx->main_prompt);
-	menu_ctx->main_prompt = nmc_colorize (nmc, prompt_color, NMC_TERM_FORMAT_NORMAL,
+	menu_ctx->main_prompt = nmc_colorize (color_option, prompt_color, NM_META_TERM_FORMAT_NORMAL,
 	                                      "nmcli %s> ", setting_name);
 	menu_ctx->curr_setting = setting;
 	g_strfreev (menu_ctx->valid_props);
@@ -7013,47 +6807,37 @@ menu_switch_to_level1 (NmCli *nmc,
 }
 
 static gboolean
-editor_menu_main (NmCli *nmc, NMConnection *connection)
+editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_type)
 {
+	gs_unref_object NMRemoteConnection *rem_con = NULL;
 	NMSettingConnection *s_con;
-	NMRemoteConnection *rem_con;
 	NMRemoteConnection *con_tmp;
 	GWeakRef weak = { { NULL } };
 	gboolean removed;
 	NmcEditorMainCmd cmd;
-	char *cmd_user;
 	gboolean cmd_loop = TRUE;
-	char *cmd_arg = NULL;
-	char *cmd_arg_s, *cmd_arg_p, *cmd_arg_v;
-	const NameItem *valid_settings_main = NULL;
-	const NameItem *valid_settings_slave = NULL;
-	char *valid_settings_str = NULL;
+	const NMMetaSettingValidPartItem *const*valid_settings_main;
+	const NMMetaSettingValidPartItem *const*valid_settings_slave;
+	gs_free char *valid_settings_str = NULL;
 	const char *s_type = NULL;
-	char *slv_type;
 	AddConnectionInfo *info = NULL;
 	gboolean dirty;
 	gboolean temp_changes;
 	GError *err1 = NULL;
-	NmcEditorMenuContext menu_ctx;
+	NmcEditorMenuContext menu_ctx = { 0 };
 
 	s_con = nm_connection_get_setting_connection (connection);
 	if (s_con)
 		s_type = nm_setting_connection_get_slave_type (s_con);
-	slv_type = g_strdup_printf ("%s-slave", s_type ? s_type : "no");
 
-	valid_settings_main = get_valid_settings_array (nm_connection_get_connection_type (connection));
-	valid_settings_slave = get_valid_settings_array (slv_type);
-	g_free (slv_type);
+	valid_settings_main = get_valid_settings_array (connection_type);
+	valid_settings_slave = nm_meta_setting_info_valid_parts_for_slave_type (s_type, NULL);
 
 	valid_settings_str = get_valid_options_string (valid_settings_main, valid_settings_slave);
 	g_print (_("You may edit the following settings: %s\n"), valid_settings_str);
 
-	menu_ctx.level = 0;
-	menu_ctx.main_prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
+	menu_ctx.main_prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NM_META_TERM_FORMAT_NORMAL,
 	                                     BASE_PROMPT);
-	menu_ctx.curr_setting = NULL;
-	menu_ctx.valid_props = NULL;
-	menu_ctx.valid_props_str = NULL;
 
 	/* Get remote connection */
 	con_tmp = nm_client_get_connection_by_uuid (nmc->client,
@@ -7062,6 +6846,12 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 	rem_con = g_weak_ref_get (&weak);
 
 	while (cmd_loop) {
+		gs_free char *cmd_user = NULL;
+		gs_free char *cmd_arg = NULL;
+		gs_free char *cmd_arg_s = NULL;
+		gs_free char *cmd_arg_p = NULL;
+		gs_free char *cmd_arg_v = NULL;
+
 		/* Connection is dirty? (not saved or differs from the saved) */
 		dirty = is_connection_dirty (connection, rem_con);
 		temp_changes = rem_con ? nm_remote_connection_get_unsaved (rem_con) : TRUE;
@@ -7081,18 +6871,16 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 			continue;
 		cmd = parse_editor_main_cmd (g_strstrip (cmd_user), &cmd_arg);
 
-		cmd_arg_s = NULL;
-		cmd_arg_p = NULL;
-		cmd_arg_v = NULL;
 		split_editor_main_cmd_args (cmd_arg, &cmd_arg_s, &cmd_arg_p, &cmd_arg_v);
 		switch (cmd) {
 		case NMC_EDITOR_MAIN_CMD_SET:
 			/* Set property value */
 			if (!cmd_arg) {
 				if (menu_ctx.level == 1) {
+					gs_strfreev char **avals_to_free = NULL;
+					gs_free char *prop_val_user = NULL;
 					const char *prop_name;
-					char *prop_val_user = NULL;
-					const char **avals;
+					const char *const*avals;
 					GError *tmp_err = NULL;
 
 					prop_name = ask_check_property (cmd_arg,
@@ -7101,12 +6889,13 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 					if (!prop_name)
 						break;
 
-					avals = nmc_setting_get_property_allowed_values (menu_ctx.curr_setting, prop_name);
+					avals = nmc_setting_get_property_allowed_values (menu_ctx.curr_setting, prop_name, &avals_to_free);
 					if (avals) {
-						char *avals_str = nmc_util_strv_for_display (avals, FALSE);
+						gs_free char *avals_str = NULL;
+
+						avals_str = nmc_util_strv_for_display (avals, FALSE);
 						g_print (_("Allowed values for '%s' property: %s\n"),
 						         prop_name, avals_str);
-						g_free (avals_str);
 					}
 					prop_val_user = nmc_readline (_("Enter '%s' value: "), prop_name);
 
@@ -7120,22 +6909,22 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 					g_print (_("use 'goto <setting>' first, or 'set <setting>.<property>'\n"));
 				}
 			} else {
+				gs_free char *prop_name = NULL;
+				gs_unref_object NMSetting *ss_created = NULL;
 				NMSetting *ss = NULL;
-				gboolean created_ss = FALSE;
-				char *prop_name;
 				GError *tmp_err = NULL;
 
 				if (cmd_arg_s) {
 					/* setting provided as "setting.property" */
 					ss = is_setting_valid (connection, valid_settings_main, valid_settings_slave, cmd_arg_s);
 					if (!ss) {
-						ss = create_setting_by_name (cmd_arg_s, valid_settings_main, valid_settings_slave);
+						ss_created = create_setting_by_name (cmd_arg_s, valid_settings_main, valid_settings_slave);
+						ss = ss_created;
 						if (!ss) {
 							g_print (_("Error: invalid setting argument '%s'; valid are [%s]\n"),
 							         cmd_arg_s, valid_settings_str);
 							break;
 						}
-						created_ss = TRUE;
 					}
 				} else {
 					if (menu_ctx.curr_setting)
@@ -7150,21 +6939,21 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 				if (!prop_name) {
 					g_print (_("Error: invalid property: %s\n"), tmp_err->message);
 					g_clear_error (&tmp_err);
-					if (created_ss)
-						g_object_unref (ss);
 					break;
 				}
 
-
-
 				/* Ask for value */
 				if (!cmd_arg_v) {
-					const char **avals = nmc_setting_get_property_allowed_values (ss, prop_name);
+					gs_strfreev char **avals_to_free = NULL;
+					const char *const*avals;
+
+					avals = nmc_setting_get_property_allowed_values (ss, prop_name, &avals_to_free);
 					if (avals) {
-						char *avals_str = nmc_util_strv_for_display (avals, FALSE);
+						gs_free char *avals_str = NULL;
+
+						avals_str = nmc_util_strv_for_display (avals, FALSE);
 						g_print (_("Allowed values for '%s' property: %s\n"),
 						         prop_name, avals_str);
-						g_free (avals_str);
 					}
 					cmd_arg_v = nmc_readline (_("Enter '%s' value: "), prop_name);
 				}
@@ -7176,9 +6965,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 					g_clear_error (&tmp_err);
 				}
 
-				if (created_ss)
-					nm_connection_add_setting (connection, ss);
-				g_free (prop_name);
+				if (ss_created)
+					nm_connection_add_setting (connection, g_steal_pointer (&ss_created));
 			}
 			break;
 
@@ -7191,20 +6979,24 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 				const char *user_arg = cmd_arg_s ? cmd_arg_s : cmd_arg_p;
 
 				setting_name = ask_check_setting (user_arg,
-								  valid_settings_main,
-								  valid_settings_slave,
-								  valid_settings_str);
+				                                  valid_settings_main,
+				                                  valid_settings_slave,
+				                                  valid_settings_str);
 				if (!setting_name)
 					break;
 
 				setting = nm_connection_get_setting_by_name (connection, setting_name);
 				if (!setting) {
-					setting = nmc_setting_new_for_name (setting_name);
-					if (!setting) {
+					const NMMetaSettingInfoEditor *setting_info;
+
+					setting_info = nm_meta_setting_info_editor_find_by_name (setting_name, FALSE);
+					if (!setting_info) {
 						g_print (_("Error: unknown setting '%s'\n"), setting_name);
 						break;
 					}
-					nmc_setting_custom_init (setting);
+
+					setting = nm_meta_setting_info_editor_new_setting (setting_info,
+					                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
 
 					if (NM_IS_SETTING_WIRELESS (setting))
 						nmc_setting_wireless_connect_handlers (NM_SETTING_WIRELESS (setting));
@@ -7221,7 +7013,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 				nmc_tab_completion.setting = setting;
 
 				/* Switch to level 1 */
-				menu_switch_to_level1 (nmc, &menu_ctx, setting, setting_name, nmc->editor_prompt_color);
+				menu_switch_to_level1 (nmc->nmc_config.use_colors, &menu_ctx, setting, setting_name, nmc->editor_prompt_color);
 
 				if (!cmd_arg_s) {
 					g_print (_("You may edit the following properties: %s\n"), menu_ctx.valid_props_str);
@@ -7279,19 +7071,20 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 				user_s = descr_all ? cmd_arg_p : cmd_arg_s ? cmd_arg_s : NULL;
 				if (user_s) {
 					ss = is_setting_valid (connection,
-							       valid_settings_main,
-							       valid_settings_slave,
-							       user_s);
+					                       valid_settings_main,
+					                       valid_settings_slave,
+					                       user_s);
 					if (!ss) {
 						if (check_valid_name (user_s,
 						                      valid_settings_main,
 						                      valid_settings_slave,
-						                      NULL))
+						                      NULL)) {
 							g_print (_("Setting '%s' is not present in the connection.\n"),
-								 user_s);
-						else
+							         user_s);
+						} else {
 							g_print (_("Error: invalid setting argument '%s'; valid are [%s]\n"),
 							         user_s, valid_settings_str);
+						}
 						break;
 					}
 				} else
@@ -7302,12 +7095,14 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 					connection_remove_setting (connection, ss);
 					if (ss == menu_ctx.curr_setting) {
 						/* If we removed the setting we are in, go up */
-						menu_switch_to_level0 (nmc, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
+						menu_switch_to_level0 (nmc->nmc_config.use_colors, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
 						nmc_tab_completion.setting = NULL;  /* for TAB completion */
 					}
 				} else {
+					gs_free char *prop_name = NULL;
 					GError *tmp_err = NULL;
-					char *prop_name = is_property_valid (ss, cmd_arg_p, &tmp_err);
+
+					prop_name = is_property_valid (ss, cmd_arg_p, &tmp_err);
 					if (prop_name) {
 						/* Delete property value */
 						if (!nmc_setting_reset_property (ss, prop_name, &tmp_err)) {
@@ -7319,16 +7114,16 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 						/* If the string is not a property, try it as a setting */
 						NMSetting *s_tmp;
 						s_tmp = is_setting_valid (connection,
-									  valid_settings_main,
-									  valid_settings_slave,
-									  cmd_arg_p);
+						                          valid_settings_main,
+						                          valid_settings_slave,
+						                          cmd_arg_p);
 						if (s_tmp) {
 							/* Remove setting from the connection */
 							connection_remove_setting (connection, s_tmp);
 							/* coverity[copy_paste_error] - suppress Coverity COPY_PASTE_ERROR defect */
 							if (ss == menu_ctx.curr_setting) {
 								/* If we removed the setting we are in, go up */
-								menu_switch_to_level0 (nmc, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
+								menu_switch_to_level0 (nmc->nmc_config.use_colors, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
 								nmc_tab_completion.setting = NULL;  /* for TAB completion */
 							}
 						} else
@@ -7336,7 +7131,6 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 							         tmp_err->message);
 						g_clear_error (&tmp_err);
 					}
-					g_free (prop_name);
 				}
 			}
 			break;
@@ -7360,8 +7154,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 					g_print (_("use 'goto <setting>' first, or 'describe <setting>.<property>'\n"));
 				}
 			} else {
+				gs_unref_object NMSetting *ss_free = NULL;
 				NMSetting *ss = NULL;
-				gboolean unref_ss = FALSE;
 				gboolean descr_all;
 				char *user_s;
 
@@ -7370,39 +7164,45 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 				user_s = descr_all ? cmd_arg_p : cmd_arg_s ? cmd_arg_s : NULL;
 				if (user_s) {
 					ss = is_setting_valid (connection,
-							       valid_settings_main,
-							       valid_settings_slave,
-							       user_s);
+					                       valid_settings_main,
+					                       valid_settings_slave,
+					                       user_s);
 					if (!ss) {
 						ss = create_setting_by_name (user_s,
-									     valid_settings_main,
-									     valid_settings_slave);
+						                             valid_settings_main,
+						                             valid_settings_slave);
 						if (!ss) {
 							g_print (_("Error: invalid setting argument '%s'; valid are [%s]\n"),
 							         user_s, valid_settings_str);
 							break;
 						}
-						unref_ss = TRUE;
+						ss_free = ss;
 					}
 				} else
 					ss = menu_ctx.curr_setting;
 
-				if (descr_all) {
+				if (!ss) {
+					g_print (_("Error: no setting selected; valid are [%s]\n"), valid_settings_str);
+					g_print (_("use 'goto <setting>' first, or 'describe <setting>.<property>'\n"));
+				} else if (descr_all) {
 					/* Show description for all properties */
 					print_setting_description (ss);
 				} else {
 					GError *tmp_err = NULL;
-					char *prop_name = is_property_valid (ss, cmd_arg_p, &tmp_err);
+					gs_free char *prop_name = NULL;
+
+					prop_name = is_property_valid (ss, cmd_arg_p, &tmp_err);
 					if (prop_name) {
 						/* Show property description */
 						print_property_description (ss, prop_name);
 					} else {
 						/* If the string is not a property, try it as a setting */
 						NMSetting *s_tmp;
+
 						s_tmp = is_setting_valid (connection,
-									  valid_settings_main,
-									  valid_settings_slave,
-									  cmd_arg_p);
+						                          valid_settings_main,
+						                          valid_settings_slave,
+						                          cmd_arg_p);
 						if (s_tmp)
 							print_setting_description (s_tmp);
 						else
@@ -7411,10 +7211,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 							         tmp_err->message);
 						g_clear_error (&tmp_err);
 					}
-					g_free (prop_name);
 				}
-				if (unref_ss)
-					g_object_unref (ss);
 			}
 			break;
 
@@ -7433,6 +7230,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 					user_s = whole_setting ? cmd_arg_p : cmd_arg_s ? cmd_arg_s : NULL;
 					if (user_s) {
 						const char *s_name;
+
 						s_name = check_valid_name (user_s,
 						                           valid_settings_main,
 						                           valid_settings_slave,
@@ -7453,20 +7251,23 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 						/* Print the whole setting */
 						editor_show_setting (ss, nmc);
 					} else {
+						gs_free char *prop_name = NULL;
 						GError *err = NULL;
-						char *prop_name = is_property_valid (ss, cmd_arg_p, &err);
+
+						prop_name = is_property_valid (ss, cmd_arg_p, &err);
 						if (prop_name) {
 							/* Print one property */
-							char *prop_val = nmc_setting_get_property (ss, prop_name, NULL);
+							gs_free char *prop_val = NULL;
+
+							prop_val = nmc_setting_get_property (ss, prop_name, NULL);
 							g_print ("%s.%s: %s\n", nm_setting_get_name (ss),prop_name , prop_val);
-							g_free (prop_val);
 						} else {
 							/* If the string is not a property, try it as a setting */
 							NMSetting *s_tmp;
 							s_tmp = is_setting_valid (connection,
-										  valid_settings_main,
-										  valid_settings_slave,
-										  cmd_arg_p);
+							                          valid_settings_main,
+							                          valid_settings_slave,
+							                          cmd_arg_p);
 							if (s_tmp) {
 								/* Print the whole setting */
 								editor_show_setting (s_tmp, nmc);
@@ -7476,7 +7277,6 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 								         cmd_arg_s ? "" : _(", neither a valid setting name"));
 							g_clear_error (&err);
 						}
-						g_free (prop_name);
 					}
 				}
 			} else {
@@ -7587,7 +7387,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 					 * adding ipv{4,6} settings when not present.
 					 */
 					if (con_tmp) {
-						char *s_name = NULL;
+						gs_free char *s_name = NULL;
+
 						if (menu_ctx.curr_setting)
 							s_name = g_strdup (nm_setting_get_name (menu_ctx.curr_setting));
 
@@ -7598,7 +7399,6 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 						/* Also update setting for menu context and TAB-completion */
 						menu_ctx.curr_setting = s_name ? nm_connection_get_setting_by_name (connection, s_name) : NULL;
 						nmc_tab_completion.setting = menu_ctx.curr_setting;
-						g_free (s_name);
 					}
 				}
 
@@ -7640,7 +7440,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 
 			nmc->nowait_flag = FALSE;
 			nmc->should_wait++;
-			nmc->print_output = NMC_PRINT_PRETTY;
+			nmc->nmc_config_mutable.print_output = NMC_PRINT_PRETTY;
 			if (!nmc_activate_connection (nmc, NM_CONNECTION (rem_con), ifname, ap_nsp, ap_nsp, NULL,
 			                              activate_connection_editor_cb, &tmp_err)) {
 				g_print (_("Error: Cannot activate connection: %s.\n"), tmp_err->message);
@@ -7679,7 +7479,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 		case NMC_EDITOR_MAIN_CMD_BACK:
 			/* Go back (up) an the menu */
 			if (menu_ctx.level == 1) {
-				menu_switch_to_level0 (nmc, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
+				menu_switch_to_level0 (nmc->nmc_config.use_colors, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
 				nmc_tab_completion.setting = NULL;  /* for TAB completion */
 			}
 			break;
@@ -7713,24 +7513,25 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 					g_print (_("Error: show-secrets: %s\n"), tmp_err->message);
 					g_clear_error (&tmp_err);
 				} else
-					nmc->editor_show_secrets = bb;
+					nmc->nmc_config_mutable.show_secrets = bb;
 			} else if (cmd_arg_p && matches (cmd_arg_p, "prompt-color")) {
 				GError *tmp_err = NULL;
-				NmcTermColor color;
+				NMMetaTermColor color;
 				color = nmc_term_color_parse_string (cmd_arg_v ? g_strstrip (cmd_arg_v) : " ", &tmp_err);
 				if (tmp_err) {
 					g_print (_("Error: bad color: %s\n"), tmp_err->message);
 					g_clear_error (&tmp_err);
 				} else {
 					nmc->editor_prompt_color = color;
-					g_free (menu_ctx.main_prompt);
-					if (menu_ctx.level == 0)
-						menu_ctx.main_prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
+					nm_clear_g_free (&menu_ctx.main_prompt);
+					if (menu_ctx.level == 0) {
+						menu_ctx.main_prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NM_META_TERM_FORMAT_NORMAL,
 						                                     BASE_PROMPT);
-					else
-						menu_ctx.main_prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
+					} else {
+						menu_ctx.main_prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NM_META_TERM_FORMAT_NORMAL,
 						                                     "nmcli %s> ",
 						                                     nm_setting_get_name (menu_ctx.curr_setting));
+					}
 				}
 			} else if (!cmd_arg_p) {
 				g_print (_("Current nmcli configuration:\n"));
@@ -7740,7 +7541,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 				         "prompt-color: %d\n",
 				         nmc->editor_status_line ? "yes" : "no",
 				         nmc->editor_save_confirmation ? "yes" : "no",
-				         nmc->editor_show_secrets ? "yes" : "no",
+				         nmc->nmc_config.show_secrets ? "yes" : "no",
 				         nmc->editor_prompt_color);
 			} else
 				g_print (_("Invalid configuration option '%s'; allowed [%s]\n"),
@@ -7761,19 +7562,11 @@ editor_menu_main (NmCli *nmc, NMConnection *connection)
 			g_print (_("Unknown command: '%s'\n"), cmd_user);
 			break;
 		}
-
-		g_free (cmd_user);
-		g_free (cmd_arg);
-		g_free (cmd_arg_s);
-		g_free (cmd_arg_p);
-		g_free (cmd_arg_v);
 	}
-	g_free (valid_settings_str);
+
 	g_free (menu_ctx.main_prompt);
 	g_strfreev (menu_ctx.valid_props);
 	g_free (menu_ctx.valid_props_str);
-	if (rem_con)
-		g_object_unref (rem_con);
 	g_weak_ref_clear (&weak);
 
 	/* Save history file */
@@ -7798,12 +7591,11 @@ get_ethernet_device_name (NmCli *nmc)
 }
 
 static void
-editor_init_new_connection (NmCli *nmc, NMConnection *connection)
+editor_init_new_connection (NmCli *nmc, NMConnection *connection, const char *slave_type)
 {
 	NMSetting *setting, *base_setting;
 	NMSettingConnection *s_con;
 	const char *con_type;
-	const char *slave_type = NULL;
 
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
@@ -7813,13 +7605,6 @@ editor_init_new_connection (NmCli *nmc, NMConnection *connection)
 
 	nmc_setting_connection_connect_handlers (s_con, connection);
 
-	if (g_strcmp0 (con_type, "bond-slave") == 0)
-		slave_type = NM_SETTING_BOND_SETTING_NAME;
-	if (g_strcmp0 (con_type, "team-slave") == 0)
-		slave_type = NM_SETTING_TEAM_SETTING_NAME;
-	if (g_strcmp0 (con_type, "bridge-slave") == 0)
-		slave_type = NM_SETTING_BRIDGE_SETTING_NAME;
-
 	if (slave_type) {
 		const char *dev_ifname = get_ethernet_device_name (nmc);
 
@@ -7833,11 +7618,14 @@ editor_init_new_connection (NmCli *nmc, NMConnection *connection)
 		              NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type,
 		              NULL);
 	} else {
+		const NMMetaSettingInfoEditor *setting_info;
+
 		/* Add a "base" setting to the connection by default */
-		base_setting = nmc_setting_new_for_name (con_type);
-		if (!base_setting)
+		setting_info = nm_meta_setting_info_editor_find_by_name (con_type, FALSE);
+		if (!setting_info)
 			return;
-		nmc_setting_custom_init (base_setting);
+		base_setting = nm_meta_setting_info_editor_new_setting (setting_info,
+		                                                        NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
 		nm_connection_add_setting (connection, base_setting);
 
 		set_default_interface_name (nmc, s_con);
@@ -7852,18 +7640,16 @@ editor_init_new_connection (NmCli *nmc, NMConnection *connection)
 		}
 
 
-		/* Always add IPv4 and IPv6 settings for non-slave connections */
-		setting = nm_setting_ip4_config_new ();
-		nmc_setting_custom_init (setting);
+		setting = nm_meta_setting_info_editor_new_setting (&nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_IP4_CONFIG],
+		                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
 		nm_connection_add_setting (connection, setting);
 
-		setting = nm_setting_ip6_config_new ();
-		nmc_setting_custom_init (setting);
+		setting = nm_meta_setting_info_editor_new_setting (&nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_IP6_CONFIG],
+		                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
 		nm_connection_add_setting (connection, setting);
 
-		/* Also Proxy Setting */
-		setting = nm_setting_proxy_new ();
-		nmc_setting_custom_init (setting);
+		setting = nm_meta_setting_info_editor_new_setting (&nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_PROXY],
+		                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
 		nm_connection_add_setting (connection, setting);
 	}
 }
@@ -7895,14 +7681,18 @@ editor_init_existing_connection (NMConnection *connection)
 }
 
 static void
-nmc_complete_connection_type (const char *prefix, const NameItem *types)
+nmc_complete_connection_type (const char *prefix)
 {
-	while (types->name) {
-		if (!*prefix || matches (prefix, types->name))
-			g_print ("%s\n", types->name);
-		if (types->alias && (!*prefix || matches (prefix, types->alias)))
-			g_print ("%s\n", types->alias);
-		types++;
+	guint i;
+
+	for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+		const NMMetaSettingInfoEditor *setting_info = &nm_meta_setting_infos_editor[i];
+
+		if (!*prefix || matches (prefix, setting_info->general->setting_name))
+			g_print ("%s\n", setting_info->general->setting_name);
+		if (   setting_info->alias
+		    && (!*prefix || matches (prefix, setting_info->alias)))
+			g_print ("%s\n", setting_info->alias);
 	}
 }
 
@@ -8016,15 +7806,17 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
 
 		editor_init_existing_connection (connection);
 	} else {
+		const char *slave_type = NULL;
+
 		/* New connection */
 		if (nmc->complete) {
 			if (type && argc == 0)
-				nmc_complete_connection_type (type, nmc_valid_connection_types);
+				nmc_complete_connection_type (type);
 			goto error;
 		}
 
-		connection_type = check_valid_name (type, nmc_valid_connection_types, NULL, &err1);
-		tmp_str = get_valid_options_string (nmc_valid_connection_types, NULL);
+		connection_type = check_valid_name_toplevel (type, &slave_type, &err1);
+		tmp_str = get_valid_options_string_toplevel ();
 
 		while (!connection_type) {
 			if (!type)
@@ -8035,7 +7827,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
 
 			type_ask = nmc_readline (EDITOR_PROMPT_CON_TYPE);
 			type = type_ask = type_ask ? g_strstrip (type_ask) : NULL;
-			connection_type = check_valid_name (type_ask, nmc_valid_connection_types, NULL, &err1);
+			connection_type = check_valid_name_toplevel (type_ask, &slave_type, &err1);
 			g_free (type_ask);
 		}
 		g_free (tmp_str);
@@ -8048,9 +7840,10 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
 		uuid = nm_utils_uuid_generate ();
 		if (con_name)
 			default_name = g_strdup (con_name);
-		else
+		else {
 			default_name = nmc_unique_connection_name (connections,
-			                                           get_name_alias (connection_type, NULL, nmc_valid_connection_types));
+			                                           get_name_alias_toplevel (connection_type, NULL));
+		}
 
 		g_object_set (s_con,
 		              NM_SETTING_CONNECTION_ID, default_name,
@@ -8062,11 +7855,11 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
 		nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 		/* Initialize the new connection so that it is valid from the start */
-		editor_init_new_connection (nmc, connection);
+		editor_init_new_connection (nmc, connection, slave_type);
 	}
 
 	/* nmcli runs the editor */
-	nmc->in_editor = TRUE;
+	nmc->nmc_config_mutable.in_editor = TRUE;
 
 	g_print ("\n");
 	g_print (_("===| nmcli interactive connection editor |==="));
@@ -8083,11 +7876,11 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
 
 	/* Set global variables for use in TAB completion */
 	nmc_tab_completion.nmc = nmc;
-	nmc_tab_completion.con_type = g_strdup (nm_connection_get_connection_type (connection));
+	nmc_tab_completion.con_type = g_strdup (connection_type);
 	nmc_tab_completion.connection = connection;
 
 	/* Run menu loop */
-	editor_menu_main (nmc, connection);
+	editor_menu_main (nmc, connection, connection_type);
 
 	if (connection)
 		g_object_unref (connection);
@@ -8119,7 +7912,7 @@ modify_connection_cb (GObject *connection,
 		g_error_free (error);
 		nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
 	} else {
-		if (nmc->print_output == NMC_PRINT_PRETTY)
+		if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 			g_print (_("Connection '%s' (%s) successfully modified.\n"),
 			         nm_connection_get_id (NM_CONNECTION (connection)),
 			         nm_connection_get_uuid (NM_CONNECTION (connection)));
@@ -8590,26 +8383,8 @@ do_connection_load (NmCli *nmc, int argc, char **argv)
 	return nmc->return_value;
 }
 
-// FIXME: change the text when non-VPN connection types are supported
-#define PROMPT_IMPORT_TYPE PROMPT_VPN_TYPE
 #define PROMPT_IMPORT_FILE N_("File to import: ")
 
-static void
-nmc_complete_vpn_service (const char *prefix)
-{
-	char **services;
-	char **candidate;
-
-	services = nm_vpn_plugin_info_list_get_service_types (NULL, FALSE, TRUE);
-	for (candidate = services; *candidate; candidate++) {
-		if (!*prefix && g_str_has_prefix (*candidate, NM_DBUS_INTERFACE))
-			continue;
-		if (!*prefix || matches (prefix, *candidate))
-			g_print ("%s\n", *candidate);
-	}
-	g_strfreev (services);
-}
-
 static NMCResultCode
 do_connection_import (NmCli *nmc, int argc, char **argv)
 {
@@ -8634,7 +8409,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv)
 		g_assert (!nmc->complete);
 
 		if (nmc->ask) {
-			type_ask = nmc_readline (gettext (PROMPT_IMPORT_TYPE));
+			type_ask = nmc_readline (gettext (NM_META_TEXT_PROMPT_VPN_TYPE));
 			filename_ask = nmc_readline (gettext (PROMPT_IMPORT_FILE));
 			type = type_ask = type_ask ? g_strstrip (type_ask) : NULL;
 			filename = filename_ask = filename_ask ? g_strstrip (filename_ask) : NULL;
@@ -8659,7 +8434,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv)
 			}
 
 			if (argc == 1 && nmc->complete)
-				nmc_complete_vpn_service (*argv);
+				complete_option ((const NMMetaAbstractInfo *) nm_meta_property_info_vpn_service_type, *argv, NULL);
 
 			if (!type)
 				type = *argv;
@@ -8934,8 +8709,8 @@ nmcli_con_tab_completion (const char *text, int start, int end)
 		generator_func = gen_func_connection_names;
 	} else if (g_strcmp0 (rl_prompt, PROMPT_ACTIVE_CONNECTIONS) == 0) {
 		generator_func = gen_func_active_connection_names;
-	} else if (g_strcmp0 (rl_prompt, PROMPT_IMPORT_TYPE) == 0) {
-		generator_func = gen_func_vpn_types;
+	} else if (g_strcmp0 (rl_prompt, NM_META_TEXT_PROMPT_VPN_TYPE) == 0) {
+		return _meta_abstract_complete ((const NMMetaAbstractInfo *) nm_meta_property_info_vpn_service_type, text);
 	} else if (g_strcmp0 (rl_prompt, PROMPT_IMPORT_FILE) == 0) {
 		rl_attempted_completion_over = 0;
 		rl_complete_with_tilde_expansion = 1;
diff --git a/clients/cli/connections.h b/clients/cli/connections.h
index c73178e2..01e78b02 100644
--- a/clients/cli/connections.h
+++ b/clients/cli/connections.h
@@ -33,12 +33,11 @@ nmc_read_connection_properties (NmCli *nmc,
                                 char ***argv,
                                 GError **error);
 
-void nmc_active_connection_state_to_color (NMActiveConnectionState state, NmcTermColor *color);
+void nmc_active_connection_state_to_color (NMActiveConnectionState state, NMMetaTermColor *color);
 
-extern NmcOutputField nmc_fields_con_show[];
-extern NmcOutputField nmc_fields_settings_names[];
-extern NmcOutputField nmc_fields_con_active_details_general[];
-extern NmcOutputField nmc_fields_con_active_details_vpn[];
-extern NmcOutputField nmc_fields_con_active_details_groups[];
+extern const NmcMetaGenericInfo *const nmc_fields_con_show[];
+extern const NmcMetaGenericInfo *const nmc_fields_con_active_details_general[];
+extern const NmcMetaGenericInfo *const nmc_fields_con_active_details_vpn[];
+extern const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[];
 
 #endif /* NMC_CONNECTIONS_H */
diff --git a/clients/cli/devices.c b/clients/cli/devices.c
index f609e1dc..467ce427 100644
--- a/clients/cli/devices.c
+++ b/clients/cli/devices.c
@@ -19,6 +19,8 @@
 
 #include "nm-default.h"
 
+#include "devices.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -26,267 +28,224 @@
 #include <readline/readline.h>
 
 #include "nm-secret-agent-simple.h"
+#include "nm-client-utils.h"
+
 #include "polkit-agent.h"
 #include "utils.h"
 #include "common.h"
-#include "devices.h"
 #include "connections.h"
 
 /* define some prompts */
 #define PROMPT_INTERFACE  _("Interface: ")
 #define PROMPT_INTERFACES _("Interface(s): ")
 
-/* Available fields for 'device status' */
-NmcOutputField nmc_fields_dev_status[] = {
-	{"DEVICE",     N_("DEVICE")},      /* 0 */
-	{"TYPE",       N_("TYPE")},        /* 1 */
-	{"STATE",      N_("STATE")},       /* 2 */
-	{"DBUS-PATH",  N_("DBUS-PATH")},   /* 3 */
-	{"CONNECTION", N_("CONNECTION")},  /* 4 */
-	{"CON-UUID",   N_("CON-UUID")},    /* 5 */
-	{"CON-PATH",   N_("CON-PATH")},    /* 6 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_status[] = {
+	NMC_META_GENERIC ("DEVICE"),       /* 0 */
+	NMC_META_GENERIC ("TYPE"),         /* 1 */
+	NMC_META_GENERIC ("STATE"),        /* 2 */
+	NMC_META_GENERIC ("DBUS-PATH"),    /* 3 */
+	NMC_META_GENERIC ("CONNECTION"),   /* 4 */
+	NMC_META_GENERIC ("CON-UUID"),     /* 5 */
+	NMC_META_GENERIC ("CON-PATH"),     /* 6 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_STATUS_ALL     "DEVICE,TYPE,STATE,DBUS-PATH,CONNECTION,CON-UUID,CON-PATH"
 #define NMC_FIELDS_DEV_STATUS_COMMON  "DEVICE,TYPE,STATE,CONNECTION"
 
 
-/* Available fields for 'device show' - GENERAL part */
-NmcOutputField nmc_fields_dev_show_general[] = {
-	{"NAME",              N_("NAME")},               /* 0 */
-	{"DEVICE",            N_("DEVICE")},             /* 1 */
-	{"TYPE",              N_("TYPE")},               /* 2 */
-	{"NM-TYPE",           N_("NM-TYPE")},            /* 3 */
-	{"VENDOR",            N_("VENDOR")},             /* 4 */
-	{"PRODUCT",           N_("PRODUCT")},            /* 5 */
-	{"DRIVER",            N_("DRIVER")},             /* 6 */
-	{"DRIVER-VERSION",    N_("DRIVER-VERSION")},     /* 7 */
-	{"FIRMWARE-VERSION",  N_("FIRMWARE-VERSION")},   /* 8 */
-	{"HWADDR",            N_("HWADDR")},             /* 9 */
-	{"MTU",               N_("MTU")},                /* 10 */
-	{"STATE",             N_("STATE")},              /* 11 */
-	{"REASON",            N_("REASON")},             /* 12 */
-	{"UDI",               N_("UDI")},                /* 13 */
-	{"IP-IFACE",          N_("IP-IFACE")},           /* 14 */
-	{"IS-SOFTWARE",       N_("IS-SOFTWARE")},        /* 15 */
-	{"NM-MANAGED",        N_("NM-MANAGED")},         /* 16 */
-	{"AUTOCONNECT",       N_("AUTOCONNECT")},        /* 17 */
-	{"FIRMWARE-MISSING",  N_("FIRMWARE-MISSING")},   /* 18 */
-	{"NM-PLUGIN-MISSING", N_("NM-PLUGIN-MISSING")},  /* 19 */
-	{"PHYS-PORT-ID",      N_("PHYS-PORT-ID")},       /* 20 */
-	{"CONNECTION",        N_("CONNECTION")},         /* 21 */
-	{"CON-UUID",          N_("CON-UUID")},           /* 22 */
-	{"CON-PATH",          N_("CON-PATH")},           /* 23 */
-	{"METERED",           N_("METERED")},            /* 24 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_show_general[] = {
+	NMC_META_GENERIC ("NAME"),                /* 0 */
+	NMC_META_GENERIC ("DEVICE"),              /* 1 */
+	NMC_META_GENERIC ("TYPE"),                /* 2 */
+	NMC_META_GENERIC ("NM-TYPE"),             /* 3 */
+	NMC_META_GENERIC ("VENDOR"),              /* 4 */
+	NMC_META_GENERIC ("PRODUCT"),             /* 5 */
+	NMC_META_GENERIC ("DRIVER"),              /* 6 */
+	NMC_META_GENERIC ("DRIVER-VERSION"),      /* 7 */
+	NMC_META_GENERIC ("FIRMWARE-VERSION"),    /* 8 */
+	NMC_META_GENERIC ("HWADDR"),              /* 9 */
+	NMC_META_GENERIC ("MTU"),                 /* 10 */
+	NMC_META_GENERIC ("STATE"),               /* 11 */
+	NMC_META_GENERIC ("REASON"),              /* 12 */
+	NMC_META_GENERIC ("UDI"),                 /* 13 */
+	NMC_META_GENERIC ("IP-IFACE"),            /* 14 */
+	NMC_META_GENERIC ("IS-SOFTWARE"),         /* 15 */
+	NMC_META_GENERIC ("NM-MANAGED"),          /* 16 */
+	NMC_META_GENERIC ("AUTOCONNECT"),         /* 17 */
+	NMC_META_GENERIC ("FIRMWARE-MISSING"),    /* 18 */
+	NMC_META_GENERIC ("NM-PLUGIN-MISSING"),   /* 19 */
+	NMC_META_GENERIC ("PHYS-PORT-ID"),        /* 20 */
+	NMC_META_GENERIC ("CONNECTION"),          /* 21 */
+	NMC_META_GENERIC ("CON-UUID"),            /* 22 */
+	NMC_META_GENERIC ("CON-PATH"),            /* 23 */
+	NMC_META_GENERIC ("METERED"),             /* 24 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_GENERAL_ALL     "NAME,DEVICE,TYPE,NM-TYPE,VENDOR,PRODUCT,DRIVER,DRIVER-VERSION,FIRMWARE-VERSION,HWADDR,MTU,"\
-                                            "STATE,REASON,UDI,IP-IFACE,IS-SOFTWARE,NM-MANAGED,AUTOCONNECT,FIRMWARE-MISSING,NM-PLUGIN-MISSING,"\
-                                            "PHYS-PORT-ID,CONNECTION,CON-UUID,CON-PATH,METERED"
 #define NMC_FIELDS_DEV_SHOW_GENERAL_COMMON  "NAME,DEVICE,TYPE,VENDOR,PRODUCT,DRIVER,HWADDR,STATE"
 
-/* Available fields for 'device show' - CONNECTIONS part */
-NmcOutputField nmc_fields_dev_show_connections[] = {
-	{"NAME",                       N_("NAME")},                        /* 0 */
-	{"AVAILABLE-CONNECTION-PATHS", N_("AVAILABLE-CONNECTION-PATHS")},  /* 1 */
-	{"AVAILABLE-CONNECTIONS",      N_("AVAILABLE-CONNECTIONS")},       /* 2 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_show_connections[] = {
+	NMC_META_GENERIC ("NAME"),                         /* 0 */
+	NMC_META_GENERIC ("AVAILABLE-CONNECTION-PATHS"),   /* 1 */
+	NMC_META_GENERIC ("AVAILABLE-CONNECTIONS"),        /* 2 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_CONNECTIONS_ALL     "NAME,AVAILABLE-CONNECTION-PATHS,AVAILABLE-CONNECTIONS"
 #define NMC_FIELDS_DEV_SHOW_CONNECTIONS_COMMON  "NAME,AVAILABLE-CONNECTION-PATHS,AVAILABLE-CONNECTIONS"
 
-/* Available fields for 'device show' - CAPABILITIES part */
-NmcOutputField nmc_fields_dev_show_cap[] = {
-	{"NAME",            N_("NAME")},            /* 0 */
-	{"CARRIER-DETECT",  N_("CARRIER-DETECT")},  /* 1 */
-	{"SPEED",           N_("SPEED")},           /* 2 */
-	{"IS-SOFTWARE",     N_("IS-SOFTWARE")},     /* 3 */
-	{"SRIOV",           N_("SRIOV")},           /* 4 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_show_cap[] = {
+	NMC_META_GENERIC ("NAME"),             /* 0 */
+	NMC_META_GENERIC ("CARRIER-DETECT"),   /* 1 */
+	NMC_META_GENERIC ("SPEED"),            /* 2 */
+	NMC_META_GENERIC ("IS-SOFTWARE"),      /* 3 */
+	NMC_META_GENERIC ("SRIOV"),            /* 4 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_CAP_ALL     "NAME,CARRIER-DETECT,SPEED,IS-SOFTWARE,SRIOV"
-#define NMC_FIELDS_DEV_SHOW_CAP_COMMON  "NAME,CARRIER-DETECT,SPEED,IS-SOFTWARE,SRIOV"
-
-/* Available fields for 'device show' - wired properties part */
-NmcOutputField nmc_fields_dev_show_wired_prop[] = {
-	{"NAME",             N_("NAME")},              /* 0 */
-	{"CARRIER",          N_("CARRIER")},           /* 1 */
-	{"S390-SUBCHANNELS", N_("S390-SUBCHANNELS")},  /* 2 */
-	{NULL, NULL}
+#define NMC_FIELDS_DEV_SHOW_CAP_COMMON  "NAME,CARRIER-DETECT,SPEED,IS-SOFTWARE"
+
+const NmcMetaGenericInfo *const nmc_fields_dev_show_wired_prop[] = {
+	NMC_META_GENERIC ("NAME"),               /* 0 */
+	NMC_META_GENERIC ("CARRIER"),            /* 1 */
+	NMC_META_GENERIC ("S390-SUBCHANNELS"),   /* 2 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_WIRED_PROP_ALL     "NAME,CARRIER,S390-SUBCHANNELS"
 #define NMC_FIELDS_DEV_SHOW_WIRED_PROP_COMMON  "NAME,CARRIER,S390-SUBCHANNELS"
 
-/* Available fields for 'device show' - wireless properties part */
-NmcOutputField nmc_fields_dev_show_wifi_prop[] = {
-	{"NAME",       N_("NAME")},   /* 0 */
-	{"WEP",        N_("WEP")},    /* 1 */
-	{"WPA",        N_("WPA")},    /* 2 */
-	{"WPA2",       N_("WPA2")},   /* 3 */
-	{"TKIP",       N_("TKIP")},   /* 4 */
-	{"CCMP",       N_("CCMP")},   /* 5 */
-	{"AP",         N_("AP")},     /* 6 */
-	{"ADHOC",      N_("ADHOC")},  /* 7 */
-	{"2GHZ",       N_("2GHZ")},   /* 8 */
-	{"5GHZ",       N_("5GHZ")},   /* 9 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_show_wifi_prop[] = {
+	NMC_META_GENERIC ("NAME"),    /* 0 */
+	NMC_META_GENERIC ("WEP"),     /* 1 */
+	NMC_META_GENERIC ("WPA"),     /* 2 */
+	NMC_META_GENERIC ("WPA2"),    /* 3 */
+	NMC_META_GENERIC ("TKIP"),    /* 4 */
+	NMC_META_GENERIC ("CCMP"),    /* 5 */
+	NMC_META_GENERIC ("AP"),      /* 6 */
+	NMC_META_GENERIC ("ADHOC"),   /* 7 */
+	NMC_META_GENERIC ("2GHZ"),    /* 8 */
+	NMC_META_GENERIC ("5GHZ"),    /* 9 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_WIFI_PROP_ALL     "NAME,WEP,WPA,WPA2,TKIP,CCMP,AP,ADHOC,2GHZ,5GHZ"
 #define NMC_FIELDS_DEV_SHOW_WIFI_PROP_COMMON  "NAME,WEP,WPA,WPA2,TKIP,CCMP,AP,ADHOC"
 
-/* Available fields for 'device show' - wimax properties part */
-NmcOutputField nmc_fields_dev_show_wimax_prop[] = {
-	{"NAME",       N_("NAME")},      /* 0 */
-	{"CTR-FREQ",   N_("CTR-FREQ")},  /* 1 */
-	{"RSSI",       N_("RSSI")},      /* 2 */
-	{"CINR",       N_("CINR")},      /* 3 */
-	{"TX-POW",     N_("TX-POW")},    /* 4 */
-	{"BSID",       N_("BSID")},      /* 5 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_show_wimax_prop[] = {
+	NMC_META_GENERIC ("NAME"),       /* 0 */
+	NMC_META_GENERIC ("CTR-FREQ"),   /* 1 */
+	NMC_META_GENERIC ("RSSI"),       /* 2 */
+	NMC_META_GENERIC ("CINR"),       /* 3 */
+	NMC_META_GENERIC ("TX-POW"),     /* 4 */
+	NMC_META_GENERIC ("BSID"),       /* 5 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_WIMAX_PROP_ALL     "NAME,CTR-FREQ,RSSI,CINR,TX-POW,BSID"
 #define NMC_FIELDS_DEV_SHOW_WIMAX_PROP_COMMON  "NAME,CTR-FREQ,RSSI,CINR,TX-POW,BSID"
 
-/* Available fields for 'device wifi list' */
-NmcOutputField nmc_fields_dev_wifi_list[] = {
-	{"NAME",       N_("NAME")},       /* 0 */
-	{"SSID",       N_("SSID")},       /* 1 */
-	{"SSID-HEX",   N_("SSID-HEX")},   /* 2 */
-	{"BSSID",      N_("BSSID")},      /* 3 */
-	{"MODE",       N_("MODE")},       /* 4 */
-	{"CHAN",       N_("CHAN")},       /* 5 */
-	{"FREQ",       N_("FREQ")},       /* 6 */
-	{"RATE",       N_("RATE")},       /* 7 */
-	{"SIGNAL",     N_("SIGNAL")},     /* 8 */
-	{"BARS",       N_("BARS")},       /* 9 */
-	{"SECURITY",   N_("SECURITY")},   /* 10 */
-	{"WPA-FLAGS",  N_("WPA-FLAGS")},  /* 11 */
-	{"RSN-FLAGS",  N_("RSN-FLAGS")},  /* 12 */
-	{"DEVICE",     N_("DEVICE")},     /* 13 */
-	{"ACTIVE",     N_("ACTIVE")},     /* 14 */
-	{"IN-USE",     N_("*")},          /* 15 */
-	{"DBUS-PATH",  N_("DBUS-PATH")},  /* 16 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_wifi_list[] = {
+	NMC_META_GENERIC ("NAME"),        /* 0 */
+	NMC_META_GENERIC ("SSID"),        /* 1 */
+	NMC_META_GENERIC ("SSID-HEX"),    /* 2 */
+	NMC_META_GENERIC ("BSSID"),       /* 3 */
+	NMC_META_GENERIC ("MODE"),        /* 4 */
+	NMC_META_GENERIC ("CHAN"),        /* 5 */
+	NMC_META_GENERIC ("FREQ"),        /* 6 */
+	NMC_META_GENERIC ("RATE"),        /* 7 */
+	NMC_META_GENERIC ("SIGNAL"),      /* 8 */
+	NMC_META_GENERIC ("BARS"),        /* 9 */
+	NMC_META_GENERIC ("SECURITY"),    /* 10 */
+	NMC_META_GENERIC ("WPA-FLAGS"),   /* 11 */
+	NMC_META_GENERIC ("RSN-FLAGS"),   /* 12 */
+	NMC_META_GENERIC ("DEVICE"),      /* 13 */
+	NMC_META_GENERIC ("ACTIVE"),      /* 14 */
+	NMC_META_GENERIC ("IN-USE"),      /* 15 */
+	NMC_META_GENERIC ("DBUS-PATH"),   /* 16 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_WIFI_LIST_ALL           "SSID,SSID-HEX,BSSID,MODE,CHAN,FREQ,RATE,SIGNAL,BARS,SECURITY,"\
-                                               "WPA-FLAGS,RSN-FLAGS,DEVICE,ACTIVE,IN-USE,DBUS-PATH"
 #define NMC_FIELDS_DEV_WIFI_LIST_COMMON        "IN-USE,SSID,MODE,CHAN,RATE,SIGNAL,BARS,SECURITY"
 #define NMC_FIELDS_DEV_WIFI_LIST_FOR_DEV_LIST  "NAME,"NMC_FIELDS_DEV_WIFI_LIST_COMMON
 
-/* Available fields for 'device wimax list' */
-NmcOutputField nmc_fields_dev_wimax_list[] = {
-	{"NAME",       N_("NAME")},       /* 0 */
-	{"NSP",        N_("NSP")},        /* 1 */
-	{"SIGNAL",     N_("SIGNAL")},     /* 2 */
-	{"TYPE",       N_("TYPE")},       /* 3 */
-	{"DEVICE",     N_("DEVICE")},     /* 4 */
-	{"ACTIVE",     N_("ACTIVE")},     /* 5 */
-	{"DBUS-PATH",  N_("DBUS-PATH")},  /* 6 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_wimax_list[] = {
+	NMC_META_GENERIC ("NAME"),        /* 0 */
+	NMC_META_GENERIC ("NSP"),         /* 1 */
+	NMC_META_GENERIC ("SIGNAL"),      /* 2 */
+	NMC_META_GENERIC ("TYPE"),        /* 3 */
+	NMC_META_GENERIC ("DEVICE"),      /* 4 */
+	NMC_META_GENERIC ("ACTIVE"),      /* 5 */
+	NMC_META_GENERIC ("DBUS-PATH"),   /* 6 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_WIMAX_LIST_ALL           "NSP,SIGNAL,TYPE,DEVICE,ACTIVE,DBUS-PATH"
 #define NMC_FIELDS_DEV_WIMAX_LIST_COMMON        "NSP,SIGNAL,TYPE,DEVICE,ACTIVE"
 #define NMC_FIELDS_DEV_WIMAX_LIST_FOR_DEV_LIST  "NAME,"NMC_FIELDS_DEV_WIMAX_LIST_COMMON
 
-/* Available fields for 'device show' - BOND, BRIDGE part */
-NmcOutputField nmc_fields_dev_show_master_prop[] = {
-	{"NAME",       N_("NAME")},    /* 0 */
-	{"SLAVES",     N_("SLAVES")},  /* 1 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_show_master_prop[] = {
+	NMC_META_GENERIC ("NAME"),     /* 0 */
+	NMC_META_GENERIC ("SLAVES"),   /* 1 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_MASTER_PROP_ALL     "NAME,SLAVES"
 #define NMC_FIELDS_DEV_SHOW_MASTER_PROP_COMMON  "NAME,SLAVES"
 
-/* Available fields for 'device show' - TEAM part */
-NmcOutputField nmc_fields_dev_show_team_prop[] = {
-	{"NAME",       N_("NAME")},    /* 0 */
-	{"SLAVES",     N_("SLAVES")},  /* 1 */
-	{"CONFIG",     N_("CONFIG")},  /* 2 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_show_team_prop[] = {
+	NMC_META_GENERIC ("NAME"),     /* 0 */
+	NMC_META_GENERIC ("SLAVES"),   /* 1 */
+	NMC_META_GENERIC ("CONFIG"),   /* 2 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_TEAM_PROP_ALL     "NAME,SLAVES,CONFIG"
 #define NMC_FIELDS_DEV_SHOW_TEAM_PROP_COMMON  "NAME,SLAVES,CONFIG"
 
-/* Available fields for 'device show' - VLAN part */
-NmcOutputField nmc_fields_dev_show_vlan_prop[] = {
-	{"NAME",           N_("NAME")},    /* 0 */
-	{"PARENT",         N_("PARENT")},  /* 1 */
-	{"ID",             N_("ID")},      /* 2 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_show_vlan_prop[] = {
+	NMC_META_GENERIC ("NAME"),     /* 0 */
+	NMC_META_GENERIC ("PARENT"),   /* 1 */
+	NMC_META_GENERIC ("ID"),       /* 2 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_VLAN_PROP_ALL     "NAME,PARENT,ID"
 #define NMC_FIELDS_DEV_SHOW_VLAN_PROP_COMMON  "NAME,PARENT,ID"
 
-/* Available fields for 'device show' - BLUETOOTH part */
-NmcOutputField nmc_fields_dev_show_bluetooth[] = {
-	{"NAME",           N_("NAME")},          /* 0 */
-	{"CAPABILITIES",   N_("CAPABILITIES")},  /* 1 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_show_bluetooth[] = {
+	NMC_META_GENERIC ("NAME"),           /* 0 */
+	NMC_META_GENERIC ("CAPABILITIES"),   /* 1 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_BLUETOOTH_ALL     "NAME,CAPABILITIES"
 #define NMC_FIELDS_DEV_SHOW_BLUETOOTH_COMMON  "NAME,CAPABILITIES"
 
-/* defined in common.c */
-extern NmcOutputField nmc_fields_ip4_config[];
-extern NmcOutputField nmc_fields_ip6_config[];
-extern NmcOutputField nmc_fields_dhcp4_config[];
-extern NmcOutputField nmc_fields_dhcp6_config[];
-
 /* Available sections for 'device show' */
-NmcOutputField nmc_fields_dev_show_sections[] = {
-	{"GENERAL",           N_("GENERAL"),           0, nmc_fields_dev_show_general + 1     },  /* 0 */
-	{"CAPABILITIES",      N_("CAPABILITIES"),      0, nmc_fields_dev_show_cap + 1         },  /* 1 */
-	{"WIFI-PROPERTIES",   N_("WIFI-PROPERTIES"),   0, nmc_fields_dev_show_wifi_prop + 1   },  /* 2 */
-	{"AP",                N_("AP"),                0, nmc_fields_dev_wifi_list + 1        },  /* 3 */
-	{"WIRED-PROPERTIES",  N_("WIRED-PROPERTIES"),  0, nmc_fields_dev_show_wired_prop + 1  },  /* 4 */
-	{"WIMAX-PROPERTIES",  N_("WIMAX-PROPERTIES"),  0, nmc_fields_dev_show_wimax_prop + 1  },  /* 5 */
-	{"NSP",               N_("NSP"),               0, nmc_fields_dev_wimax_list + 1       },  /* 6 */
-	{"IP4",               N_("IP4"),               0, nmc_fields_ip4_config + 1           },  /* 7 */
-	{"DHCP4",             N_("DHCP4"),             0, nmc_fields_dhcp4_config + 1         },  /* 8 */
-	{"IP6",               N_("IP6"),               0, nmc_fields_ip6_config + 1           },  /* 9 */
-	{"DHCP6",             N_("DHCP6"),             0, nmc_fields_dhcp6_config + 1         },  /* 10 */
-	{"BOND",              N_("BOND"),              0, nmc_fields_dev_show_master_prop + 1 },  /* 11 */
-	{"TEAM",              N_("TEAM"),              0, nmc_fields_dev_show_team_prop + 1   },  /* 12 */
-	{"BRIDGE",            N_("BRIDGE"),            0, nmc_fields_dev_show_master_prop + 1 },  /* 13 */
-	{"VLAN",              N_("VLAN"),              0, nmc_fields_dev_show_vlan_prop  + 1  },  /* 14 */
-	{"BLUETOOTH",         N_("BLUETOOTH"),         0, nmc_fields_dev_show_bluetooth + 1   },  /* 15 */
-	{"CONNECTIONS",       N_("CONNECTIONS"),       0, nmc_fields_dev_show_connections + 1 },  /* 16 */
-	{NULL,                NULL,                    0, NULL                                }
+const NmcMetaGenericInfo *const nmc_fields_dev_show_sections[] = {
+	NMC_META_GENERIC_WITH_NESTED ("GENERAL",           nmc_fields_dev_show_general + 1),      /* 0 */
+	NMC_META_GENERIC_WITH_NESTED ("CAPABILITIES",      nmc_fields_dev_show_cap + 1),          /* 1 */
+	NMC_META_GENERIC_WITH_NESTED ("WIFI-PROPERTIES",   nmc_fields_dev_show_wifi_prop + 1),    /* 2 */
+	NMC_META_GENERIC_WITH_NESTED ("AP",                nmc_fields_dev_wifi_list + 1),         /* 3 */
+	NMC_META_GENERIC_WITH_NESTED ("WIRED-PROPERTIES",  nmc_fields_dev_show_wired_prop + 1),   /* 4 */
+	NMC_META_GENERIC_WITH_NESTED ("WIMAX-PROPERTIES",  nmc_fields_dev_show_wimax_prop + 1),   /* 5 */
+	NMC_META_GENERIC_WITH_NESTED ("NSP",               nmc_fields_dev_wimax_list + 1),        /* 6 */
+	NMC_META_GENERIC_WITH_NESTED ("IP4",               metagen_ip4_config),                   /* 7 */
+	NMC_META_GENERIC_WITH_NESTED ("DHCP4",             nmc_fields_dhcp4_config + 1),          /* 8 */
+	NMC_META_GENERIC_WITH_NESTED ("IP6",               nmc_fields_ip6_config + 1),            /* 9 */
+	NMC_META_GENERIC_WITH_NESTED ("DHCP6",             nmc_fields_dhcp6_config + 1),          /* 10 */
+	NMC_META_GENERIC_WITH_NESTED ("BOND",              nmc_fields_dev_show_master_prop + 1),  /* 11 */
+	NMC_META_GENERIC_WITH_NESTED ("TEAM",              nmc_fields_dev_show_team_prop + 1),    /* 12 */
+	NMC_META_GENERIC_WITH_NESTED ("BRIDGE",            nmc_fields_dev_show_master_prop + 1),  /* 13 */
+	NMC_META_GENERIC_WITH_NESTED ("VLAN",              nmc_fields_dev_show_vlan_prop + 1),    /* 14 */
+	NMC_META_GENERIC_WITH_NESTED ("BLUETOOTH",         nmc_fields_dev_show_bluetooth + 1),    /* 15 */
+	NMC_META_GENERIC_WITH_NESTED ("CONNECTIONS",       nmc_fields_dev_show_connections + 1),  /* 16 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_SHOW_SECTIONS_ALL     "GENERAL,CAPABILITIES,BOND,TEAM,BRIDGE,VLAN,WIFI-PROPERTIES,AP,WIRED-PROPERTIES,"\
-                                             "BLUETOOTH,CONNECTIONS,IP4,DHCP4,IP6,DHCP6"
 #define NMC_FIELDS_DEV_SHOW_SECTIONS_COMMON  "GENERAL.DEVICE,GENERAL.TYPE,GENERAL.HWADDR,GENERAL.MTU,GENERAL.STATE,"\
                                              "GENERAL.CONNECTION,GENERAL.CON-PATH,WIRED-PROPERTIES,IP4,IP6"
 
-/* Available fields for 'device lldp' */
-NmcOutputField nmc_fields_dev_lldp_list[] = {
-	{"NAME",                    N_("NAME")},                     /* 0 */
-	{"DEVICE",                  N_("DEVICE")},                   /* 1 */
-	{"CHASSIS-ID",              N_("CHASSIS-ID")},               /* 2 */
-	{"PORT-ID",                 N_("PORT-ID")},                  /* 3 */
-	{"PORT-DESCRIPTION",        N_("PORT-DESCRIPTION")},         /* 4 */
-	{"SYSTEM-NAME",             N_("SYSTEM-NAME")},              /* 5 */
-	{"SYSTEM-DESCRIPTION",      N_("SYSTEM-DESCRIPTION")},       /* 6 */
-	{"SYSTEM-CAPABILITIES",     N_("SYSTEM-CAPABILITIES")},      /* 7 */
-	{"IEEE-802-1-PVID",         N_("IEEE-802-1-PVID")},          /* 8 */
-	{"IEEE-802-1-PPVID",        N_("IEEE-802-1-PPVID")},         /* 9 */
-	{"IEEE-802-1-PPVID-FLAGS",  N_("IEEE-802-1-PPVID-FLAGS")},   /* 10 */
-	{"IEEE-802-1-VID",          N_("IEEE-802-1-VID")},           /* 11 */
-	{"IEEE-802-1-VLAN-NAME",    N_("IEEE-802-1-VLAN-NAME")},     /* 12 */
-	{"DESTINATION",             N_("DESTINATION")},              /* 13 */
-	{"CHASSIS-ID-TYPE",         N_("CHASSIS-ID-TYPE")},          /* 14 */
-	{"PORT-ID-TYPE",            N_("PORT-ID-TYPE")},             /* 15 */
-	{NULL, NULL}
+const NmcMetaGenericInfo *const nmc_fields_dev_lldp_list[] = {
+	NMC_META_GENERIC ("NAME"),                      /* 0 */
+	NMC_META_GENERIC ("DEVICE"),                    /* 1 */
+	NMC_META_GENERIC ("CHASSIS-ID"),                /* 2 */
+	NMC_META_GENERIC ("PORT-ID"),                   /* 3 */
+	NMC_META_GENERIC ("PORT-DESCRIPTION"),          /* 4 */
+	NMC_META_GENERIC ("SYSTEM-NAME"),               /* 5 */
+	NMC_META_GENERIC ("SYSTEM-DESCRIPTION"),        /* 6 */
+	NMC_META_GENERIC ("SYSTEM-CAPABILITIES"),       /* 7 */
+	NMC_META_GENERIC ("IEEE-802-1-PVID"),           /* 8 */
+	NMC_META_GENERIC ("IEEE-802-1-PPVID"),          /* 9 */
+	NMC_META_GENERIC ("IEEE-802-1-PPVID-FLAGS"),    /* 10 */
+	NMC_META_GENERIC ("IEEE-802-1-VID"),            /* 11 */
+	NMC_META_GENERIC ("IEEE-802-1-VLAN-NAME"),      /* 12 */
+	NMC_META_GENERIC ("DESTINATION"),               /* 13 */
+	NMC_META_GENERIC ("CHASSIS-ID-TYPE"),           /* 14 */
+	NMC_META_GENERIC ("PORT-ID-TYPE"),              /* 15 */
+	NULL,
 };
-#define NMC_FIELDS_DEV_LLDP_LIST_ALL     "DEVICE,CHASSIS-ID,PORT-ID,PORT-DESCRIPTION,SYSTEM-NAME,SYSTEM-DESCRIPTION," \
-                                         "SYSTEM-CAPABILITIES,IEEE-802-1-PVID,IEEE-802-1-PPVID,IEEE-802-1-PPVID-FLAGS," \
-                                         "IEEE-802-1-VID,IEEE-802-1-VLAN-NAME,DESTINATION,CHASSIS-ID-TYPE,PORT-ID-TYPE"
 #define NMC_FIELDS_DEV_LLDP_LIST_COMMON  "DEVICE,CHASSIS-ID,PORT-ID,PORT-DESCRIPTION,SYSTEM-NAME,SYSTEM-DESCRIPTION," \
                                          "SYSTEM-CAPABILITIES"
 
-/* glib main loop variable - defined in nmcli.c */
-extern GMainLoop *loop;
-
 static guint progress_id = 0;  /* ID of event source for displaying progress */
 
 static void
@@ -489,7 +448,6 @@ usage_device_lldp (void)
 	              "used to list neighbors for a particular interface.\n\n"));
 }
 
-/* quit main loop */
 static void
 quit (void)
 {
@@ -498,7 +456,7 @@ quit (void)
 		nmc_terminal_erase_line ();
 	}
 
-	g_main_loop_quit (loop);  /* quit main loop */
+	g_main_loop_quit (loop);
 }
 
 static int
@@ -506,6 +464,12 @@ compare_devices (const void *a, const void *b)
 {
 	NMDevice *da = *(NMDevice **)a;
 	NMDevice *db = *(NMDevice **)b;
+	NMActiveConnection *da_ac;
+	NMActiveConnection *db_ac;
+	NMIPConfig *da_ip;
+	NMIPConfig *db_ip;
+	int da_num_addrs;
+	int db_num_addrs;
 	int cmp;
 
 	/* Sort by later device states first */
@@ -513,6 +477,57 @@ compare_devices (const void *a, const void *b)
 	if (cmp != 0)
 		return cmp;
 
+	da_ac = nm_device_get_active_connection (da);
+	db_ac = nm_device_get_active_connection (db);
+
+	/* Prioritize devices with active connections */
+	if (da_ac)
+		cmp++;
+	if (db_ac)
+		cmp--;
+	if (cmp != 0)
+		return cmp;
+
+	/* VPNs go on the top if possible */
+	if (da_ac && !nm_active_connection_get_vpn (da_ac))
+		cmp++;
+	if (db_ac && !nm_active_connection_get_vpn (db_ac))
+		cmp--;
+	if (cmp != 0)
+		return cmp;
+
+	/* Default devices are prioritized */
+	if (da_ac && !nm_active_connection_get_default (da_ac))
+		cmp++;
+	if (db_ac && !nm_active_connection_get_default (db_ac))
+		cmp--;
+	if (cmp != 0)
+		return cmp;
+
+	/* Default IPv6 devices are prioritized */
+	if (da_ac && !nm_active_connection_get_default6 (da_ac))
+		cmp++;
+	if (db_ac && !nm_active_connection_get_default6 (db_ac))
+		cmp--;
+	if (cmp != 0)
+		return cmp;
+
+	/* Sort by number of addresses. */
+	da_ip = da_ac ? nm_active_connection_get_ip4_config (da_ac) : NULL;
+	da_num_addrs = da_ip ? nm_ip_config_get_addresses (da_ip)->len : 0;
+	db_ip = db_ac ? nm_active_connection_get_ip4_config (db_ac) : NULL;
+	db_num_addrs = db_ip ? nm_ip_config_get_addresses (db_ip)->len : 0;
+
+	da_ip = da_ac ? nm_active_connection_get_ip6_config (da_ac) : NULL;
+	da_num_addrs += da_ip ? nm_ip_config_get_addresses (da_ip)->len : 0;
+	db_ip = db_ac ? nm_active_connection_get_ip6_config (db_ac) : NULL;
+	db_num_addrs += db_ip ? nm_ip_config_get_addresses (db_ip)->len : 0;
+
+	cmp = db_num_addrs - da_num_addrs;
+	if (cmp != 0)
+		return cmp;
+
+	/* Fall back to alphanumeric sort by description and interface. */
 	cmp = g_strcmp0 (nm_device_get_type_description (da),
 	                 nm_device_get_type_description (db));
 	if (cmp != 0)
@@ -697,21 +712,21 @@ sort_access_points (const GPtrArray *aps)
 }
 
 static void
-wifi_signal_to_color (guint8 strength, NmcTermColor *color, NmcTermFormat *color_fmt)
+wifi_signal_to_color (guint8 strength, NMMetaTermColor *color, NMMetaTermFormat *color_fmt)
 {
-	*color = NMC_TERM_COLOR_NORMAL;
-	*color_fmt = NMC_TERM_FORMAT_NORMAL;
+	*color = NM_META_TERM_COLOR_NORMAL;
+	*color_fmt = NM_META_TERM_FORMAT_NORMAL;
 
 	if (strength > 80)
-		*color = NMC_TERM_COLOR_GREEN;
+		*color = NM_META_TERM_COLOR_GREEN;
 	else if (strength > 55)
-		*color = NMC_TERM_COLOR_YELLOW;
+		*color = NM_META_TERM_COLOR_YELLOW;
 	else if (strength > 30)
-		*color = NMC_TERM_COLOR_MAGENTA;
+		*color = NM_META_TERM_COLOR_MAGENTA;
 	else if (strength > 5)
-		*color = NMC_TERM_COLOR_CYAN;
+		*color = NM_META_TERM_COLOR_CYAN;
 	else
-		*color_fmt = NMC_TERM_FORMAT_DIM;
+		*color_fmt = NM_META_TERM_FORMAT_DIM;
 }
 
 static char *
@@ -762,6 +777,7 @@ typedef struct {
 	guint32 output_flags;
 	const char* active_bssid;
 	const char* device;
+	GPtrArray *output_data;
 } APInfo;
 
 static void
@@ -783,8 +799,8 @@ fill_output_access_point (gpointer data, gpointer user_data)
 	GString *security_str;
 	char *ap_name;
 	const char *sig_bars;
-	NmcTermColor color;
-	NmcTermFormat color_fmt;
+	NMMetaTermColor color;
+	NMMetaTermFormat color_fmt;
 
 	if (info->active_bssid) {
 		const char *current_bssid = nm_access_point_get_bssid (ap);
@@ -845,8 +861,7 @@ fill_output_access_point (gpointer data, gpointer user_data)
 	if (security_str->len > 0)
 		g_string_truncate (security_str, security_str->len-1);  /* Chop off last space */
 
-	arr = nmc_dup_fields_array (nmc_fields_dev_wifi_list,
-	                            sizeof (nmc_fields_dev_wifi_list),
+	arr = nmc_dup_fields_array ((const NMMetaAbstractInfo *const*) nmc_fields_dev_wifi_list,
 	                            info->output_flags);
 
 	ap_name = g_strdup_printf ("AP[%d]", info->index++); /* AP */
@@ -875,9 +890,9 @@ fill_output_access_point (gpointer data, gpointer user_data)
 	set_val_color_all (arr, color);
 	set_val_color_fmt_all (arr, color_fmt);
 	if (active)
-		arr[15].color = NMC_TERM_COLOR_GREEN;
+		arr[15].color = NM_META_TERM_COLOR_GREEN;
 
-	g_ptr_array_add (info->nmc->output_data, arr);
+	g_ptr_array_add (info->output_data, arr);
 
 	g_string_free (security_str, FALSE);
 }
@@ -908,20 +923,13 @@ bluetooth_caps_to_string (NMBluetoothCapabilities caps)
 	return ret_str;
 }
 
-static const char *
+static char *
 construct_header_name (const char *base, const char *spec)
 {
-	static char header_name[128];
-
 	if (spec == NULL)
-		return base;
-
-	g_strlcpy (header_name, base, sizeof (header_name));
-	g_strlcat (header_name, " (", sizeof (header_name));
-	g_strlcat (header_name, spec, sizeof (header_name));
-	g_strlcat (header_name, ")", sizeof (header_name));
+		return g_strdup (base);
 
-	return header_name;
+	return g_strdup_printf ("%s (%s)", base, spec);
 }
 
 static const char *
@@ -945,8 +953,9 @@ print_bond_bridge_info (NMDevice *device,
 	const GPtrArray *slaves = NULL;
 	GString *slaves_str;
 	int idx;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	const NMMetaAbstractInfo *const*tmpl;
+	NmcOutputField *arr;
+	NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
 	if (NM_IS_DEVICE_BOND (device))
 		slaves = nm_device_bond_get_slaves (NM_DEVICE_BOND (device));
@@ -968,22 +977,21 @@ print_bond_bridge_info (NMDevice *device,
 	if (slaves_str->len > 0)
 		g_string_truncate (slaves_str, slaves_str->len-1);  /* Chop off last space */
 
-	tmpl = nmc_fields_dev_show_master_prop;
-	tmpl_len = sizeof (nmc_fields_dev_show_master_prop);
-	nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DEV_SHOW_MASTER_PROP_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
+	tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_master_prop;
+	out_indices = parse_output_fields (one_field,
+	                                   tmpl, FALSE, NULL, NULL);
+	arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+	g_ptr_array_add (out.output_data, arr);
 
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
+	arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
 	set_val_strc (arr, 0, group_prefix);     /* i.e. BOND, TEAM, BRIDGE */
 	set_val_str  (arr, 1, slaves_str->str);
-	g_ptr_array_add (nmc->output_data, arr);
+	g_ptr_array_add (out.output_data, arr);
 
-	print_data (nmc);  /* Print all data */
+	print_data_prepare_width (out.output_data);
+	print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 
 	g_string_free (slaves_str, FALSE);
-	nmc_empty_output_fields (nmc);
 
 	return TRUE;
 }
@@ -1016,8 +1024,9 @@ print_team_info (NMDevice *device,
 	const GPtrArray *slaves = NULL;
 	GString *slaves_str;
 	int idx;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	const NMMetaAbstractInfo *const* tmpl;
+	NmcOutputField *arr;
+	NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
 	if (NM_IS_DEVICE_TEAM (device))
 		slaves = nm_device_team_get_slaves (NM_DEVICE_TEAM (device));
@@ -1037,23 +1046,22 @@ print_team_info (NMDevice *device,
 	if (slaves_str->len > 0)
 		g_string_truncate (slaves_str, slaves_str->len-1);  /* Chop off last space */
 
-	tmpl = nmc_fields_dev_show_team_prop;
-	tmpl_len = sizeof (nmc_fields_dev_show_team_prop);
-	nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DEV_SHOW_TEAM_PROP_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
+	tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_team_prop;
+	out_indices = parse_output_fields (one_field,
+	                                   tmpl, FALSE, NULL, NULL);
+	arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+	g_ptr_array_add (out.output_data, arr);
 
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
+	arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
 	set_val_strc (arr, 0, group_prefix);     /* TEAM */
 	set_val_str  (arr, 1, slaves_str->str);
 	set_val_str (arr, 2, sanitize_team_config (nm_device_team_get_config (NM_DEVICE_TEAM (device))));
-	g_ptr_array_add (nmc->output_data, arr);
+	g_ptr_array_add (out.output_data, arr);
 
-	print_data (nmc);  /* Print all data */
+	print_data_prepare_width (out.output_data);
+	print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 
 	g_string_free (slaves_str, FALSE);
-	nmc_empty_output_fields (nmc);
 
 	return TRUE;
 }
@@ -1062,7 +1070,6 @@ static gboolean
 show_device_info (NMDevice *device, NmCli *nmc)
 {
 	GError *error = NULL;
-	APInfo *info;
 	const char *hwaddr = NULL;
 	NMDeviceState state = NM_DEVICE_STATE_UNKNOWN;
 	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
@@ -1072,11 +1079,9 @@ show_device_info (NMDevice *device, NmCli *nmc)
 	char *speed_str, *state_str, *reason_str, *mtu_str;
 	GArray *sections_array;
 	int k;
-	char *fields_str;
-	char *fields_all =    NMC_FIELDS_DEV_SHOW_SECTIONS_ALL;
-	char *fields_common = NMC_FIELDS_DEV_SHOW_SECTIONS_COMMON;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	const char *fields_str = NULL;
+	const NMMetaAbstractInfo *const*tmpl;
+	NmcOutputField *arr;
 	gboolean was_output = FALSE;
 	NMIPConfig *cfg4, *cfg6;
 	NMDhcpConfig *dhcp4, *dhcp6;
@@ -1084,13 +1089,12 @@ show_device_info (NMDevice *device, NmCli *nmc)
 	GPtrArray *fields_in_section = NULL;
 
 	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
-		fields_str = fields_common;
-	else if (strcasecmp (nmc->required_fields, "all") == 0)
-		fields_str = fields_all;
-	else
+		fields_str = NMC_FIELDS_DEV_SHOW_SECTIONS_COMMON;
+	else if (strcasecmp (nmc->required_fields, "all") == 0) {
+	} else
 		fields_str = nmc->required_fields;
 
-	sections_array = parse_output_fields (fields_str, nmc_fields_dev_show_sections, TRUE, &fields_in_section, &error);
+	sections_array = parse_output_fields (fields_str, (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_sections, TRUE, &fields_in_section, &error);
 	if (error) {
 		g_string_printf (nmc->return_text, _("Error: 'device show': %s"), error->message);
 		g_error_free (error);
@@ -1098,40 +1102,51 @@ show_device_info (NMDevice *device, NmCli *nmc)
 		return FALSE;
 	}
 
-	/* Main header (pretty only) */
-	nmc->print_fields.header_name = (char *) construct_header_name (base_hdr, nm_device_get_iface (device));
+	{
+		gs_unref_array GArray *out_indices = NULL;
+		gs_free char *header_name = NULL;
+		gs_free NmcOutputField *row = NULL;
+		int i;
+
+		/* Main header (pretty only) */
+		header_name = construct_header_name (base_hdr, nm_device_get_iface (device));
+
+		/* Lazy way to retrieve sorted array from 0 to the number of dev fields */
+		out_indices = parse_output_fields (NULL,
+		                                   (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_general,
+		                                   FALSE, NULL, NULL);
 
-	/* Lazy way to retrieve sorted array from 0 to the number of dev fields */
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_DEV_SHOW_GENERAL_ALL,
-	                                                 nmc_fields_dev_show_general, FALSE, NULL, NULL);
+		row = g_new0 (NmcOutputField, _NM_META_SETTING_TYPE_NUM + 1);
+		for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++)
+			row[i].info = (const NMMetaAbstractInfo *) &nmc_fields_dev_show_general[i];
 
-	nmc_fields_dev_show_general[0].flags = NMC_OF_FLAG_MAIN_HEADER_ONLY;
-	print_required_fields (nmc, nmc_fields_dev_show_general);
+		print_required_fields (&nmc->nmc_config, NMC_OF_FLAG_MAIN_HEADER_ONLY,
+		                       out_indices, header_name,
+		                       0, row);
+	}
 
 	/* Loop through the required sections and print them. */
 	for (k = 0; k < sections_array->len; k++) {
 		int section_idx = g_array_index (sections_array, int, k);
 		char *section_fld = (char *) g_ptr_array_index (fields_in_section, k);
 
-		if (nmc->print_output != NMC_PRINT_TERSE && !nmc->multiline_output && was_output)
+		if (nmc->nmc_config.print_output != NMC_PRINT_TERSE && !nmc->nmc_config.multiline_output && was_output)
 			g_print ("\n"); /* Print empty line between groups in tabular mode */
 
 		was_output = FALSE;
 
-		/* Remove any previous data */
-		nmc_empty_output_fields (nmc);
-
 		state = nm_device_get_state (device);
 		reason = nm_device_get_state_reason (device);
 
 		/* section GENERAL */
-		if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[0].name)) {
-			tmpl = nmc_fields_dev_show_general;
-			tmpl_len = sizeof (nmc_fields_dev_show_general);
-			nmc->print_fields.indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_SHOW_GENERAL_ALL,
-			                                                 tmpl, FALSE, NULL, NULL);
-			arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-			g_ptr_array_add (nmc->output_data, arr);
+		if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[0]->name)) {
+			NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+
+			tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_general;
+			out_indices = parse_output_fields (section_fld,
+			                                   tmpl, FALSE, NULL, NULL);
+			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+			g_ptr_array_add (out.output_data, arr);
 
 			state_str = g_strdup_printf ("%d (%s)", state, nmc_device_state_to_string (state));
 			reason_str = g_strdup_printf ("%d (%s)", reason, nmc_device_reason_to_string (reason));
@@ -1139,8 +1154,8 @@ show_device_info (NMDevice *device, NmCli *nmc)
 			mtu_str = g_strdup_printf ("%u", nm_device_get_mtu (device));
 			acon = nm_device_get_active_connection (device);
 
-			arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-			set_val_strc (arr, 0, nmc_fields_dev_show_sections[0].name);  /* "GENERAL"*/
+			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
+			set_val_strc (arr, 0, nmc_fields_dev_show_sections[0]->name);  /* "GENERAL"*/
 			set_val_strc (arr, 1, nm_device_get_iface (device));
 			set_val_strc (arr, 2, nm_device_get_type_description (device));
 			set_val_strc (arr, 3, G_OBJECT_TYPE_NAME (device));
@@ -1165,20 +1180,22 @@ show_device_info (NMDevice *device, NmCli *nmc)
 			set_val_strc (arr, 22, acon ? nm_active_connection_get_uuid (acon) : NULL);
 			set_val_strc (arr, 23, acon ? nm_object_get_path (NM_OBJECT (acon)) : NULL);
 			set_val_strc (arr, 24, nmc_device_metered_to_string (nm_device_get_metered (device)));
-			g_ptr_array_add (nmc->output_data, arr);
+			g_ptr_array_add (out.output_data, arr);
 
-			print_data (nmc);  /* Print all data */
+			print_data_prepare_width (out.output_data);
+			print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 			was_output = TRUE;
 		}
 
 		/* section CAPABILITIES */
-		if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[1].name)) {
-			tmpl = nmc_fields_dev_show_cap;
-			tmpl_len = sizeof (nmc_fields_dev_show_cap);
-			nmc->print_fields.indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_SHOW_CAP_ALL,
-			                                                 tmpl, FALSE, NULL, NULL);
-			arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-			g_ptr_array_add (nmc->output_data, arr);
+		if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[1]->name)) {
+			NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+
+			tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_cap;
+			out_indices = parse_output_fields (section_fld,
+			                                   tmpl, FALSE, NULL, NULL);
+			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+			g_ptr_array_add (out.output_data, arr);
 
 			caps = nm_device_get_capabilities (device);
 			speed = 0;
@@ -1192,15 +1209,16 @@ show_device_info (NMDevice *device, NmCli *nmc)
 			}
 			speed_str = speed ? g_strdup_printf (_("%u Mb/s"), speed) : g_strdup (_("unknown"));
 
-			arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-			set_val_strc (arr, 0, nmc_fields_dev_show_sections[1].name);  /* "CAPABILITIES" */
+			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
+			set_val_strc (arr, 0, nmc_fields_dev_show_sections[1]->name);  /* "CAPABILITIES" */
 			set_val_strc (arr, 1, (caps & NM_DEVICE_CAP_CARRIER_DETECT) ? _("yes") : _("no"));
 			set_val_str  (arr, 2, speed_str);
 			set_val_strc (arr, 3, (caps & NM_DEVICE_CAP_IS_SOFTWARE) ? _("yes") : _("no"));
 			set_val_strc (arr, 4, (caps & NM_DEVICE_CAP_SRIOV) ? _("yes") : _("no"));
-			g_ptr_array_add (nmc->output_data, arr);
+			g_ptr_array_add (out.output_data, arr);
 
-			print_data (nmc);  /* Print all data */
+			print_data_prepare_width (out.output_data);
+			print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 			was_output = TRUE;
 		}
 
@@ -1212,18 +1230,19 @@ show_device_info (NMDevice *device, NmCli *nmc)
 			GPtrArray *aps;
 
 			/* section WIFI-PROPERTIES */
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[2].name)) {
+			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[2]->name)) {
+				NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+
 				wcaps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (device));
 
-				tmpl = nmc_fields_dev_show_wifi_prop;
-				tmpl_len = sizeof (nmc_fields_dev_show_wifi_prop);
-				nmc->print_fields.indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_SHOW_WIFI_PROP_ALL,
-				                                                 tmpl, FALSE, NULL, NULL);
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-				g_ptr_array_add (nmc->output_data, arr);
+				tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_wifi_prop;
+				out_indices = parse_output_fields (section_fld,
+				                                   tmpl, FALSE, NULL, NULL);
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+				g_ptr_array_add (out.output_data, arr);
 
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-				set_val_strc (arr, 0, nmc_fields_dev_show_sections[2].name);  /* "WIFI-PROPERTIES" */
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
+				set_val_strc (arr, 0, nmc_fields_dev_show_sections[2]->name);  /* "WIFI-PROPERTIES" */
 				set_val_strc (arr, 1, (wcaps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) ?
 				                        _("yes") : _("no"));
 				set_val_strc (arr, 2, (wcaps & NM_WIFI_DEVICE_CAP_WPA) ? _("yes") : _("no"));
@@ -1236,57 +1255,67 @@ show_device_info (NMDevice *device, NmCli *nmc)
 				                      ((wcaps & NM_WIFI_DEVICE_CAP_FREQ_2GHZ) ? _("yes") : _("no")));
 				set_val_strc (arr, 9, !(wcaps & NM_WIFI_DEVICE_CAP_FREQ_VALID) ? _("unknown") :
 				                      ((wcaps & NM_WIFI_DEVICE_CAP_FREQ_5GHZ) ? _("yes") : _("no")));
-				g_ptr_array_add (nmc->output_data, arr);
+				g_ptr_array_add (out.output_data, arr);
 
-				print_data (nmc);  /* Print all data */
+				print_data_prepare_width (out.output_data);
+				print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 				was_output = TRUE;
 			}
 
 			/* section AP */
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[3].name)) {
+			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[3]->name)) {
+				NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+
 				if (state == NM_DEVICE_STATE_ACTIVATED) {
 					active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (device));
 					active_bssid = active_ap ? nm_access_point_get_bssid (active_ap) : NULL;
 				}
 
-				tmpl = nmc_fields_dev_wifi_list;
-				tmpl_len = sizeof (nmc_fields_dev_wifi_list);
-				nmc->print_fields.indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_WIFI_LIST_FOR_DEV_LIST,
-				                                                 tmpl, FALSE, NULL, NULL);
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-				g_ptr_array_add (nmc->output_data, arr);
+				tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_wifi_list;
+				out_indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_WIFI_LIST_FOR_DEV_LIST,
+				                                   tmpl, FALSE, NULL, NULL);
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+				g_ptr_array_add (out.output_data, arr);
+
+				{
+					APInfo info = {
+						.nmc = nmc,
+						.index = 1,
+						.output_flags = NMC_OF_FLAG_SECTION_PREFIX,
+						.active_bssid = active_bssid,
+						.device = nm_device_get_iface (device),
+						.output_data = out.output_data,
+					};
+
+					aps = sort_access_points (nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device)));
+					g_ptr_array_foreach (aps, fill_output_access_point, &info);
+					g_ptr_array_free (aps, FALSE);
+				}
 
-				info = g_malloc0 (sizeof (APInfo));
-				info->nmc = nmc;
-				info->index = 1;
-				info->output_flags = NMC_OF_FLAG_SECTION_PREFIX;
-				info->active_bssid = active_bssid;
-				info->device = nm_device_get_iface (device);
-				aps = sort_access_points (nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device)));
-				g_ptr_array_foreach ((GPtrArray *) aps, fill_output_access_point, (gpointer) info);
-				g_ptr_array_free (aps, FALSE);
-				g_free (info);
-				print_data (nmc);  /* Print all data */
+				print_data_prepare_width (out.output_data);
+				print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 				was_output = TRUE;
 			}
 		} else if (NM_IS_DEVICE_ETHERNET (device)) {
 			/* WIRED-PROPERTIES */
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[4].name)) {
-				tmpl = nmc_fields_dev_show_wired_prop;
-				tmpl_len = sizeof (nmc_fields_dev_show_wired_prop);
-				nmc->print_fields.indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_SHOW_WIRED_PROP_ALL,
-				                                                 tmpl, FALSE, NULL, NULL);
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-				g_ptr_array_add (nmc->output_data, arr);
-
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-				set_val_strc (arr, 0, nmc_fields_dev_show_sections[4].name);  /* "WIRED-PROPERTIES" */
+			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[4]->name)) {
+				NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+
+				tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_wired_prop;
+				out_indices = parse_output_fields (section_fld,
+				                                   tmpl, FALSE, NULL, NULL);
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+				g_ptr_array_add (out.output_data, arr);
+
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
+				set_val_strc (arr, 0, nmc_fields_dev_show_sections[4]->name);  /* "WIRED-PROPERTIES" */
 				set_val_strc (arr, 1, (nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (device))) ?
 				                        _("on") : _("off"));
 				set_val_arrc (arr, 2, ((const char **) nm_device_ethernet_get_s390_subchannels (NM_DEVICE_ETHERNET (device))));
-				g_ptr_array_add (nmc->output_data, arr);
+				g_ptr_array_add (out.output_data, arr);
 
-				print_data (nmc);  /* Print all data */
+				print_data_prepare_width (out.output_data);
+				print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 				was_output = TRUE;
 			}
 		}
@@ -1298,96 +1327,99 @@ show_device_info (NMDevice *device, NmCli *nmc)
 		dhcp6 = nm_device_get_dhcp6_config (device);
 
 		/* IP4 */
-		if (cfg4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[7].name))
-			was_output = print_ip4_config (cfg4, nmc, nmc_fields_dev_show_sections[7].name, section_fld);
+		if (cfg4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[7]->name))
+			was_output = print_ip4_config (cfg4, &nmc->nmc_config, section_fld);
 
 		/* DHCP4 */
-		if (dhcp4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[8].name))
-			was_output = print_dhcp4_config (dhcp4, nmc, nmc_fields_dev_show_sections[8].name, section_fld);
+		if (dhcp4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[8]->name))
+			was_output = print_dhcp4_config (dhcp4, &nmc->nmc_config, nmc_fields_dev_show_sections[8]->name, section_fld);
 
 		/* IP6 */
-		if (cfg6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[9].name))
-			was_output = print_ip6_config (cfg6, nmc, nmc_fields_dev_show_sections[9].name, section_fld);
+		if (cfg6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[9]->name))
+			was_output = print_ip6_config (cfg6, &nmc->nmc_config, nmc_fields_dev_show_sections[9]->name, section_fld);
 
 		/* DHCP6 */
-		if (dhcp6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[10].name))
-			was_output = print_dhcp6_config (dhcp6, nmc, nmc_fields_dev_show_sections[10].name, section_fld);
+		if (dhcp6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[10]->name))
+			was_output = print_dhcp6_config (dhcp6, &nmc->nmc_config, nmc_fields_dev_show_sections[10]->name, section_fld);
 
 		/* Bond specific information */
 		if (NM_IS_DEVICE_BOND (device)) {
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[11].name))
-				was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[11].name, section_fld);
+			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[11]->name))
+				was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[11]->name, section_fld);
 		}
 
 		/* Team specific information */
 		if (NM_IS_DEVICE_TEAM (device)) {
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[12].name))
-				was_output = print_team_info (device, nmc, nmc_fields_dev_show_sections[12].name, section_fld);
+			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[12]->name))
+				was_output = print_team_info (device, nmc, nmc_fields_dev_show_sections[12]->name, section_fld);
 		}
 
 		/* Bridge specific information */
 		if (NM_IS_DEVICE_BRIDGE (device)) {
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[13].name))
-				was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[13].name, section_fld);
+			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[13]->name))
+				was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[13]->name, section_fld);
 		}
 
 		/* VLAN-specific information */
 		if ((NM_IS_DEVICE_VLAN (device))) {
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[14].name)) {
+			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[14]->name)) {
 				char * vlan_id_str = g_strdup_printf ("%u", nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device)));
 				NMDevice *parent = nm_device_vlan_get_parent (NM_DEVICE_VLAN (device));
+				NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
-				tmpl = nmc_fields_dev_show_vlan_prop;
-				tmpl_len = sizeof (nmc_fields_dev_show_vlan_prop);
-				nmc->print_fields.indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_SHOW_VLAN_PROP_ALL,
-				                                                 tmpl, FALSE, NULL, NULL);
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-				g_ptr_array_add (nmc->output_data, arr);
+				tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_vlan_prop;
+				out_indices = parse_output_fields (section_fld,
+				                                   tmpl, FALSE, NULL, NULL);
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+				g_ptr_array_add (out.output_data, arr);
 
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-				set_val_strc (arr, 0, nmc_fields_dev_show_sections[14].name);  /* "VLAN" */
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
+				set_val_strc (arr, 0, nmc_fields_dev_show_sections[14]->name);  /* "VLAN" */
 				set_val_strc (arr, 1, parent ? nm_device_get_iface (parent) : NULL);
 				set_val_str  (arr, 2, vlan_id_str);
-				g_ptr_array_add (nmc->output_data, arr);
+				g_ptr_array_add (out.output_data, arr);
 
-				print_data (nmc);  /* Print all data */
+				print_data_prepare_width (out.output_data);
+				print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 
 				was_output = TRUE;
 			}
 		}
 
 		if (NM_IS_DEVICE_BT (device)) {
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[15].name)) {
-				tmpl = nmc_fields_dev_show_bluetooth;
-				tmpl_len = sizeof (nmc_fields_dev_show_bluetooth);
-				nmc->print_fields.indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_SHOW_BLUETOOTH_ALL,
-				                                                 tmpl, FALSE, NULL, NULL);
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-				g_ptr_array_add (nmc->output_data, arr);
-
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-				set_val_strc (arr, 0, nmc_fields_dev_show_sections[15].name);  /* "BLUETOOTH" */
+			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[15]->name)) {
+				NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+
+				tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_bluetooth;
+				out_indices = parse_output_fields (section_fld,
+				                                   tmpl, FALSE, NULL, NULL);
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+				g_ptr_array_add (out.output_data, arr);
+
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
+				set_val_strc (arr, 0, nmc_fields_dev_show_sections[15]->name);  /* "BLUETOOTH" */
 				set_val_str (arr, 1, bluetooth_caps_to_string (nm_device_bt_get_capabilities (NM_DEVICE_BT (device))));
-				g_ptr_array_add (nmc->output_data, arr);
+				g_ptr_array_add (out.output_data, arr);
 
-				print_data (nmc);  /* Print all data */
+				print_data_prepare_width (out.output_data);
+				print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 				was_output = TRUE;
 			}
 		}
 
 		/* section CONNECTIONS */
-		if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[16].name)) {
+		if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[16]->name)) {
 			const GPtrArray *avail_cons;
 			GString *ac_paths_str;
 			char **ac_arr = NULL;
 			int i;
+			NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
-			tmpl = nmc_fields_dev_show_connections;
-			tmpl_len = sizeof (nmc_fields_dev_show_connections);
-			nmc->print_fields.indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_SHOW_CONNECTIONS_ALL,
-			                                                 tmpl, FALSE, NULL, NULL);
-			arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-			g_ptr_array_add (nmc->output_data, arr);
+			tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_connections;
+			out_indices = parse_output_fields (section_fld,
+			                                   tmpl, FALSE, NULL, NULL);
+			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
+			g_ptr_array_add (out.output_data, arr);
 
 			/* available-connections */
 			avail_cons = nm_device_get_available_connections (device);
@@ -1413,13 +1445,14 @@ show_device_info (NMDevice *device, NmCli *nmc)
 			if (ac_paths_str->len > 0)
 				g_string_append_c (ac_paths_str, '}');
 
-			arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-			set_val_strc (arr, 0, nmc_fields_dev_show_sections[16].name);  /* "CONNECTIONS" */
+			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
+			set_val_strc (arr, 0, nmc_fields_dev_show_sections[16]->name);  /* "CONNECTIONS" */
 			set_val_str  (arr, 1, ac_paths_str->str);
 			set_val_arr  (arr, 2, (ac_arr));
-			g_ptr_array_add (nmc->output_data, arr);
+			g_ptr_array_add (out.output_data, arr);
 
-			print_data (nmc);  /* Print all data */
+			print_data_prepare_width (out.output_data);
+			print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 
 			g_string_free (ac_paths_str, FALSE);
 			was_output = TRUE;
@@ -1435,30 +1468,29 @@ show_device_info (NMDevice *device, NmCli *nmc)
 }
 
 void
-nmc_device_state_to_color (NMDeviceState state, NmcTermColor *color, NmcTermFormat *color_fmt)
+nmc_device_state_to_color (NMDeviceState state, NMMetaTermColor *color, NMMetaTermFormat *color_fmt)
 {
-	*color = NMC_TERM_COLOR_NORMAL;
-	*color_fmt = NMC_TERM_FORMAT_NORMAL;
+	*color = NM_META_TERM_COLOR_NORMAL;
+	*color_fmt = NM_META_TERM_FORMAT_NORMAL;
 
 	if (state <= NM_DEVICE_STATE_UNAVAILABLE)
-		*color_fmt= NMC_TERM_FORMAT_DIM;
+		*color_fmt= NM_META_TERM_FORMAT_DIM;
 	else if (state == NM_DEVICE_STATE_DISCONNECTED)
-		*color = NMC_TERM_COLOR_RED;
+		*color = NM_META_TERM_COLOR_RED;
 	else if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES)
-		*color = NMC_TERM_COLOR_YELLOW;
+		*color = NM_META_TERM_COLOR_YELLOW;
 	else if (state == NM_DEVICE_STATE_ACTIVATED)
-		*color = NMC_TERM_COLOR_GREEN;
+		*color = NM_META_TERM_COLOR_GREEN;
 }
 
 static void
-fill_output_device_status (NMDevice *device, NmCli *nmc)
+fill_output_device_status (NMDevice *device, GPtrArray *output_data)
 {
 	NMActiveConnection *ac;
 	NMDeviceState state;
-	NmcTermColor color;
-	NmcTermFormat color_fmt;
-	NmcOutputField *arr = nmc_dup_fields_array (nmc_fields_dev_status,
-	                                            sizeof (nmc_fields_dev_status),
+	NMMetaTermColor color;
+	NMMetaTermFormat color_fmt;
+	NmcOutputField *arr = nmc_dup_fields_array ((const NMMetaAbstractInfo *const*) nmc_fields_dev_status,
 	                                            0);
 
 	state = nm_device_get_state (device);
@@ -1477,7 +1509,7 @@ fill_output_device_status (NMDevice *device, NmCli *nmc)
 	set_val_strc (arr, 5, ac ? nm_active_connection_get_uuid (ac) : NULL);
 	set_val_strc (arr, 6, ac ? nm_object_get_path (NM_OBJECT (ac)) : NULL);
 
-	g_ptr_array_add (nmc->output_data, arr);
+	g_ptr_array_add (output_data, arr);
 }
 
 static NMCResultCode
@@ -1486,11 +1518,10 @@ do_devices_status (NmCli *nmc, int argc, char **argv)
 	GError *error = NULL;
 	NMDevice **devices;
 	int i;
-	char *fields_str;
-	char *fields_all =    NMC_FIELDS_DEV_STATUS_ALL;
-	char *fields_common = NMC_FIELDS_DEV_STATUS_COMMON;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	const char *fields_str = NULL;
+	const NMMetaAbstractInfo *const*tmpl;
+	NmcOutputField *arr;
+	NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
 	next_arg (nmc, &argc, &argv, NULL);
 
@@ -1504,15 +1535,13 @@ do_devices_status (NmCli *nmc, int argc, char **argv)
 	}
 
 	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
-		fields_str = fields_common;
-	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
-		fields_str = fields_all;
-	else
+		fields_str = NMC_FIELDS_DEV_STATUS_COMMON;
+	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) {
+	} else
 		fields_str = nmc->required_fields;
 
-	tmpl = nmc_fields_dev_status;
-	tmpl_len = sizeof (nmc_fields_dev_status);
-	nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
+	tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_status;
+	out_indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
 
 	if (error) {
 		g_string_printf (nmc->return_text, _("Error: 'device status': %s"), error->message);
@@ -1521,16 +1550,15 @@ do_devices_status (NmCli *nmc, int argc, char **argv)
 	}
 
 	/* Add headers */
-	nmc->print_fields.header_name = _("Status of devices");
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
+	arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
+	g_ptr_array_add (out.output_data, arr);
 
 	devices = nmc_get_devices_sorted (nmc->client);
 	for (i = 0; devices[i]; i++)
-		fill_output_device_status (devices[i], nmc);
+		fill_output_device_status (devices[i], out.output_data);
 
-	/* Now print all data */
-	print_data (nmc);
+	print_data_prepare_width (out.output_data);
+	print_data (&nmc->nmc_config, out_indices, _("Status of devices"), 0, &out);
 
 	g_free (devices);
 
@@ -1544,7 +1572,7 @@ do_device_show (NmCli *nmc, int argc, char **argv)
 
 	next_arg (nmc, &argc, &argv, NULL);
 	if (!nmc->mode_specified)
-		nmc->multiline_output = TRUE;  /* multiline mode is default for 'device show' */
+		nmc->nmc_config_mutable.multiline_output = TRUE;  /* multiline mode is default for 'device show' */
 
 	if (argc) {
 		NMDevice *device;
@@ -1573,7 +1601,6 @@ do_device_show (NmCli *nmc, int argc, char **argv)
 
 		/* Show details for all devices */
 		for (i = 0; devices[i]; i++) {
-			nmc_empty_output_fields (nmc);
 			if (!show_device_info (devices[i], nmc))
 				break;
 			if (devices[i + 1])
@@ -1708,7 +1735,7 @@ add_and_activate_cb (GObject *client,
 		if (nmc->nowait_flag || state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
 			/* User doesn't want to wait or already activated */
 			if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
-				if (nmc->print_output == NMC_PRINT_PRETTY)
+				if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 					nmc_terminal_erase_line ();
 				if (info->hotspot)
 					g_print (_("Connection with UUID '%s' created and activated on device '%s'\n"),
@@ -1726,7 +1753,7 @@ add_and_activate_cb (GObject *client,
 
 			g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc);  /* Exit if timeout expires */
 
-			if (nmc->print_output == NMC_PRINT_PRETTY)
+			if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 				progress_id = g_timeout_add (120, progress_cb, device);
 		}
 	}
@@ -1800,7 +1827,7 @@ connect_device_cb (GObject *client, GAsyncResult *result, gpointer user_data)
 
 		if (nmc->nowait_flag || state == NM_DEVICE_STATE_ACTIVATED) {
 			/* Don't want to wait or device already activated */
-			if (state == NM_DEVICE_STATE_ACTIVATED && nmc->print_output == NMC_PRINT_PRETTY) {
+			if (state == NM_DEVICE_STATE_ACTIVATED && nmc->nmc_config.print_output == NMC_PRINT_PRETTY) {
 				nmc_terminal_erase_line ();
 				g_print (_("Device '%s' has been connected.\n"), nm_device_get_iface (device));
 			}
@@ -1880,7 +1907,7 @@ do_device_connect (NmCli *nmc, int argc, char **argv)
 	                                     info);
 
 	/* Start progress indication */
-	if (nmc->print_output == NMC_PRINT_PRETTY)
+	if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 		progress_id = g_timeout_add (120, progress_cb, device);
 
 	return nmc->return_value;
@@ -1985,7 +2012,7 @@ reapply_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 		nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT;
 		device_cb_info_finish (info, device);
 	} else {
-		if (nmc->print_output == NMC_PRINT_PRETTY)
+		if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 			nmc_terminal_erase_line ();
 		g_print (_("Connection successfully reapplied to device '%s'.\n"),
 		         nm_device_get_iface (device));
@@ -2054,7 +2081,7 @@ modify_reapply_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 		g_error_free (error);
 		nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT;
 	} else {
-		if (nmc->print_output == NMC_PRINT_PRETTY)
+		if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 			nmc_terminal_erase_line ();
 		g_print (_("Connection successfully reapplied to device '%s'.\n"),
 		         nm_device_get_iface (device));
@@ -2158,7 +2185,7 @@ disconnect_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 		if (nmc->nowait_flag || state <= NM_DEVICE_STATE_DISCONNECTED) {
 			/* Don't want to wait or device already disconnected */
 			if (state <= NM_DEVICE_STATE_DISCONNECTED) {
-				if (nmc->print_output == NMC_PRINT_PRETTY)
+				if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
 					nmc_terminal_erase_line ();
 				g_print (_("Device '%s' successfully disconnected.\n"),
 				         nm_device_get_iface (device));
@@ -2383,12 +2410,12 @@ static void
 device_state (NMDevice *device, GParamSpec *pspec, NmCli *nmc)
 {
 	NMDeviceState state = nm_device_get_state (device);
-	NmcTermColor color;
-	NmcTermFormat color_fmt;
+	NMMetaTermColor color;
+	NMMetaTermFormat color_fmt;
 	char *str;
 
 	nmc_device_state_to_color (state, &color, &color_fmt);
-	str = nmc_colorize (nmc, color, color_fmt, "%s: %s\n",
+	str = nmc_colorize (nmc->nmc_config.use_colors, color, color_fmt, "%s: %s\n",
 	                    nm_device_get_iface (device),
 	                    nmc_device_state_to_string (state));
 
@@ -2475,12 +2502,11 @@ do_devices_monitor (NmCli *nmc, int argc, char **argv)
 }
 
 static void
-show_access_point_info (NMDevice *device, NmCli *nmc)
+show_access_point_info (NMDevice *device, NmCli *nmc, NmcOutputData *out)
 {
 	NMAccessPoint *active_ap = NULL;
 	const char *active_bssid = NULL;
 	GPtrArray *aps;
-	APInfo *info;
 	NmcOutputField *arr;
 
 	if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) {
@@ -2488,23 +2514,26 @@ show_access_point_info (NMDevice *device, NmCli *nmc)
 		active_bssid = active_ap ? nm_access_point_get_bssid (active_ap) : NULL;
 	}
 
-	arr = nmc_dup_fields_array (nmc_fields_dev_wifi_list, sizeof (nmc_fields_dev_wifi_list),
+	arr = nmc_dup_fields_array ((const NMMetaAbstractInfo *const*) nmc_fields_dev_wifi_list,
 	                            NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
+	g_ptr_array_add (out->output_data, arr);
 
-	info = g_malloc0 (sizeof (APInfo));
-	info->nmc = nmc;
-	info->index = 1;
-	info->output_flags = 0;
-	info->active_bssid = active_bssid;
-	info->device = nm_device_get_iface (device);
-	aps = sort_access_points (nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device)));
-	g_ptr_array_foreach ((GPtrArray *) aps, fill_output_access_point, (gpointer) info);
-	g_ptr_array_free (aps, FALSE);
-
-	print_data (nmc);  /* Print all data */
-	nmc_empty_output_fields (nmc);
-	g_free (info);
+	{
+		APInfo info = {
+			.nmc = nmc,
+			.index = 1,
+			.output_flags = 0,
+			.active_bssid = active_bssid,
+			.device = nm_device_get_iface (device),
+			.output_data = out->output_data,
+		};
+
+		aps = sort_access_points (nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device)));
+		g_ptr_array_foreach (aps, fill_output_access_point, &info);
+		g_ptr_array_free (aps, FALSE);
+	}
+
+	print_data_prepare_width (out->output_data);
 }
 
 /*
@@ -2631,12 +2660,12 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 	const GPtrArray *aps;
 	APInfo *info;
 	int i, j;
-	char *fields_str;
-	char *fields_all =    NMC_FIELDS_DEV_WIFI_LIST_ALL;
-	char *fields_common = NMC_FIELDS_DEV_WIFI_LIST_COMMON;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	const char *fields_str = NULL;
+	const NMMetaAbstractInfo *const*tmpl;
+	NmcOutputField *arr;
 	const char *base_hdr = _("Wi-Fi scan list");
+	NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+	gs_free char *header_name = NULL;
 
 	devices = nmc_get_devices_sorted (nmc->client);
 
@@ -2674,15 +2703,13 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 	}
 
 	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
-		fields_str = fields_common;
-	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
-		fields_str = fields_all;
-	else
+		fields_str = NMC_FIELDS_DEV_WIFI_LIST_COMMON;
+	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) {
+	} else
 		fields_str = nmc->required_fields;
 
-	tmpl = nmc_fields_dev_wifi_list;
-	tmpl_len = sizeof (nmc_fields_dev_wifi_list);
-	nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
+	tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_wifi_list;
+	out_indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
 
 	if (error) {
 		g_string_printf (nmc->return_text, _("Error: 'device wifi': %s"), error->message);
@@ -2694,13 +2721,14 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 		return nmc->return_value;
 
 	if (ifname) {
+
 		device = find_wifi_device_by_iface (devices, ifname, NULL);
 		if (!device) {
 			g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), ifname);
 			return NMC_RESULT_ERROR_NOT_FOUND;
 		}
 		/* Main header name */
-		nmc->print_fields.header_name = (char *) construct_header_name (base_hdr, ifname);
+		header_name = construct_header_name (base_hdr, ifname);
 
 		if (NM_IS_DEVICE_WIFI (device)) {
 			if (bssid_user) {
@@ -2722,8 +2750,8 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 					return NMC_RESULT_ERROR_NOT_FOUND;
 				}
 				/* Add headers (field names) */
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-				g_ptr_array_add (nmc->output_data, arr);
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
+				g_ptr_array_add (out.output_data, arr);
 
 				info = g_malloc0 (sizeof (APInfo));
 				info->nmc = nmc;
@@ -2734,10 +2762,12 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 
 				fill_output_access_point (ap, info);
 
-				print_data (nmc);  /* Print all data */
+				print_data_prepare_width (out.output_data);
+				print_data (&nmc->nmc_config, out_indices, header_name, 0, &out);
 				g_free (info);
 			} else {
-				show_access_point_info (device, nmc);
+				show_access_point_info (device, nmc, &out);
+				print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 			}
 		} else {
 			if (   nm_device_get_device_type (device) == NM_DEVICE_TYPE_GENERIC
@@ -2760,16 +2790,18 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 			/* Specific AP requested - list only that */
 			for (i = 0; devices[i]; i++) {
 				NMDevice *dev = devices[i];
+				NMC_OUTPUT_DATA_DEFINE_SCOPED (out2);
+				gs_free char *header_name2 = NULL;
 
 				if (!NM_IS_DEVICE_WIFI (dev))
 					continue;
 
 				/* Main header name */
-				nmc->print_fields.header_name = (char *) construct_header_name (base_hdr, nm_device_get_iface (dev));
-				nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, NULL);
+				header_name2 = construct_header_name (base_hdr, nm_device_get_iface (dev));
+				out2_indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, NULL);
 
-				arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-				g_ptr_array_add (nmc->output_data, arr);
+				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
+				g_ptr_array_add (out2.output_data, arr);
 
 				aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (dev));
 				for (j = 0; j < aps->len; j++) {
@@ -2794,8 +2826,8 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 				}
 				if (empty_line)
 					g_print ("\n"); /* Empty line between devices' APs */
-				print_data (nmc);  /* Print all data */
-				nmc_empty_output_fields (nmc);
+				print_data_prepare_width (out2.output_data);
+				print_data (&nmc->nmc_config, out2_indices, header_name2, 0, &out2);
 				empty_line = TRUE;
 			}
 			if (!ap) {
@@ -2806,16 +2838,19 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 		} else {
 			for (i = 0; devices[i]; i++) {
 				NMDevice *dev = devices[i];
+				NMC_OUTPUT_DATA_DEFINE_SCOPED (out2);
+				gs_free char *header_name2 = NULL;
 
 				/* Main header name */
-				nmc->print_fields.header_name = (char *) construct_header_name (base_hdr,
-				                                                                nm_device_get_iface (dev));
-				nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, NULL);
+				header_name2 = construct_header_name (base_hdr,
+				                                      nm_device_get_iface (dev));
+				out2_indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, NULL);
 
 				if (NM_IS_DEVICE_WIFI (dev)) {
 					if (empty_line)
 						g_print ("\n"); /* Empty line between devices' APs */
-					show_access_point_info (dev, nmc);
+					show_access_point_info (dev, nmc, &out2);
+					print_data (&nmc->nmc_config, out2_indices, header_name2, 0, &out2);
 					empty_line = TRUE;
 				}
 			}
@@ -3132,7 +3167,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
 	if (ap_flags & NM_802_11_AP_FLAGS_PRIVACY) {
 		/* Ask for missing password when one is expected and '--ask' is used */
 		if (!password && nmc->ask)
-			password = passwd_ask = nmc_readline_echo (nmc->show_secrets, _("Password: "));
+			password = passwd_ask = nmc_readline_echo (nmc->nmc_config.show_secrets, _("Password: "));
 
 		if (password) {
 			if (!connection)
@@ -3430,7 +3465,7 @@ do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv)
 
 		next_arg (nmc, &argc, &argv, NULL);
 	}
-	show_password = nmc->show_secrets || show_password;
+	show_password = nmc->nmc_config.show_secrets || show_password;
 
 	if (nmc->complete)
 		return nmc->return_value;
@@ -3670,34 +3705,35 @@ do_device_wifi (NmCli *nmc, int argc, char **argv)
 }
 
 static int
-show_device_lldp_list (NMDevice *device, NmCli *nmc, char *fields_str, int *counter)
+show_device_lldp_list (NMDevice *device, NmCli *nmc, const char *fields_str, int *counter)
 {
-	NmcOutputField *tmpl, *arr;
+	const NMMetaAbstractInfo *const*tmpl;
+	NmcOutputField *arr;
 	GPtrArray *neighbors;
-	size_t tmpl_len;
 	const char *str;
 	int i;
+	NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+	gs_free char *header_name = NULL;
 
 	neighbors = nm_device_get_lldp_neighbors (device);
 
 	if (!neighbors || !neighbors->len)
 		return 0;
 
-	tmpl = nmc_fields_dev_lldp_list;
-	tmpl_len = sizeof (nmc_fields_dev_lldp_list);
+	tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_lldp_list;
 
 	/* Main header name */
-	nmc->print_fields.header_name = (char *) construct_header_name (_("Device LLDP neighbors"),
-	                                                                nm_device_get_iface (device));
-	nmc->print_fields.indices = parse_output_fields (fields_str, nmc_fields_dev_lldp_list, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
+	header_name = construct_header_name (_("Device LLDP neighbors"),
+	                                     nm_device_get_iface (device));
+	out_indices = parse_output_fields (fields_str, (const NMMetaAbstractInfo *const*) nmc_fields_dev_lldp_list, FALSE, NULL, NULL);
+	arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
+	g_ptr_array_add (out.output_data, arr);
 
 	for (i = 0; i < neighbors->len; i++) {
 		NMLldpNeighbor *neighbor = neighbors->pdata[i];
 		guint value;
 
-		arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
+		arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
 		set_val_str (arr, 0, g_strdup_printf ("NEIGHBOR[%d]", (*counter)++));
 
 		set_val_strc (arr, 1, nm_device_get_iface (device));
@@ -3744,11 +3780,11 @@ show_device_lldp_list (NMDevice *device, NmCli *nmc, char *fields_str, int *coun
 		if (nm_lldp_neighbor_get_attr_uint_value (neighbor, NM_LLDP_ATTR_PORT_ID_TYPE, &value))
 			set_val_strc (arr, 15, g_strdup_printf ("%u", value));
 
-		g_ptr_array_add (nmc->output_data, arr);
+		g_ptr_array_add (out.output_data, arr);
 	}
 
-	print_data (nmc);
-	nmc_empty_output_fields (nmc);
+	print_data_prepare_width (out.output_data);
+	print_data (&nmc->nmc_config, out_indices, header_name, 0, &out);
 
 	return neighbors->len;
 }
@@ -3758,8 +3794,9 @@ do_device_lldp_list (NmCli *nmc, int argc, char **argv)
 {
 	NMDevice *device = NULL;
 	gs_free_error GError *error = NULL;
-	char *fields_str;
+	const char *fields_str = NULL;
 	int counter = 0;
+	gs_unref_array GArray *out_indices = NULL;
 
 	next_arg (nmc, &argc, &argv, NULL);
 	while (argc > 0) {
@@ -3789,12 +3826,11 @@ do_device_lldp_list (NmCli *nmc, int argc, char **argv)
 
 	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
 		fields_str = NMC_FIELDS_DEV_LLDP_LIST_COMMON;
-	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
-		fields_str = NMC_FIELDS_DEV_LLDP_LIST_ALL;
-	else
+	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) {
+	} else
 		fields_str = nmc->required_fields;
 
-	nmc->print_fields.indices = parse_output_fields (fields_str, nmc_fields_dev_lldp_list, FALSE, NULL, &error);
+	out_indices = parse_output_fields (fields_str, (const NMMetaAbstractInfo *const*) nmc_fields_dev_lldp_list, FALSE, NULL, &error);
 
 	if (error) {
 		g_string_printf (nmc->return_text, _("Error: 'device lldp list': %s"), error->message);
@@ -3805,16 +3841,13 @@ do_device_lldp_list (NmCli *nmc, int argc, char **argv)
 		return nmc->return_value;
 
 	if (device) {
-		nmc_empty_output_fields (nmc);
 		show_device_lldp_list (device, nmc, fields_str, &counter);
 	} else {
 		NMDevice **devices = nmc_get_devices_sorted (nmc->client);
 		int i;
 
-		for (i = 0; devices[i]; i++) {
-			nmc_empty_output_fields (nmc);
+		for (i = 0; devices[i]; i++)
 			show_device_lldp_list (devices[i], nmc, fields_str, &counter);
-		}
 
 		g_free (devices);
 	}
@@ -3831,7 +3864,7 @@ static NMCResultCode
 do_device_lldp (NmCli *nmc, int argc, char **argv)
 {
 	if (!nmc->mode_specified)
-		nmc->multiline_output = TRUE;  /* multiline mode is default for 'device lldp' */
+		nmc->nmc_config_mutable.multiline_output = TRUE;  /* multiline mode is default for 'device lldp' */
 
 	next_arg (nmc, &argc, &argv, NULL);
 	nmc_do_cmd (nmc, device_lldp_cmds, *argv, argc, argv);
diff --git a/clients/cli/devices.h b/clients/cli/devices.h
index 672944be..2c261bc7 100644
--- a/clients/cli/devices.h
+++ b/clients/cli/devices.h
@@ -32,22 +32,22 @@ void monitor_devices (NmCli *nmc);
 
 NMDevice ** nmc_get_devices_sorted (NMClient *client);
 
-void nmc_device_state_to_color (NMDeviceState state, NmcTermColor *color, NmcTermFormat *color_fmt);
-
-extern NmcOutputField nmc_fields_dev_status[];
-extern NmcOutputField nmc_fields_dev_show_general[];
-extern NmcOutputField nmc_fields_dev_show_connections[];
-extern NmcOutputField nmc_fields_dev_show_cap[];
-extern NmcOutputField nmc_fields_dev_show_wired_prop[];
-extern NmcOutputField nmc_fields_dev_show_wifi_prop[];
-extern NmcOutputField nmc_fields_dev_show_wimax_prop[];
-extern NmcOutputField nmc_fields_dev_wifi_list[];
-extern NmcOutputField nmc_fields_dev_wimax_list[];
-extern NmcOutputField nmc_fields_dev_show_master_prop[];
-extern NmcOutputField nmc_fields_dev_show_team_prop[];
-extern NmcOutputField nmc_fields_dev_show_vlan_prop[];
-extern NmcOutputField nmc_fields_dev_show_bluetooth[];
-extern NmcOutputField nmc_fields_dev_show_sections[];
-extern NmcOutputField nmc_fields_dev_lldp_list[];
+void nmc_device_state_to_color (NMDeviceState state, NMMetaTermColor *color, NMMetaTermFormat *color_fmt);
+
+extern const NmcMetaGenericInfo *const nmc_fields_dev_status[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_general[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_connections[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_cap[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_wired_prop[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_wifi_prop[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_wimax_prop[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_wifi_list[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_wimax_list[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_master_prop[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_team_prop[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_vlan_prop[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_bluetooth[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_show_sections[];
+extern const NmcMetaGenericInfo *const nmc_fields_dev_lldp_list[];
 
 #endif /* NMC_DEVICES_H */
diff --git a/clients/cli/general.c b/clients/cli/general.c
index 68fab6e0..5ae31e1b 100644
--- a/clients/cli/general.c
+++ b/clients/cli/general.c
@@ -14,39 +14,253 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2010 - 2015 Red Hat, Inc.
+ * Copyright 2010 - 2017 Red Hat, Inc.
  */
 
 #include "nm-default.h"
 
+#include "general.h"
+
 #include <string.h>
 #include <stdlib.h>
 
+#include "nm-common-macros.h"
+
+#include "nm-client-utils.h"
+
 #include "polkit-agent.h"
 #include "utils.h"
 #include "common.h"
-#include "general.h"
 #include "common.h"
-#include "nm-common-macros.h"
-
 #include "devices.h"
 #include "connections.h"
 
-/* Available fields for 'general status' */
-static NmcOutputField nmc_fields_nm_status[] = {
-	{"RUNNING",      N_("RUNNING")},       /* 0 */
-	{"VERSION",      N_("VERSION")},       /* 1 */
-	{"STATE",        N_("STATE")},         /* 2 */
-	{"STARTUP",      N_("STARTUP")},       /* 3 */
-	{"CONNECTIVITY", N_("CONNECTIVITY")},  /* 4 */
-	{"NETWORKING",   N_("NETWORKING")},    /* 5 */
-	{"WIFI-HW",      N_("WIFI-HW")},       /* 6 */
-	{"WIFI",         N_("WIFI")},          /* 7 */
-	{"WWAN-HW",      N_("WWAN-HW")},       /* 8 */
-	{"WWAN",         N_("WWAN")},          /* 9 */
-	{"WIMAX-HW",     N_("WIMAX-HW")},      /* 10 */
-	{"WIMAX",        N_("WIMAX")},         /* 11 */
-	{NULL, NULL}
+/*****************************************************************************/
+
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (nm_state_to_string_no_l10n, NMState,
+	NM_UTILS_LOOKUP_DEFAULT (N_("unknown")),
+	NM_UTILS_LOOKUP_ITEM (NM_STATE_ASLEEP,           N_("asleep")),
+	NM_UTILS_LOOKUP_ITEM (NM_STATE_CONNECTING,       N_("connecting")),
+	NM_UTILS_LOOKUP_ITEM (NM_STATE_CONNECTED_LOCAL,  N_("connected (local only)")),
+	NM_UTILS_LOOKUP_ITEM (NM_STATE_CONNECTED_SITE,   N_("connected (site only)")),
+	NM_UTILS_LOOKUP_ITEM (NM_STATE_CONNECTED_GLOBAL, N_("connected")),
+	NM_UTILS_LOOKUP_ITEM (NM_STATE_DISCONNECTING,    N_("disconnecting")),
+	NM_UTILS_LOOKUP_ITEM (NM_STATE_DISCONNECTED,     N_("disconnected")),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (NM_STATE_UNKNOWN),
+);
+
+static const char *
+nm_state_to_string (NMState state)
+{
+	return _(nm_state_to_string_no_l10n (state));
+}
+
+static NMMetaTermColor
+state_to_color (NMState state)
+{
+	switch (state) {
+	case NM_STATE_CONNECTING:
+		return NM_META_TERM_COLOR_YELLOW;
+	case NM_STATE_CONNECTED_LOCAL:
+	case NM_STATE_CONNECTED_SITE:
+	case NM_STATE_CONNECTED_GLOBAL:
+		return NM_META_TERM_COLOR_GREEN;
+	case NM_STATE_DISCONNECTING:
+		return NM_META_TERM_COLOR_YELLOW;
+	case NM_STATE_ASLEEP:
+	case NM_STATE_DISCONNECTED:
+		return NM_META_TERM_COLOR_RED;
+	default:
+		return NM_META_TERM_COLOR_NORMAL;
+	}
+}
+
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (nm_connectivity_to_string_no_l10n, NMConnectivityState,
+	NM_UTILS_LOOKUP_DEFAULT (N_("unknown")),
+	NM_UTILS_LOOKUP_ITEM (NM_CONNECTIVITY_NONE,    N_("none")),
+	NM_UTILS_LOOKUP_ITEM (NM_CONNECTIVITY_PORTAL,  N_("portal")),
+	NM_UTILS_LOOKUP_ITEM (NM_CONNECTIVITY_LIMITED, N_("limited")),
+	NM_UTILS_LOOKUP_ITEM (NM_CONNECTIVITY_FULL,    N_("full")),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (NM_CONNECTIVITY_UNKNOWN),
+);
+
+static const char *
+nm_connectivity_to_string (NMConnectivityState connectivity)
+{
+	return _(nm_connectivity_to_string_no_l10n (connectivity));
+}
+
+static NMMetaTermColor
+connectivity_to_color (NMConnectivityState connectivity)
+{
+	switch (connectivity) {
+	case NM_CONNECTIVITY_NONE:
+		return NM_META_TERM_COLOR_RED;
+	case NM_CONNECTIVITY_PORTAL:
+	case NM_CONNECTIVITY_LIMITED:
+		return NM_META_TERM_COLOR_YELLOW;
+	case NM_CONNECTIVITY_FULL:
+		return NM_META_TERM_COLOR_GREEN;
+	default:
+		return NM_META_TERM_COLOR_NORMAL;
+	}
+}
+
+static const char *
+permission_to_string (NMClientPermission perm)
+{
+	switch (perm) {
+	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK:
+		return NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK;
+	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI:
+		return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI;
+	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN:
+		return NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN;
+	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX:
+		return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
+	case NM_CLIENT_PERMISSION_SLEEP_WAKE:
+		return NM_AUTH_PERMISSION_SLEEP_WAKE;
+	case NM_CLIENT_PERMISSION_NETWORK_CONTROL:
+		return NM_AUTH_PERMISSION_NETWORK_CONTROL;
+	case NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED:
+		return NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED;
+	case NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN:
+		return NM_AUTH_PERMISSION_WIFI_SHARE_OPEN;
+	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM:
+		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
+	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN:
+		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
+	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME:
+		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
+	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS:
+		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
+	case NM_CLIENT_PERMISSION_RELOAD:
+		return NM_AUTH_PERMISSION_RELOAD;
+	case NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK:
+		return NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK;
+	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS:
+		return NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS;
+	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK:
+		return NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK;
+	default:
+		return _("unknown");
+	}
+}
+
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (permission_result_to_string_no_l10n, NMClientPermissionResult,
+	NM_UTILS_LOOKUP_DEFAULT (N_("unknown")),
+	NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_YES,  N_("yes")),
+	NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_NO,   N_("no")),
+	NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_AUTH, N_("auth")),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (NM_CLIENT_PERMISSION_RESULT_UNKNOWN),
+);
+
+_NM_UTILS_LOOKUP_DEFINE (static, permission_result_to_color, NMClientPermissionResult, NMMetaTermColor,
+	NM_UTILS_LOOKUP_DEFAULT (NM_META_TERM_COLOR_NORMAL),
+	NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_YES,  NM_META_TERM_COLOR_GREEN),
+	NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_NO,   NM_META_TERM_COLOR_RED),
+	NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_AUTH, NM_META_TERM_COLOR_YELLOW),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (NM_CLIENT_PERMISSION_RESULT_UNKNOWN),
+);
+
+/*****************************************************************************/
+
+static const NmcMetaGenericInfo *const metagen_general_status[];
+
+static gconstpointer
+_metagen_general_status_get_fcn (const NMMetaEnvironment *environment,
+                                 gpointer environment_user_data,
+                                 const NmcMetaGenericInfo *info,
+                                 gpointer target,
+                                 NMMetaAccessorGetType get_type,
+                                 NMMetaAccessorGetFlags get_flags,
+                                 NMMetaAccessorGetOutFlags *out_flags,
+                                 gpointer *out_to_free)
+{
+	NmCli *nmc = target;
+	const char *value;
+	gboolean v_bool;
+	NMState state;
+	NMConnectivityState connectivity;
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_RUNNING:
+		NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL);
+		value = N_("running");
+		goto translate_and_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_VERSION:
+		NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL);
+		value = nm_client_get_version (nmc->client);
+		goto clone_and_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STATE:
+		state = nm_client_get_state (nmc->client);
+		NMC_HANDLE_TERMFORMAT (state_to_color (state));
+		value = nm_state_to_string_no_l10n (state);
+		goto translate_and_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STARTUP:
+		v_bool = nm_client_get_startup (nmc->client);
+		NMC_HANDLE_TERMFORMAT (v_bool ? NM_META_TERM_COLOR_YELLOW : NM_META_TERM_COLOR_GREEN);
+		value = v_bool ? N_("starting") : N_("started");
+		goto translate_and_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_CONNECTIVITY:
+		connectivity = nm_client_get_connectivity (nmc->client);
+		NMC_HANDLE_TERMFORMAT (connectivity_to_color (connectivity));
+		value = nm_connectivity_to_string_no_l10n (connectivity);
+		goto translate_and_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NETWORKING:
+		v_bool = nm_client_networking_get_enabled (nmc->client);
+		goto enabled_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI_HW:
+		v_bool = nm_client_wireless_hardware_get_enabled (nmc->client);
+		goto enabled_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI:
+		v_bool = nm_client_wireless_get_enabled (nmc->client);
+		goto enabled_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN_HW:
+		v_bool = nm_client_wwan_hardware_get_enabled (nmc->client);
+		goto enabled_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN:
+		v_bool = nm_client_wwan_get_enabled (nmc->client);
+		goto enabled_out;
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX_HW:
+	case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX:
+		/* deprected fields. Don't return anything. */
+		return NULL;
+	default:
+		break;
+	}
+
+	g_return_val_if_reached (NULL);
+
+enabled_out:
+	NMC_HANDLE_TERMFORMAT (v_bool ? NM_META_TERM_COLOR_GREEN : NM_META_TERM_COLOR_RED);
+	value = v_bool ? N_("enabled") : N_("disabled");
+	goto translate_and_out;
+
+clone_and_out:
+	return (*out_to_free = g_strdup (value));
+
+translate_and_out:
+	if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
+		return _(value);
+	return value;
+}
+
+static const NmcMetaGenericInfo *const metagen_general_status[_NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NUM + 1] = {
+#define _METAGEN_GENERAL_STATUS(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_general_status_get_fcn)
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_RUNNING,       "RUNNING"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_VERSION,       "VERSION"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STATE,         "STATE"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STARTUP,       "STARTUP"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_CONNECTIVITY,  "CONNECTIVITY"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NETWORKING,    "NETWORKING"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI_HW,       "WIFI-HW"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI,          "WIFI"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN_HW,       "WWAN-HW"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN,          "WWAN"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX_HW,      "WIMAX-HW"),
+	_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX,         "WIMAX"),
 };
 #define NMC_FIELDS_NM_STATUS_ALL     "RUNNING,VERSION,STATE,STARTUP,CONNECTIVITY,NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN"
 #define NMC_FIELDS_NM_STATUS_SWITCH  "NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN"
@@ -58,29 +272,96 @@ static NmcOutputField nmc_fields_nm_status[] = {
 #define NMC_FIELDS_NM_WIMAX          "WIMAX"
 #define NMC_FIELDS_NM_CONNECTIVITY   "CONNECTIVITY"
 
+/*****************************************************************************/
+
+static gconstpointer
+_metagen_general_permissions_get_fcn (const NMMetaEnvironment *environment,
+                                      gpointer environment_user_data,
+                                      const NmcMetaGenericInfo *info,
+                                      gpointer target,
+                                      NMMetaAccessorGetType get_type,
+                                      NMMetaAccessorGetFlags get_flags,
+                                      NMMetaAccessorGetOutFlags *out_flags,
+                                      gpointer *out_to_free)
+{
+	NMClientPermission perm = GPOINTER_TO_UINT (target);
+	NmCli *nmc = environment_user_data;
+	NMClientPermissionResult perm_result;
+	const char *s;
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_PERMISSION:
+		NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL);
+		return permission_to_string (perm);
+	case NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_VALUE:
+		perm_result = nm_client_get_permission_result (nmc->client, perm);
+		NMC_HANDLE_TERMFORMAT (permission_result_to_color (perm_result));
+		s = permission_result_to_string_no_l10n (perm_result);
+		if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
+			return _(s);
+		return s;
+	default:
+		break;
+	}
+
+	g_return_val_if_reached (NULL);
+}
 
-/* Available fields for 'general permissions' */
-static NmcOutputField nmc_fields_nm_permissions[] = {
-	{"PERMISSION", N_("PERMISSION")},  /* 0 */
-	{"VALUE",      N_("VALUE")},       /* 1 */
-	{NULL, NULL}
+static const NmcMetaGenericInfo *const metagen_general_permissions[_NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_NUM + 1] = {
+#define _METAGEN_GENERAL_PERMISSIONS(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_general_permissions_get_fcn)
+	_METAGEN_GENERAL_PERMISSIONS (NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_PERMISSION,  "PERMISSION"),
+	_METAGEN_GENERAL_PERMISSIONS (NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_VALUE,       "VALUE"),
 };
-#define NMC_FIELDS_NM_PERMISSIONS_ALL     "PERMISSION,VALUE"
-#define NMC_FIELDS_NM_PERMISSIONS_COMMON  "PERMISSION,VALUE"
-
-/* Available fields for 'general logging' */
-static NmcOutputField nmc_fields_nm_logging[] = {
-	{"LEVEL",   N_("LEVEL")},    /* 0 */
-	{"DOMAINS", N_("DOMAINS")},  /* 1 */
-	{NULL, NULL}
-};
-#define NMC_FIELDS_NM_LOGGING_ALL     "LEVEL,DOMAINS"
-#define NMC_FIELDS_NM_LOGGING_COMMON  "LEVEL,DOMAINS"
 
+/*****************************************************************************/
+
+typedef struct {
+	bool initialized;
+	char **level;
+	char **domains;
+} GetGeneralLoggingData;
+
+static gconstpointer
+_metagen_general_logging_get_fcn (const NMMetaEnvironment *environment,
+                                  gpointer environment_user_data,
+                                  const NmcMetaGenericInfo *info,
+                                  gpointer target,
+                                  NMMetaAccessorGetType get_type,
+                                  NMMetaAccessorGetFlags get_flags,
+                                  NMMetaAccessorGetOutFlags *out_flags,
+                                  gpointer *out_to_free)
+{
+	NmCli *nmc = environment_user_data;
+	GetGeneralLoggingData *d = target;
 
-/* glib main loop variable - defined in nmcli.c */
-extern GMainLoop *loop;
+	nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_NUM);
 
+	NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL);
+
+	if (!d->initialized) {
+		d->initialized = TRUE;
+		if (!nm_client_get_logging (nmc->client,
+		                            d->level,
+		                            d->domains,
+		                            NULL))
+			return NULL;
+	}
+
+	if (info->info_type == NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_LEVEL)
+		return *d->level;
+	else
+		return *d->domains;
+}
+
+static const NmcMetaGenericInfo *const metagen_general_logging[_NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_NUM + 1] = {
+#define _METAGEN_GENERAL_LOGGING(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_general_logging_get_fcn)
+	_METAGEN_GENERAL_LOGGING (NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_LEVEL,   "LEVEL"),
+	_METAGEN_GENERAL_LOGGING (NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_DOMAINS, "DOMAINS"),
+};
+
+/*****************************************************************************/
 
 static void
 usage_general (void)
@@ -221,106 +502,19 @@ usage_monitor (void)
 	              "Prints a line whenever a change occurs in NetworkManager\n\n"));
 }
 
-/* quit main loop */
 static void
 quit (void)
 {
-	g_main_loop_quit (loop);  /* quit main loop */
-}
-
-static const char *
-nm_state_to_string (NMState state)
-{
-	switch (state) {
-	case NM_STATE_ASLEEP:
-		return _("asleep");
-	case NM_STATE_CONNECTING:
-		return _("connecting");
-	case NM_STATE_CONNECTED_LOCAL:
-		return _("connected (local only)");
-	case NM_STATE_CONNECTED_SITE:
-		return _("connected (site only)");
-	case NM_STATE_CONNECTED_GLOBAL:
-		return _("connected");
-	case NM_STATE_DISCONNECTING:
-		return _("disconnecting");
-	case NM_STATE_DISCONNECTED:
-		return _("disconnected");
-	case NM_STATE_UNKNOWN:
-	default:
-		return _("unknown");
-	}
-}
-
-static NmcTermColor
-state_to_color (NMState state)
-{
-	switch (state) {
-	case NM_STATE_CONNECTING:
-		return NMC_TERM_COLOR_YELLOW;
-	case NM_STATE_CONNECTED_LOCAL:
-	case NM_STATE_CONNECTED_SITE:
-	case NM_STATE_CONNECTED_GLOBAL:
-		return NMC_TERM_COLOR_GREEN;
-	case NM_STATE_DISCONNECTING:
-		return NMC_TERM_COLOR_YELLOW;
-	case NM_STATE_ASLEEP:
-	case NM_STATE_DISCONNECTED:
-		return NMC_TERM_COLOR_RED;
-	default:
-		return NMC_TERM_COLOR_NORMAL;
-	}
-}
-
-static const char *
-nm_connectivity_to_string (NMConnectivityState connectivity)
-{
-	switch (connectivity) {
-	case NM_CONNECTIVITY_NONE:
-		return _("none");
-	case NM_CONNECTIVITY_PORTAL:
-		return _("portal");
-	case NM_CONNECTIVITY_LIMITED:
-		return _("limited");
-	case NM_CONNECTIVITY_FULL:
-		return _("full");
-	case NM_CONNECTIVITY_UNKNOWN:
-	default:
-		return _("unknown");
-	}
-}
-
-static NmcTermColor
-connectivity_to_color (NMConnectivityState connectivity)
-{
-	switch (connectivity) {
-	case NM_CONNECTIVITY_NONE:
-		return NMC_TERM_COLOR_RED;
-	case NM_CONNECTIVITY_PORTAL:
-	case NM_CONNECTIVITY_LIMITED:
-		return NMC_TERM_COLOR_YELLOW;
-	case NM_CONNECTIVITY_FULL:
-		return NMC_TERM_COLOR_GREEN;
-	default:
-		return NMC_TERM_COLOR_NORMAL;
-	}
+	g_main_loop_quit (loop);
 }
 
 static gboolean
 show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_flds)
 {
-	gboolean startup = FALSE;
-	NMState state = NM_STATE_UNKNOWN;
-	NMConnectivityState connectivity = NM_CONNECTIVITY_UNKNOWN;
-	gboolean net_enabled;
-	gboolean wireless_hw_enabled, wireless_enabled;
-	gboolean wwan_hw_enabled, wwan_enabled;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
 	const char *fields_str;
 	const char *fields_all =    print_flds ? print_flds : NMC_FIELDS_NM_STATUS_ALL;
 	const char *fields_common = print_flds ? print_flds : NMC_FIELDS_NM_STATUS_COMMON;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
 
 	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
 		fields_str = fields_common;
@@ -329,56 +523,16 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl
 	else
 		fields_str = nmc->required_fields;
 
-	tmpl = nmc_fields_nm_status;
-	tmpl_len = sizeof (nmc_fields_nm_status);
-	nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
-
-	if (error) {
+	if (!nmc_print (&nmc->nmc_config,
+	                (gpointer[]) { nmc, NULL },
+	                pretty_header_name ?: N_("NetworkManager status"),
+	                (const NMMetaAbstractInfo *const*) metagen_general_status,
+	                fields_str,
+	                &error)) {
 		g_string_printf (nmc->return_text, _("Error: only these fields are allowed: %s"), fields_all);
-		g_error_free (error);
 		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 		return FALSE;
 	}
-
-	state = nm_client_get_state (nmc->client);
-	startup = nm_client_get_startup (nmc->client);
-	connectivity = nm_client_get_connectivity (nmc->client);
-	net_enabled = nm_client_networking_get_enabled (nmc->client);
-	wireless_hw_enabled = nm_client_wireless_hardware_get_enabled (nmc->client);
-	wireless_enabled = nm_client_wireless_get_enabled (nmc->client);
-	wwan_hw_enabled = nm_client_wwan_hardware_get_enabled (nmc->client);
-	wwan_enabled = nm_client_wwan_get_enabled (nmc->client);
-
-	nmc->print_fields.header_name = pretty_header_name ? (char *) pretty_header_name : _("NetworkManager status");
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, 0);
-	set_val_strc (arr, 0, _("running"));
-	set_val_strc (arr, 1, nm_client_get_version (nmc->client));
-	set_val_strc (arr, 2, nm_state_to_string (state));
-	set_val_strc (arr, 3, startup ? _("starting") : _("started"));
-	set_val_strc (arr, 4, nm_connectivity_to_string (connectivity));
-	set_val_strc (arr, 5, net_enabled ? _("enabled") : _("disabled"));
-	set_val_strc (arr, 6, wireless_hw_enabled ? _("enabled") : _("disabled"));
-	set_val_strc (arr, 7, wireless_enabled ? _("enabled") : _("disabled"));
-	set_val_strc (arr, 8, wwan_hw_enabled ? _("enabled") : _("disabled"));
-	set_val_strc (arr, 9, wwan_enabled ? _("enabled") : _("disabled"));
-
-	/* Set colors */
-	arr[2].color = state_to_color (state);
-	arr[3].color = startup ? NMC_TERM_COLOR_YELLOW : NMC_TERM_COLOR_GREEN;
-	arr[4].color = connectivity_to_color (connectivity);
-	arr[5].color = net_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
-	arr[6].color = wireless_hw_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
-	arr[7].color = wireless_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
-	arr[8].color = wwan_hw_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
-	arr[9].color = wwan_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
-
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
 	return TRUE;
 }
 
@@ -393,60 +547,6 @@ do_general_status (NmCli *nmc, int argc, char **argv)
 	return nmc->return_value;
 }
 
-static const char *
-permission_to_string (NMClientPermission perm)
-{
-	switch (perm) {
-	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK:
-		return NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK;
-	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI:
-		return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI;
-	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN:
-		return NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN;
-	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX:
-		return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
-	case NM_CLIENT_PERMISSION_SLEEP_WAKE:
-		return NM_AUTH_PERMISSION_SLEEP_WAKE;
-	case NM_CLIENT_PERMISSION_NETWORK_CONTROL:
-		return NM_AUTH_PERMISSION_NETWORK_CONTROL;
-	case NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED:
-		return NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED;
-	case NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN:
-		return NM_AUTH_PERMISSION_WIFI_SHARE_OPEN;
-	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM:
-		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
-	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN:
-		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
-	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME:
-		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
-	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS:
-		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
-	case NM_CLIENT_PERMISSION_RELOAD:
-		return NM_AUTH_PERMISSION_RELOAD;
-	case NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK:
-		return NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK;
-	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS:
-		return NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS;
-	default:
-		return _("unknown");
-	}
-}
-
-static const char *
-permission_result_to_string (NMClientPermissionResult perm_result)
-{
-	switch (perm_result) {
-	case NM_CLIENT_PERMISSION_RESULT_YES:
-		return _("yes");
-	case NM_CLIENT_PERMISSION_RESULT_NO:
-		return _("no");
-	case NM_CLIENT_PERMISSION_RESULT_AUTH:
-		return _("auth");
-	default:
-		return _("unknown");
-	}
-}
-
 static gboolean
 timeout_cb (gpointer user_data)
 {
@@ -462,47 +562,31 @@ static int
 print_permissions (void *user_data)
 {
 	NmCli *nmc = user_data;
+	gs_free_error GError *error = NULL;
+	const char *fields_str = NULL;
 	NMClientPermission perm;
-	GError *error = NULL;
-	const char *fields_str;
-	const char *fields_all =    NMC_FIELDS_NM_PERMISSIONS_ALL;
-	const char *fields_common = NMC_FIELDS_NM_PERMISSIONS_COMMON;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
+	guint i;
+	gpointer permissions[NM_CLIENT_PERMISSION_LAST + 1];
 
-	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
-		fields_str = fields_common;
-	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
-		fields_str = fields_all;
-	else
+	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) {
+	} else if (strcasecmp (nmc->required_fields, "all") == 0) {
+	} else
 		fields_str = nmc->required_fields;
 
-	tmpl = nmc_fields_nm_permissions;
-	tmpl_len = sizeof (nmc_fields_nm_permissions);
-	nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
+	for (i = 0, perm = NM_CLIENT_PERMISSION_NONE + 1; perm <= NM_CLIENT_PERMISSION_LAST; perm++)
+		permissions[i++] = GINT_TO_POINTER (perm);
+	permissions[i++] = NULL;
 
-	if (error) {
+	if (!nmc_print (&nmc->nmc_config,
+	                permissions,
+	                _("NetworkManager permissions"),
+	                (const NMMetaAbstractInfo *const*) metagen_general_permissions,
+	                fields_str,
+	                &error)) {
 		g_string_printf (nmc->return_text, _("Error: 'general permissions': %s"), error->message);
-		g_error_free (error);
 		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-		return FALSE;
 	}
 
-	nmc->print_fields.header_name = _("NetworkManager permissions");
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-
-	for (perm = NM_CLIENT_PERMISSION_NONE + 1; perm <= NM_CLIENT_PERMISSION_LAST; perm++) {
-		NMClientPermissionResult perm_result = nm_client_get_permission_result (nmc->client, perm);
-
-		arr = nmc_dup_fields_array (tmpl, tmpl_len, 0);
-		set_val_strc (arr, 0, permission_to_string (perm));
-		set_val_strc (arr, 1, permission_result_to_string (perm_result));
-		g_ptr_array_add (nmc->output_data, arr);
-	}
-	print_data (nmc);  /* Print all data */
-
 	quit ();
 	return G_SOURCE_REMOVE;
 }
@@ -568,56 +652,32 @@ do_general_permissions (NmCli *nmc, int argc, char **argv)
 	return nmc->return_value;
 }
 
-static gboolean
+static void
 show_general_logging (NmCli *nmc)
 {
-	char *level = NULL;
-	char *domains = NULL;
-	GError *error = NULL;
-	const char *fields_str;
-	const char *fields_all =    NMC_FIELDS_NM_LOGGING_ALL;
-	const char *fields_common = NMC_FIELDS_NM_LOGGING_COMMON;
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
-		fields_str = fields_common;
-	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
-		fields_str = fields_all;
-	else
+	gs_free char *level_cache = NULL;
+	gs_free char *domains_cache = NULL;
+	gs_free_error GError *error = NULL;
+	const char *fields_str = NULL;
+	GetGeneralLoggingData d = {
+		.level = &level_cache,
+		.domains = &domains_cache,
+	};
+
+	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) {
+	} else if (strcasecmp (nmc->required_fields, "all") == 0) {
+	} else
 		fields_str = nmc->required_fields;
 
-	tmpl = nmc_fields_nm_logging;
-	tmpl_len = sizeof (nmc_fields_nm_logging);
-	nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
-
-	if (error) {
+	if (!nmc_print (&nmc->nmc_config,
+	                (gpointer const []) { &d, NULL },
+	                _("NetworkManager logging"),
+	                (const NMMetaAbstractInfo *const*) metagen_general_logging,
+	                fields_str,
+	                &error)) {
 		g_string_printf (nmc->return_text, _("Error: 'general logging': %s"), error->message);
-		g_error_free (error);
-		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-		return FALSE;
-	}
-
-	nm_client_get_logging (nmc->client, &level, &domains, &error);
-	if (error) {
-		g_string_printf (nmc->return_text, _("Error: %s."), error->message);
 		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-		g_error_free (error);
-		return FALSE;
 	}
-
-	nmc->print_fields.header_name = _("NetworkManager logging");
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, 0);
-	set_val_str (arr, 0, level);
-	set_val_str (arr, 1, domains);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
 }
 
 static void
@@ -788,8 +848,8 @@ nmc_switch_show (NmCli *nmc, const char *switch_name, const char *header)
 		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 		return FALSE;
 	}
-	if (nmc->print_output == NMC_PRINT_NORMAL)
-		nmc->print_output = NMC_PRINT_TERSE;
+	if (nmc->nmc_config.print_output == NMC_PRINT_NORMAL)
+		nmc->nmc_config_mutable.print_output = NMC_PRINT_TERSE;
 
 	if (!nmc->required_fields)
 		nmc->required_fields = g_strdup (switch_name);
@@ -856,7 +916,7 @@ do_networking_connectivity (NmCli *nmc, int argc, char **argv)
 
 	if (!argc) {
 		/* no arguments -> get current state */
-		nmc_switch_show (nmc, NMC_FIELDS_NM_CONNECTIVITY, _("Connectivity"));
+		nmc_switch_show (nmc, NMC_FIELDS_NM_CONNECTIVITY, N_("Connectivity"));
 	} else if (matches (*argv, "check")) {
 		gs_free_error GError *error = NULL;
 
@@ -868,7 +928,7 @@ do_networking_connectivity (NmCli *nmc, int argc, char **argv)
 			g_string_printf (nmc->return_text, _("Error: %s."), error->message);
 			nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
 		} else
-			nmc_switch_show (nmc, NMC_FIELDS_NM_CONNECTIVITY, _("Connectivity"));
+			nmc_switch_show (nmc, NMC_FIELDS_NM_CONNECTIVITY, N_("Connectivity"));
 	} else {
 		usage_networking ();
 		g_string_printf (nmc->return_text, _("Error: 'networking' command '%s' is not valid."), *argv);
@@ -885,7 +945,7 @@ do_networking_show (NmCli *nmc, int argc, char **argv)
 	if (nmc->complete)
 		return nmc->return_value;
 
-	nmc_switch_show (nmc, NMC_FIELDS_NM_NETWORKING, _("Networking"));
+	nmc_switch_show (nmc, NMC_FIELDS_NM_NETWORKING, N_("Networking"));
 
 	return nmc->return_value;
 }
@@ -920,7 +980,7 @@ do_radio_all (NmCli *nmc, int argc, char **argv)
 			return nmc->return_value;
 
 		/* no argument, show all radio switches */
-		show_nm_status (nmc, _("Radio switches"), NMC_FIELDS_NM_STATUS_RADIO);
+		show_nm_status (nmc, N_("Radio switches"), NMC_FIELDS_NM_STATUS_RADIO);
 	} else {
 		if (nmc->complete) {
 			if (argc == 1)
@@ -950,7 +1010,7 @@ do_radio_wifi (NmCli *nmc, int argc, char **argv)
 			return nmc->return_value;
 
 		/* no argument, show current WiFi state */
-		nmc_switch_show (nmc, NMC_FIELDS_NM_WIFI, _("Wi-Fi radio switch"));
+		nmc_switch_show (nmc, NMC_FIELDS_NM_WIFI, N_("Wi-Fi radio switch"));
 	} else {
 		if (nmc->complete) {
 			if (argc == 1)
@@ -977,7 +1037,7 @@ do_radio_wwan (NmCli *nmc, int argc, char **argv)
 			return nmc->return_value;
 
 		/* no argument, show current WWAN (mobile broadband) state */
-		nmc_switch_show (nmc, NMC_FIELDS_NM_WWAN, _("WWAN radio switch"));
+		nmc_switch_show (nmc, NMC_FIELDS_NM_WWAN, N_("WWAN radio switch"));
 	} else {
 		if (nmc->complete) {
 			if (argc == 1)
@@ -1023,9 +1083,9 @@ networkmanager_running (NMClient *client, GParamSpec *param, NmCli *nmc)
 	char *str;
 
 	running = nm_client_get_nm_running (client);
-	str = nmc_colorize (nmc,
-	                    running ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED,
-	                    NMC_TERM_FORMAT_NORMAL,
+	str = nmc_colorize (nmc->nmc_config.use_colors,
+	                    running ? NM_META_TERM_COLOR_GREEN : NM_META_TERM_COLOR_RED,
+	                    NM_META_TERM_FORMAT_NORMAL,
 	                    running ? _("NetworkManager has started") : _("NetworkManager has stopped"));
 	g_print ("%s\n", str);
 	g_free (str);
@@ -1065,7 +1125,7 @@ client_connectivity (NMClient *client, GParamSpec *param, NmCli *nmc)
 	char *str;
 
 	g_object_get (client, NM_CLIENT_CONNECTIVITY, &connectivity, NULL);
-	str = nmc_colorize (nmc, connectivity_to_color (connectivity), NMC_TERM_FORMAT_NORMAL,
+	str = nmc_colorize (nmc->nmc_config.use_colors, connectivity_to_color (connectivity), NM_META_TERM_FORMAT_NORMAL,
 	                    _("Connectivity is now '%s'\n"), nm_connectivity_to_string (connectivity));
 	g_print ("%s", str);
 	g_free (str);
@@ -1078,7 +1138,7 @@ client_state (NMClient *client, GParamSpec *param, NmCli *nmc)
 	char *str;
 
 	g_object_get (client, NM_CLIENT_STATE, &state, NULL);
-	str = nmc_colorize (nmc, state_to_color (state), NMC_TERM_FORMAT_NORMAL,
+	str = nmc_colorize (nmc->nmc_config.use_colors, state_to_color (state), NM_META_TERM_FORMAT_NORMAL,
 	                    _("Networkmanager is now in the '%s' state\n"),
 	                    nm_state_to_string (state));
 	g_print ("%s", str);
@@ -1122,12 +1182,12 @@ device_overview (NmCli *nmc, NMDevice *device)
 	if (!nm_device_get_autoconnect (device))
 		g_string_append_printf (outbuf, "%s, ", _("autoconnect"));
 	if (nm_device_get_firmware_missing (device)) {
-		tmp = nmc_colorize (nmc, NMC_TERM_COLOR_RED, NMC_TERM_FORMAT_NORMAL, _("fw missing"));
+		tmp = nmc_colorize (nmc->nmc_config.use_colors, NM_META_TERM_COLOR_RED, NM_META_TERM_FORMAT_NORMAL, _("fw missing"));
 		g_string_append_printf (outbuf, "%s, ", tmp);
 		g_free (tmp);
 	}
 	if (nm_device_get_nm_plugin_missing (device)) {
-		tmp = nmc_colorize (nmc, NMC_TERM_COLOR_RED, NMC_TERM_FORMAT_NORMAL, _("plugin missing"));
+		tmp = nmc_colorize (nmc->nmc_config.use_colors, NM_META_TERM_COLOR_RED, NM_META_TERM_FORMAT_NORMAL, _("plugin missing"));
 		g_string_append_printf (outbuf, "%s, ", tmp);
 		g_free (tmp);
 	}
@@ -1228,7 +1288,7 @@ do_overview (NmCli *nmc, int argc, char **argv)
 	NMDevice **devices;
 	const GPtrArray *p;
 	NMActiveConnection *ac;
-	NmcTermColor color;
+	NMMetaTermColor color;
 	NMDnsEntry *dns;
 	char *tmp;
 	int i;
@@ -1238,6 +1298,9 @@ do_overview (NmCli *nmc, int argc, char **argv)
 	/* Register polkit agent */
 	nmc_start_polkit_agent_start_try (nmc);
 
+	/* Optionally start paging the output. */
+	nmc_terminal_spawn_pager (&nmc->nmc_config);
+
 	/* The VPN connections don't have devices (yet?). */
 	p = nm_client_get_active_connections (nmc->client);
 	for (i = 0; i < p->len; i++) {
@@ -1250,7 +1313,7 @@ do_overview (NmCli *nmc, int argc, char **argv)
 
 		state = nm_active_connection_get_state (ac);
 		nmc_active_connection_state_to_color (state, &color);
-		tmp = nmc_colorize (nmc, color, NMC_TERM_FORMAT_NORMAL, _("%s VPN connection"),
+		tmp = nmc_colorize (nmc->nmc_config.use_colors, color, NM_META_TERM_FORMAT_NORMAL, _("%s VPN connection"),
 		                    nm_active_connection_get_id (ac));
 		g_print ("%s\n", tmp);
 		g_free (tmp);
@@ -1261,14 +1324,14 @@ do_overview (NmCli *nmc, int argc, char **argv)
 
 	devices = nmc_get_devices_sorted (nmc->client);
 	for (i = 0; devices[i]; i++) {
-		NmcTermFormat color_fmt;
+		NMMetaTermFormat color_fmt;
 		NMDeviceState state;
 
 		ac = nm_device_get_active_connection (devices[i]);
 
 		state = nm_device_get_state (devices[i]);
 		nmc_device_state_to_color (state, &color, &color_fmt);
-		tmp = nmc_colorize (nmc, color, color_fmt, "%s: %s%s%s",
+		tmp = nmc_colorize (nmc->nmc_config.use_colors, color, color_fmt, "%s: %s%s%s",
 		                    nm_device_get_iface (devices[i]),
 		                    nmc_device_state_to_string (state),
 		                    ac ? " to " : "",
@@ -1352,7 +1415,7 @@ do_monitor (NmCli *nmc, int argc, char **argv)
 	if (!nm_client_get_nm_running (nmc->client)) {
 		char *str;
 
-		str = nmc_colorize (nmc, NMC_TERM_COLOR_RED, NMC_TERM_FORMAT_NORMAL,
+		str = nmc_colorize (nmc->nmc_config.use_colors, NM_META_TERM_COLOR_RED, NM_META_TERM_FORMAT_NORMAL,
 		                    _("Networkmanager is not running (waiting for it)\n"));
 		g_print ("%s", str);
 		g_free (str);
diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c
index b8019403..ee621ca3 100644
--- a/clients/cli/nmcli.c
+++ b/clients/cli/nmcli.c
@@ -16,11 +16,13 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2010 - 2015 Red Hat, Inc.
+ * Copyright 2010 - 2017 Red Hat, Inc.
  */
 
 #include "nm-default.h"
 
+#include "nmcli.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -32,8 +34,11 @@
 #include <readline/readline.h>
 #include <readline/history.h>
 
+#include "nm-client-utils.h"
+
+#include "nm-utils/nm-hash-utils.h"
+
 #include "polkit-agent.h"
-#include "nmcli.h"
 #include "utils.h"
 #include "common.h"
 #include "connections.h"
@@ -49,10 +54,10 @@
 #endif
 
 /* Global NmCli object */
-// FIXME: Currently, we pass NmCli over in most APIs, but we might refactor
-// that and use the global variable directly instead.
 NmCli nm_cli;
 
+/*****************************************************************************/
+
 typedef struct {
 	NmCli *nmc;
 	int argc;
@@ -66,22 +71,33 @@ struct termios termios_orig;
 NM_CACHED_QUARK_FCN ("nmcli-error-quark", nmcli_error_quark)
 
 static void
-complete_field (GHashTable *h, const char *setting, NmcOutputField field[])
+complete_field_setting (GHashTable *h, NMMetaSettingType setting_type)
 {
-	int i;
+	const NMMetaSettingInfoEditor *setting_info = &nm_meta_setting_infos_editor[setting_type];
+	guint i;
 
-	for (i = 0; field[i].name; i++) {
-		if (setting)
-			g_hash_table_add (h, g_strdup_printf ("%s.%s", setting, field[i].name));
-		else
-			g_hash_table_add (h, g_strdup (field[i].name));
+	for (i = 0; i < setting_info->properties_num; i++) {
+		g_hash_table_add (h, g_strdup_printf ("%s.%s",
+		                                      setting_info->general->setting_name,
+		                                      setting_info->properties[i]->property_name));
 	}
 }
 
 static void
+complete_field (GHashTable *h, const NmcMetaGenericInfo *const*field)
+{
+	int i;
+
+	for (i = 0; field[i]; i++)
+		g_hash_table_add (h, g_strdup (field[i]->name));
+}
+
+static void
 complete_one (gpointer key, gpointer value, gpointer user_data)
 {
-	const char *prefix = user_data;
+	const char **option_with_value = user_data;
+	const char *option = option_with_value[0];
+	const char *prefix = option_with_value[1];
 	const char *name = key;
 	const char *last;
 
@@ -92,78 +108,77 @@ complete_one (gpointer key, gpointer value, gpointer user_data)
 		last = prefix;
 
 	if ((!*last && !strchr (name, '.')) || matches (last, name)) {
+		if (option != prefix) {
+			/* value prefix was not a standalone argument,
+			 * it was part of --option=<value> argument.
+			 * Repeat the part leading to "=". */
+			g_print ("%s=", option);
+		}
 		g_print ("%.*s%s%s\n", (int)(last-prefix), prefix, name,
 		                       strcmp (last, name) == 0 ? "," : "");
 	}
 }
 
 static void
-complete_fields (const char *prefix)
+complete_fields (const char *option, const char *prefix)
 {
-
+	guint i;
 	GHashTable *h;
-
-	h = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
-	complete_field (h, NULL, nmc_fields_ip4_config);
-	complete_field (h, NULL, nmc_fields_dhcp4_config);
-	complete_field (h, NULL, nmc_fields_ip6_config);
-	complete_field (h, NULL, nmc_fields_dhcp6_config);
-	complete_field (h, NULL, nmc_fields_con_show);
-	complete_field (h, NULL, nmc_fields_settings_names);
-	complete_field (h, NULL, nmc_fields_con_active_details_general);
-	complete_field (h, NULL, nmc_fields_con_active_details_vpn);
-	complete_field (h, NULL, nmc_fields_con_active_details_groups);
-	complete_field (h, NULL, nmc_fields_dev_status);
-	complete_field (h, NULL, nmc_fields_dev_show_general);
-	complete_field (h, NULL, nmc_fields_dev_show_connections);
-	complete_field (h, NULL, nmc_fields_dev_show_cap);
-	complete_field (h, NULL, nmc_fields_dev_show_wired_prop);
-	complete_field (h, NULL, nmc_fields_dev_show_wifi_prop);
-	complete_field (h, NULL, nmc_fields_dev_show_wimax_prop);
-	complete_field (h, NULL, nmc_fields_dev_wifi_list);
-	complete_field (h, NULL, nmc_fields_dev_wimax_list);
-	complete_field (h, NULL, nmc_fields_dev_show_master_prop);
-	complete_field (h, NULL, nmc_fields_dev_show_team_prop);
-	complete_field (h, NULL, nmc_fields_dev_show_vlan_prop);
-	complete_field (h, NULL, nmc_fields_dev_show_bluetooth);
-	complete_field (h, NULL, nmc_fields_dev_show_sections);
-	complete_field (h, NULL, nmc_fields_dev_lldp_list);
-
-	complete_field (h, "connection", nmc_fields_setting_connection);
-	complete_field (h, "802-3-ethernet", nmc_fields_setting_wired);
-	complete_field (h, "802-1x", nmc_fields_setting_8021X);
-	complete_field (h, "802-11-wireless", nmc_fields_setting_wireless);
-	complete_field (h, "802-11-wireless-security", nmc_fields_setting_wireless_security);
-	complete_field (h, "ipv4", nmc_fields_setting_ip4_config);
-	complete_field (h, "ipv6", nmc_fields_setting_ip6_config);
-	complete_field (h, "serial", nmc_fields_setting_serial);
-	complete_field (h, "ppp", nmc_fields_setting_ppp);
-	complete_field (h, "pppoe", nmc_fields_setting_pppoe);
-	complete_field (h, "adsl", nmc_fields_setting_adsl);
-	complete_field (h, "gsm", nmc_fields_setting_gsm);
-	complete_field (h, "cdma", nmc_fields_setting_cdma);
-	complete_field (h, "bluetooth", nmc_fields_setting_bluetooth);
-	complete_field (h, "802-11-olpc-mesh", nmc_fields_setting_olpc_mesh);
-	complete_field (h, "vpn", nmc_fields_setting_vpn);
-	complete_field (h, "wimax", nmc_fields_setting_wimax);
-	complete_field (h, "infiniband", nmc_fields_setting_infiniband);
-	complete_field (h, "bond", nmc_fields_setting_bond);
-	complete_field (h, "vlan", nmc_fields_setting_vlan);
-	complete_field (h, "bridge", nmc_fields_setting_bridge);
-	complete_field (h, "bridge-port", nmc_fields_setting_bridge_port);
-	complete_field (h, "team", nmc_fields_setting_team);
-	complete_field (h, "team-port", nmc_fields_setting_team_port);
-	complete_field (h, "dcb", nmc_fields_setting_dcb);
-	complete_field (h, "tun", nmc_fields_setting_tun);
-	complete_field (h, "ip-tunnel", nmc_fields_setting_ip_tunnel);
-	complete_field (h, "macvlan", nmc_fields_setting_macvlan);
-	complete_field (h, "vxlan", nmc_fields_setting_vxlan);
-
-	g_hash_table_foreach (h, complete_one, (gpointer) prefix);
+	const char *option_with_value[2] = { option, prefix };
+
+	h = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL);
+
+	complete_field (h, metagen_ip4_config);
+	complete_field (h, nmc_fields_dhcp4_config);
+	complete_field (h, nmc_fields_ip6_config);
+	complete_field (h, nmc_fields_dhcp6_config);
+	complete_field (h, nmc_fields_con_show);
+	complete_field (h, nmc_fields_con_active_details_general);
+	complete_field (h, nmc_fields_con_active_details_vpn);
+	complete_field (h, nmc_fields_con_active_details_groups);
+	complete_field (h, nmc_fields_dev_status);
+	complete_field (h, nmc_fields_dev_show_general);
+	complete_field (h, nmc_fields_dev_show_connections);
+	complete_field (h, nmc_fields_dev_show_cap);
+	complete_field (h, nmc_fields_dev_show_wired_prop);
+	complete_field (h, nmc_fields_dev_show_wifi_prop);
+	complete_field (h, nmc_fields_dev_show_wimax_prop);
+	complete_field (h, nmc_fields_dev_wifi_list);
+	complete_field (h, nmc_fields_dev_wimax_list);
+	complete_field (h, nmc_fields_dev_show_master_prop);
+	complete_field (h, nmc_fields_dev_show_team_prop);
+	complete_field (h, nmc_fields_dev_show_vlan_prop);
+	complete_field (h, nmc_fields_dev_show_bluetooth);
+	complete_field (h, nmc_fields_dev_show_sections);
+	complete_field (h, nmc_fields_dev_lldp_list);
+
+	for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++)
+		complete_field_setting (h, i);
+
+	g_hash_table_foreach (h, complete_one, (gpointer) &option_with_value[0]);
 	g_hash_table_destroy (h);
 }
 
+static void
+complete_option_with_value (const char *option, const char *prefix, ...)
+{
+	va_list args;
+	const char *candidate;
+
+	va_start (args, prefix);
+	while ((candidate = va_arg (args, const char *))) {
+		if (!*prefix || matches (prefix, candidate)) {
+			if (option != prefix) {
+				/* value prefix was not a standalone argument,
+				 * it was part of --option=<value> argument.
+				 * Repeat the part leading to "=". */
+				g_print ("%s=", option);
+			}
+			g_print ("%s\n", candidate);
+		}
+	}
+	va_end (args);
+}
 
 static void
 usage (void)
@@ -207,6 +222,57 @@ static const NMCCommand nmcli_cmds[] = {
 };
 
 static gboolean
+matches_arg (NmCli *nmc, int *argc, char ***argv, const char *pattern, char **arg)
+{
+	char *opt = *argv[0];
+
+	if (nmc->return_value != NMC_RESULT_SUCCESS) {
+		/* Don't process further matches if there has been an error. */
+		return FALSE;
+	}
+
+	if (opt[1] == '-') {
+		/* We know one '-' was already seen by the caller.
+		 * Skip it if there's a second one*/
+		opt++;
+	}
+
+	if (arg) {
+		/* If there's a "=" separator, replace it with NUL so that matches()
+		 * works and consider the part after it to be the arguemnt's value. */
+		*arg = strchr (opt, '=');
+		if (*arg) {
+			**arg = '\0';
+			(*arg)++;
+		}
+	}
+
+	if (!matches (opt, pattern)) {
+		if (arg && *arg) {
+			/* Back off the replacement of "=". */
+			(*arg)--;
+			**arg = '=';
+		}
+		return FALSE;
+	}
+
+	if (arg && !*arg) {
+		/* We need a value, but the option didn't contain a "=<value>" part.
+		 * Proceed to the next argument. */
+		(*argc)--;
+		(*argv)++;
+		if (!*argc) {
+			g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt);
+			nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+			return FALSE;
+		}
+		*arg = *argv[0];
+	}
+
+	return TRUE;
+}
+
+static gboolean
 process_command_line (NmCli *nmc, int argc, char **argv)
 {
 	char *base;
@@ -225,171 +291,129 @@ process_command_line (NmCli *nmc, int argc, char **argv)
 
 	/* parse options */
 	while (argc) {
-		char *opt = argv[0];
-		if (opt[0] != '-')
+		char *value;
+
+		if (argv[0][0] != '-')
 			break;
 
 		if (argc == 1 && nmc->complete) {
-			nmc_complete_strings (opt, "--terse", "--pretty", "--mode", "--colors", "--escape",
+			nmc_complete_strings (argv[0], "--terse", "--pretty", "--mode", "--colors", "--escape",
 			                           "--fields", "--nocheck", "--get-values",
 			                            "--wait", "--version", "--help", NULL);
 		}
 
-		if (opt[1] == '-') {
-			opt++;
+		if (argv[0][1] == '-' && argv[0][2] == '\0') {
 			/* '--' ends options */
-			if (opt[1] == '\0') {
-				next_arg (nmc, &argc, &argv, NULL);
-				break;
-			}
+			next_arg (nmc, &argc, &argv, NULL);
+			break;
 		}
 
-		if (matches (opt, "-terse")) {
-			if (nmc->print_output == NMC_PRINT_TERSE) {
+		if (matches_arg (nmc, &argc, &argv, "-terse", NULL)) {
+			if (nmc->nmc_config.print_output == NMC_PRINT_TERSE) {
 				g_string_printf (nmc->return_text, _("Error: Option '--terse' is specified the second time."));
 				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 				return FALSE;
 			}
-			else if (nmc->print_output == NMC_PRINT_PRETTY) {
+			else if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) {
 				g_string_printf (nmc->return_text, _("Error: Option '--terse' is mutually exclusive with '--pretty'."));
 				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 				return FALSE;
 			}
 			else
-				nmc->print_output = NMC_PRINT_TERSE;
-		} else if (matches (opt, "-pretty")) {
-			if (nmc->print_output == NMC_PRINT_PRETTY) {
+				nmc->nmc_config_mutable.print_output = NMC_PRINT_TERSE;
+		} else if (matches_arg (nmc, &argc, &argv, "-pretty", NULL)) {
+			if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) {
 				g_string_printf (nmc->return_text, _("Error: Option '--pretty' is specified the second time."));
 				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 				return FALSE;
 			}
-			else if (nmc->print_output == NMC_PRINT_TERSE) {
+			else if (nmc->nmc_config.print_output == NMC_PRINT_TERSE) {
 				g_string_printf (nmc->return_text, _("Error: Option '--pretty' is mutually exclusive with '--terse'."));
 				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 				return FALSE;
 			}
 			else
-				nmc->print_output = NMC_PRINT_PRETTY;
-		} else if (matches (opt, "-mode")) {
+				nmc->nmc_config_mutable.print_output = NMC_PRINT_PRETTY;
+		} else if (matches_arg (nmc, &argc, &argv, "-mode", &value)) {
 			nmc->mode_specified = TRUE;
-			argc--;
-			argv++;
-			if (!argc) {
-				g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt);
-				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-				return FALSE;
-			}
 			if (argc == 1 && nmc->complete)
-				nmc_complete_strings (argv[0], "tabular", "multiline", NULL);
-			if (matches (argv[0], "tabular"))
-				nmc->multiline_output = FALSE;
-			else if (matches (argv[0], "multiline"))
-				nmc->multiline_output = TRUE;
+				complete_option_with_value (argv[0], value, "tabular", "multiline", NULL);
+			if (matches (value, "tabular"))
+				nmc->nmc_config_mutable.multiline_output = FALSE;
+			else if (matches (value, "multiline"))
+				nmc->nmc_config_mutable.multiline_output = TRUE;
 			else {
-				g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt);
-				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-				return FALSE;
-			}
-		} else if (matches (opt, "-colors")) {
-			argc--;
-			argv++;
-			if (!argc) {
-				g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt);
+				g_string_printf (nmc->return_text, _("Error: '%s' is not a valid argument for '%s' option."), value, argv[0]);
 				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 				return FALSE;
 			}
+		} else if (matches_arg (nmc, &argc, &argv, "-colors", &value)) {
 			if (argc == 1 && nmc->complete)
-				nmc_complete_strings (argv[0], "yes", "no", "auto", NULL);
-			if (matches (argv[0], "auto"))
-				nmc->use_colors = NMC_USE_COLOR_AUTO;
-			else if (matches (argv[0], "yes"))
-				nmc->use_colors = NMC_USE_COLOR_YES;
-			else if (matches (argv[0], "no"))
-				nmc->use_colors = NMC_USE_COLOR_NO;
+				complete_option_with_value (argv[0], value, "yes", "no", "auto", NULL);
+			if (matches (value, "auto"))
+				nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_AUTO;
+			else if (matches (value, "yes"))
+				nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_YES;
+			else if (matches (value, "no"))
+				nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_NO;
 			else {
-				g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt);
-				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-				return FALSE;
-			}
-		} else if (matches (opt, "-escape")) {
-			argc--;
-			argv++;
-			if (!argc) {
-				g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt);
+				g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), value, argv[0]);
 				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 				return FALSE;
 			}
+		} else if (matches_arg (nmc, &argc, &argv, "-escape", &value)) {
 			if (argc == 1 && nmc->complete)
-				nmc_complete_strings (argv[0], "yes", "no", NULL);
-			if (matches (argv[0], "yes"))
-				nmc->escape_values = TRUE;
-			else if (matches (argv[0], "no"))
-				nmc->escape_values = FALSE;
+				complete_option_with_value (argv[0], value, "yes", "no", NULL);
+			if (matches (value, "yes"))
+				nmc->nmc_config_mutable.escape_values = TRUE;
+			else if (matches (value, "no"))
+				nmc->nmc_config_mutable.escape_values = FALSE;
 			else {
-				g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt);
-				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-				return FALSE;
-			}
-		} else if (matches (opt, "-fields")) {
-			argc--;
-			argv++;
-			if (!argc) {
-				g_string_printf (nmc->return_text, _("Error: fields for '%s' options are missing."), opt);
+				g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), value, argv[0]);
 				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 				return FALSE;
 			}
+		} else if (matches_arg (nmc, &argc, &argv, "-fields", &value)) {
 			if (argc == 1 && nmc->complete)
-				complete_fields (argv[0]);
-			nmc->required_fields = g_strdup (argv[0]);
-		} else if (matches (opt, "-get-values")) {
-			argc--;
-			argv++;
-			if (!argc) {
-				g_string_printf (nmc->return_text, _("Error: fields for '%s' options are missing."), opt);
-				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-				return FALSE;
-			}
+				complete_fields (argv[0], value);
+			nmc->required_fields = g_strdup (value);
+		} else if (matches_arg (nmc, &argc, &argv, "-get-values", &value)) {
 			if (argc == 1 && nmc->complete)
-				complete_fields (argv[0]);
-			nmc->required_fields = g_strdup (argv[0]);
-			nmc->print_output = NMC_PRINT_TERSE;
+				complete_fields (argv[0], value);
+			nmc->required_fields = g_strdup (value);
+			nmc->nmc_config_mutable.print_output = NMC_PRINT_TERSE;
 			/* We want fixed tabular mode here, but just set the mode specified and rely on the initialization
 			 * in nmc_init: in this way we allow use of "-m multiline" to swap the output mode also if placed
 			 * before the "-g <field>" option (-g may be still more practical and easy to remember than -t -f).
 			*/
 			nmc->mode_specified = TRUE;
-		} else if (matches (opt, "-nocheck")) {
+		} else if (matches_arg (nmc, &argc, &argv, "-nocheck", NULL)) {
 			/* ignore for backward compatibility */
-		} else if (matches (opt, "-wait")) {
+		} else if (matches_arg (nmc, &argc, &argv, "-wait", &value)) {
 			unsigned long timeout;
 
-			argc--;
-			argv++;
-			if (!argc) {
-				g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt);
-				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
-				return FALSE;
-			}
-			if (!nmc_string_to_uint (argv[0], TRUE, 0, G_MAXINT, &timeout)) {
-				g_string_printf (nmc->return_text, _("Error: '%s' is not a valid timeout for '%s' option."),
-						 argv[0], opt);
+			if (!nmc_string_to_uint (value, TRUE, 0, G_MAXINT, &timeout)) {
+				g_string_printf (nmc->return_text, _("Error: '%s' is not a valid timeout."), value);
 				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
 				return FALSE;
 			}
 			nmc->timeout = (int) timeout;
-		} else if (matches (opt, "-version")) {
+		} else if (matches_arg (nmc, &argc, &argv, "-version", NULL)) {
 			if (!nmc->complete)
 				g_print (_("nmcli tool, version %s\n"), NMCLI_VERSION);
 			return NMC_RESULT_SUCCESS;
-		} else if (matches (opt, "-help")) {
+		} else if (matches_arg (nmc, &argc, &argv, "-help", NULL)) {
 			if (!nmc->complete)
 				usage ();
 			return NMC_RESULT_SUCCESS;
 		} else {
-			g_string_printf (nmc->return_text, _("Error: Option '%s' is unknown, try 'nmcli -help'."), opt);
-			nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+			if (nmc->return_value == NMC_RESULT_SUCCESS) {
+				g_string_printf (nmc->return_text, _("Error: Option '%s' is unknown, try 'nmcli -help'."), argv[0]);
+				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+			}
 			return FALSE;
 		}
+
 		next_arg (nmc, &argc, &argv, NULL);
 	}
 
@@ -545,28 +569,27 @@ nmc_init (NmCli *nmc)
 
 	nmc->should_wait = 0;
 	nmc->nowait_flag = TRUE;
-	nmc->print_output = NMC_PRINT_NORMAL;
-	nmc->multiline_output = FALSE;
+	nmc->nmc_config_mutable.print_output = NMC_PRINT_NORMAL;
+	nmc->nmc_config_mutable.multiline_output = FALSE;
 	nmc->mode_specified = FALSE;
-	nmc->escape_values = TRUE;
+	nmc->nmc_config_mutable.escape_values = TRUE;
 	nmc->required_fields = NULL;
-	nmc->output_data = g_ptr_array_new_full (20, g_free);
-	memset (&nmc->print_fields, '\0', sizeof (NmcPrintFields));
 	nmc->ask = FALSE;
 	nmc->complete = FALSE;
-	nmc->show_secrets = FALSE;
-	nmc->use_colors = NMC_USE_COLOR_AUTO;
-	nmc->in_editor = FALSE;
+	nmc->nmc_config_mutable.show_secrets = FALSE;
+	nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_AUTO;
+	nmc->nmc_config_mutable.in_editor = FALSE;
 	nmc->editor_status_line = FALSE;
 	nmc->editor_save_confirmation = TRUE;
-	nmc->editor_show_secrets = FALSE;
-	nmc->editor_prompt_color = NMC_TERM_COLOR_NORMAL;
+	nmc->editor_prompt_color = NM_META_TERM_COLOR_NORMAL;
 }
 
 static void
 nmc_cleanup (NmCli *nmc)
 {
-	if (nmc->client) g_object_unref (nmc->client);
+	pid_t ret;
+
+	g_clear_object (&nmc->client);
 
 	g_string_free (nmc->return_text, TRUE);
 
@@ -579,8 +602,15 @@ nmc_cleanup (NmCli *nmc)
 		g_hash_table_destroy (nmc->pwds_hash);
 
 	g_free (nmc->required_fields);
-	nmc_empty_output_fields (nmc);
-	g_ptr_array_unref (nmc->output_data);
+
+	if (nmc->pager_pid > 0) {
+		fclose (stdout);
+		fclose (stderr);
+		do {
+			ret = waitpid (nmc->pager_pid, NULL, 0);
+		} while (ret == -1 && errno == EINTR);
+		nmc->pager_pid = 0;
+	}
 
 	nmc_polkit_agent_fini (nmc);
 }
diff --git a/clients/cli/nmcli.h b/clients/cli/nmcli.h
index 7e33e3a7..874bca21 100644
--- a/clients/cli/nmcli.h
+++ b/clients/cli/nmcli.h
@@ -14,7 +14,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2010 - 2015 Red Hat, Inc.
+ * Copyright 2010 - 2017 Red Hat, Inc.
  */
 
 #ifndef NMC_NMCLI_H
@@ -23,6 +23,8 @@
 #include "NetworkManager.h"
 #include "nm-secret-agent-old.h"
 
+#include "nm-meta-setting-desc.h"
+
 #if WITH_POLKIT_AGENT
 #include "nm-polkit-listener.h"
 #else
@@ -30,6 +32,8 @@
 typedef gpointer NMPolkitListener;
 #endif
 
+typedef char *(*NmcCompEntryFunc) (const char *, int);
+
 /* nmcli exit codes */
 typedef enum {
 	/* Indicates successful execution */
@@ -70,58 +74,35 @@ typedef enum {
 } NMCResultCode;
 
 typedef enum {
-	NMC_TERM_COLOR_NORMAL  = 0,
-	NMC_TERM_COLOR_BLACK   = 1,
-	NMC_TERM_COLOR_RED     = 2,
-	NMC_TERM_COLOR_GREEN   = 3,
-	NMC_TERM_COLOR_YELLOW  = 4,
-	NMC_TERM_COLOR_BLUE    = 5,
-	NMC_TERM_COLOR_MAGENTA = 6,
-	NMC_TERM_COLOR_CYAN    = 7,
-	NMC_TERM_COLOR_WHITE   = 8
-} NmcTermColor;
-
-typedef enum {
-	NMC_TERM_FORMAT_NORMAL,
-	NMC_TERM_FORMAT_BOLD,
-	NMC_TERM_FORMAT_DIM,
-	NMC_TERM_FORMAT_UNDERLINE,
-	NMC_TERM_FORMAT_BLINK,
-	NMC_TERM_FORMAT_REVERSE,
-	NMC_TERM_FORMAT_HIDDEN,
-} NmcTermFormat;
-
-typedef enum {
 	NMC_PRINT_TERSE = 0,
 	NMC_PRINT_NORMAL = 1,
 	NMC_PRINT_PRETTY = 2
 } NMCPrintOutput;
 
 /* === Output fields === */
-/* Flags for NmcOutputField */
-#define NMC_OF_FLAG_FIELD_NAMES        0x00000001   /* Print field names instead of values */
-#define NMC_OF_FLAG_SECTION_PREFIX     0x00000002   /* Use the first value as section prefix for the other field names - just in multiline */
-#define NMC_OF_FLAG_MAIN_HEADER_ADD    0x00000004   /* Print main header in addition to values/field names */
-#define NMC_OF_FLAG_MAIN_HEADER_ONLY   0x00000008   /* Print main header only */
-
-typedef struct _NmcOutputField {
-	const char *name;               /* Field's name */
-	const char *name_l10n;          /* Field's name for translation */
+
+typedef enum {
+	NMC_OF_FLAG_FIELD_NAMES        = 0x00000001,   /* Print field names instead of values */
+	NMC_OF_FLAG_SECTION_PREFIX     = 0x00000002,   /* Use the first value as section prefix for the other field names - just in multiline */
+	NMC_OF_FLAG_MAIN_HEADER_ADD    = 0x00000004,   /* Print main header in addition to values/field names */
+	NMC_OF_FLAG_MAIN_HEADER_ONLY   = 0x00000008,   /* Print main header only */
+} NmcOfFlags;
+
+extern const NMMetaType nmc_meta_type_generic_info;
+
+typedef struct _NmcOutputField NmcOutputField;
+typedef struct _NmcMetaGenericInfo NmcMetaGenericInfo;
+
+struct _NmcOutputField {
+	const NMMetaAbstractInfo *info;
 	int width;                      /* Width in screen columns */
-	struct _NmcOutputField *group;  /* Points to an array with available section field names if this is a section (group) field */
 	void *value;                    /* Value of current field - char* or char** (NULL-terminated array) */
 	gboolean value_is_array;        /* Whether value is char** instead of char* */
 	gboolean free_value;            /* Whether to free the value */
-	guint32 flags;                  /* Flags - whether and how to print values/field names/headers */
-	NmcTermColor color;             /* Use this color to print value */
-	NmcTermFormat color_fmt;        /* Use this terminal format to print value */
-} NmcOutputField;
-
-typedef struct {
-	GArray *indices;      /* Array of field indices to the array of allowed fields */
-	char *header_name;    /* Name of the output */
-	int indent;           /* Indent by this number of spaces */
-} NmcPrintFields;
+	NmcOfFlags flags;               /* Flags - whether and how to print values/field names/headers */
+	NMMetaTermColor color;             /* Use this color to print value */
+	NMMetaTermFormat color_fmt;        /* Use this terminal format to print value */
+};
 
 typedef enum {
 	NMC_USE_COLOR_AUTO,
@@ -129,12 +110,26 @@ typedef enum {
 	NMC_USE_COLOR_NO,
 } NmcColorOption;
 
+typedef struct _NmcConfig {
+	NMCPrintOutput print_output;                      /* Output mode */
+	NmcColorOption use_colors;                        /* Whether to use colors for output: option '--color' */
+	bool multiline_output;                            /* Multiline output instead of default tabular */
+	bool escape_values;                               /* Whether to escape ':' and '\' in terse tabular mode */
+	bool in_editor;                                   /* Whether running the editor - nmcli con edit' */
+	bool show_secrets;                                /* Whether to display secrets (both input and output): option '--show-secrets' */
+} NmcConfig;
+
+typedef struct _NmcOutputData {
+	GPtrArray *output_data;                           /* GPtrArray of arrays of NmcOutputField structs - accumulates data for output */
+} NmcOutputData;
+
 /* NmCli - main structure */
 typedef struct _NmCli {
 	NMClient *client;                                 /* Pointer to NMClient of libnm */
 
 	NMCResultCode return_value;                       /* Return code of nmcli */
 	GString *return_text;                             /* Reason text */
+	pid_t pager_pid;                                  /* PID of a pager, if one was spawned */
 
 	int timeout;                                      /* Operation timeout */
 
@@ -144,22 +139,17 @@ typedef struct _NmCli {
 
 	int should_wait;                                  /* Semaphore indicating whether nmcli should not end or not yet */
 	gboolean nowait_flag;                             /* '--nowait' option; used for passing to callbacks */
-	NMCPrintOutput print_output;                      /* Output mode */
-	gboolean multiline_output;                        /* Multiline output instead of default tabular */
 	gboolean mode_specified;                          /* Whether tabular/multiline mode was specified via '--mode' option */
-	NmcColorOption use_colors;                        /* Whether to use colors for output: option '--color' */
-	gboolean escape_values;                           /* Whether to escape ':' and '\' in terse tabular mode */
+	union {
+		const NmcConfig nmc_config;
+		NmcConfig nmc_config_mutable;
+	};
 	char *required_fields;                            /* Required fields in output: '--fields' option */
-	GPtrArray *output_data;                           /* GPtrArray of arrays of NmcOutputField structs - accumulates data for output */
-	NmcPrintFields print_fields;                      /* Structure with field indices to print */
 	gboolean ask;                                     /* Ask for missing parameters: option '--ask' */
 	gboolean complete;                                /* Autocomplete the command line */
-	gboolean show_secrets;                            /* Whether to display secrets (both input and output): option '--show-secrets' */
-	gboolean in_editor;                               /* Whether running the editor - nmcli con edit' */
 	gboolean editor_status_line;                      /* Whether to display status line in connection editor */
 	gboolean editor_save_confirmation;                /* Whether to ask for confirmation on saving connections with 'autoconnect=yes' */
-	gboolean editor_show_secrets;                     /* Whether to display secrets in the editor' */
-	NmcTermColor editor_prompt_color;                 /* Color of prompt in connection editor */
+	NMMetaTermColor editor_prompt_color;              /* Color of prompt in connection editor */
 } NmCli;
 
 extern NmCli nm_cli;
@@ -168,9 +158,19 @@ extern NmCli nm_cli;
 #define NMCLI_ERROR (nmcli_error_quark ())
 GQuark nmcli_error_quark (void);
 
+extern GMainLoop *loop;
+
 gboolean nmc_seen_sigint (void);
 void     nmc_clear_sigint (void);
 void     nmc_set_sigquit_internal (void);
 void     nmc_exit (void);
 
+void nmc_empty_output_fields (NmcOutputData *output_data);
+
+#define NMC_OUTPUT_DATA_DEFINE_SCOPED(out) \
+	gs_unref_array GArray *out##_indices = NULL; \
+	nm_auto (nmc_empty_output_fields) NmcOutputData out = { \
+		.output_data = g_ptr_array_new_full (20, g_free), \
+	}
+
 #endif /* NMC_NMCLI_H */
diff --git a/clients/cli/polkit-agent.c b/clients/cli/polkit-agent.c
index 086851de..10a84f9c 100644
--- a/clients/cli/polkit-agent.c
+++ b/clients/cli/polkit-agent.c
@@ -21,13 +21,15 @@
 
 #if WITH_POLKIT_AGENT
 
+#include "polkit-agent.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "polkit-agent.h"
 #include "nm-polkit-listener.h"
+
 #include "common.h"
 
 static char *
diff --git a/clients/cli/settings-docs.c b/clients/cli/settings-docs.c
deleted file mode 100644
index 5d7abebf..00000000
--- a/clients/cli/settings-docs.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/* Generated file. Do not edit. */
-
-typedef struct {
-	const char *name;
-	const char *docs;
-} NmcPropertyDesc;
-
-NmcPropertyDesc setting_802_11_olpc_mesh[] = {
-	{ "channel", "Channel on which the mesh network to join is located." },
-	{ "dhcp-anycast-address", "Anycast DHCP MAC address used when requesting an IP address via DHCP. The specific anycast address used determines which DHCP server class answers the request." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "ssid", "SSID of the mesh network to join." },
-};
-  
-NmcPropertyDesc setting_802_11_wireless[] = {
-	{ "band", "802.11 frequency band of the network.  One of \"a\" for 5GHz 802.11a or \"bg\" for 2.4GHz 802.11.  This will lock associations to the Wi-Fi network to the specific band, i.e. if \"a\" is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible.  This setting depends on specific driver capability and may not work with all drivers." },
-	{ "bssid", "If specified, directs the device to only associate with the given access point.  This capability is highly driver dependent and not supported by all devices.  Note: this property does not control the BSSID used when creating an Ad-Hoc network and is unlikely to in the future." },
-	{ "channel", "Wireless channel to use for the Wi-Fi connection.  The device will only join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel.  Because channel numbers overlap between bands, this property also requires the \"band\" property to be set." },
-	{ "cloned-mac-address", "If specified, request that the device use this MAC address instead. This is known as MAC cloning or spoofing. Beside explicitly specifing a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address of the device. \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"preserve\" (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\"." },
-	{ "generate-mac-address-mask", "With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting \"FE:FF:FF:00:00:00\" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the \"random\" or \"stable\" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of \"FE:FF:FF:00:00:00 68:F7:28:00:00:00\" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of \"02:00:00:00:00:00 00:00:00:00:00:00\" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more then one additional MAC addresses, one of them is chosen randomly. For example, \"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00\" will create a fully scrambled MAC address, randomly locally or globally administered." },
-	{ "hidden", "If TRUE, indicates this network is a non-broadcasting network that hides its SSID.  In this case various workarounds may take place, such as probe-scanning the SSID for more reliable network discovery.  However, these workarounds expose inherent insecurities with hidden SSID networks, and thus hidden SSID networks should be used with caution." },
-	{ "mac-address", "If specified, this connection will only apply to the Wi-Fi device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing)." },
-	{ "mac-address-blacklist", "A list of permanent MAC addresses of Wi-Fi devices to which this connection should never apply.  Each MAC address should be given in the standard hex-digits-and-colons notation (eg \"00:11:22:33:44:55\")." },
-	{ "mac-address-randomization", "One of NM_SETTING_MAC_RANDOMIZATION_DEFAULT (0) (never randomize unless the user has set a global default to randomize and the supplicant supports randomization),  NM_SETTING_MAC_RANDOMIZATION_NEVER (1) (never randomize the MAC address), or NM_SETTING_MAC_RANDOMIZATION_ALWAYS (2) (always randomize the MAC address). This property is deprecated for 'cloned-mac-address'. Deprecated: 1" },
-	{ "mode", "Wi-Fi network mode; one of \"infrastructure\", \"adhoc\" or \"ap\".  If blank, infrastructure is assumed." },
-	{ "mtu", "If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "powersave", "One of NM_SETTING_WIRELESS_POWERSAVE_DISABLE (2) (disable Wi-Fi power saving), NM_SETTING_WIRELESS_POWERSAVE_ENABLE (3) (enable Wi-Fi power saving), NM_SETTING_WIRELESS_POWERSAVE_IGNORE (1) (don't touch currently configure setting) or NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (0) (use the globally configured value). All other values are reserved." },
-	{ "rate", "If non-zero, directs the device to only use the specified bitrate for communication with the access point.  Units are in Kb/s, ie 5500 = 5.5 Mbit/s.  This property is highly driver dependent and not all devices support setting a static bitrate." },
-	{ "seen-bssids", "A list of BSSIDs (each BSSID formatted as a MAC address like \"00:11:22:33:44:55\") that have been detected as part of the Wi-Fi network.  NetworkManager internally tracks previously seen BSSIDs. The property is only meant for reading and reflects the BSSID list of NetworkManager. The changes you make to this property will not be preserved." },
-	{ "ssid", "SSID of the Wi-Fi network. Must be specified." },
-	{ "tx-power", "If non-zero, directs the device to use the specified transmit power. Units are dBm.  This property is highly driver dependent and not all devices support setting a static transmit power." },
-};
-  
-NmcPropertyDesc setting_802_11_wireless_security[] = {
-	{ "auth-alg", "When WEP is used (ie, key-mgmt = \"none\" or \"ieee8021x\") indicate the 802.11 authentication algorithm required by the AP here.  One of \"open\" for Open System, \"shared\" for Shared Key, or \"leap\" for Cisco LEAP.  When using Cisco LEAP (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\") the \"leap-username\" and \"leap-password\" properties must be specified." },
-	{ "group", "A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list.  For maximum compatibility leave this property empty.  Each list element may be one of \"wep40\", \"wep104\", \"tkip\", or \"ccmp\"." },
-	{ "key-mgmt", "Key management used for the connection.  One of \"none\" (WEP), \"ieee8021x\" (Dynamic WEP), \"wpa-none\" (Ad-Hoc WPA-PSK), \"wpa-psk\" (infrastructure WPA-PSK), or \"wpa-eap\" (WPA-Enterprise).  This property must be set for any Wi-Fi connection that uses security." },
-	{ "leap-password", "The login password for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\")." },
-	{ "leap-password-flags", "Flags indicating how to handle the \"leap-password\" property." },
-	{ "leap-username", "The login username for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\")." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "pairwise", "A list of pairwise encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty.  Each list element may be one of \"tkip\" or \"ccmp\"." },
-	{ "proto", "List of strings specifying the allowed WPA protocol versions to use. Each element may be one \"wpa\" (allow WPA) or \"rsn\" (allow WPA2/RSN).  If not specified, both WPA and RSN connections are allowed." },
-	{ "psk", "Pre-Shared-Key for WPA networks.  If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key.  Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network." },
-	{ "psk-flags", "Flags indicating how to handle the \"psk\" property." },
-	{ "wep-key-flags", "Flags indicating how to handle the \"wep-key0\", \"wep-key1\", \"wep-key2\", and \"wep-key3\" properties." },
-	{ "wep-key-type", "Controls the interpretation of WEP keys.  Allowed values are NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character hexadecimal string, or a 5- or 13-character ASCII password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a string and will be hashed using the de-facto MD5 method to derive the actual WEP key." },
-	{ "wep-key0", "Index 0 WEP key.  This is the WEP key used in most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted." },
-	{ "wep-key1", "Index 1 WEP key.  This WEP index is not used by most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted." },
-	{ "wep-key2", "Index 2 WEP key.  This WEP index is not used by most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted." },
-	{ "wep-key3", "Index 3 WEP key.  This WEP index is not used by most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted." },
-	{ "wep-tx-keyidx", "When static WEP is used (ie, key-mgmt = \"none\") and a non-default WEP key index is used by the AP, put that WEP key index here.  Valid values are 0 (default key) through 3.  Note that some consumer access points (like the Linksys WRT54G) number the keys 1 - 4." },
-};
-  
-NmcPropertyDesc setting_802_1x[] = {
-	{ "altsubject-matches", "List of strings to be matched against the altSubjectName of the certificate presented by the authentication server. If the list is empty, no verification of the server certificate's altSubjectName is performed." },
-	{ "anonymous-identity", "Anonymous identity string for EAP authentication methods.  Used as the unencrypted identity with EAP types that support different tunneled identity like EAP-TTLS." },
-	{ "auth-timeout", "A timeout for the authentication. Zero means the global default; if the global default is not set, the authentication timeout is 25 seconds." },
-	{ "ca-cert", "Contains the CA certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." },
-	{ "ca-cert-password", "The password used to access the CA certificate stored in \"ca-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login." },
-	{ "ca-cert-password-flags", "Flags indicating how to handle the \"ca-cert-password\" property." },
-	{ "ca-path", "UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"ca-cert\" property." },
-	{ "client-cert", "Contains the client certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte." },
-	{ "client-cert-password", "The password used to access the client certificate stored in \"client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login." },
-	{ "client-cert-password-flags", "Flags indicating how to handle the \"client-cert-password\" property." },
-	{ "domain-suffix-match", "Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server.  If a matching dNSName is found, this constraint is met.  If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison." },
-	{ "eap", "The allowed EAP method to be used when authenticating to the network with 802.1x.  Valid methods are: \"leap\", \"md5\", \"tls\", \"peap\", \"ttls\", \"pwd\", and \"fast\".  Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations." },
-	{ "identity", "Identity string for EAP authentication methods.  Often the user's user or login name." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "pac-file", "UTF-8 encoded file path containing PAC for EAP-FAST." },
-	{ "password", "UTF-8 encoded password used for EAP authentication methods. If both the \"password\" property and the \"password-raw\" property are specified, \"password\" is preferred." },
-	{ "password-flags", "Flags indicating how to handle the \"password\" property." },
-	{ "password-raw", "Password used for EAP authentication methods, given as a byte array to allow passwords in other encodings than UTF-8 to be used. If both the \"password\" property and the \"password-raw\" property are specified, \"password\" is preferred." },
-	{ "password-raw-flags", "Flags indicating how to handle the \"password-raw\" property." },
-	{ "phase1-auth-flags", "Specifies authentication flags to use in \"phase 1\" outer authentication using NMSetting8021xAuthFlags options. The invidual TLS versions can be explicitly disabled. If a certain TLS disable flag is not set, it is up to the supplicant to allow or forbid it. The TLS options map to tls_disable_tlsv1_x settings. See the wpa_supplicant documentation for more details." },
-	{ "phase1-fast-provisioning", "Enables or disables in-line provisioning of EAP-FAST credentials when FAST is specified as the EAP method in the \"eap\" property. Recognized values are \"0\" (disabled), \"1\" (allow unauthenticated provisioning), \"2\" (allow authenticated provisioning), and \"3\" (allow both authenticated and unauthenticated provisioning).  See the wpa_supplicant documentation for more details." },
-	{ "phase1-peaplabel", "Forces use of the new PEAP label during key derivation.  Some RADIUS servers may require forcing the new PEAP label to interoperate with PEAPv1.  Set to \"1\" to force use of the new PEAP label.  See the wpa_supplicant documentation for more details." },
-	{ "phase1-peapver", "Forces which PEAP version is used when PEAP is set as the EAP method in the \"eap\" property.  When unset, the version reported by the server will be used.  Sometimes when using older RADIUS servers, it is necessary to force the client to use a particular PEAP version.  To do so, this property may be set to \"0\" or \"1\" to force that specific PEAP version." },
-	{ "phase2-altsubject-matches", "List of strings to be matched against the altSubjectName of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If the list is empty, no verification of the server certificate's altSubjectName is performed." },
-	{ "phase2-auth", "Specifies the allowed \"phase 2\" inner non-EAP authentication methods when an EAP method that uses an inner TLS tunnel is specified in the \"eap\" property.  Recognized non-EAP \"phase 2\" methods are \"pap\", \"chap\", \"mschap\", \"mschapv2\", \"gtc\", \"otp\", \"md5\", and \"tls\". Each \"phase 2\" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details." },
-	{ "phase2-autheap", "Specifies the allowed \"phase 2\" inner EAP-based authentication methods when an EAP method that uses an inner TLS tunnel is specified in the \"eap\" property.  Recognized EAP-based \"phase 2\" methods are \"md5\", \"mschapv2\", \"otp\", \"gtc\", and \"tls\". Each \"phase 2\" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details." },
-	{ "phase2-ca-cert", "Contains the \"phase 2\" CA certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." },
-	{ "phase2-ca-cert-password", "The password used to access the \"phase2\" CA certificate stored in \"phase2-ca-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login." },
-	{ "phase2-ca-cert-password-flags", "Flags indicating how to handle the \"phase2-ca-cert-password\" property." },
-	{ "phase2-ca-path", "UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"phase2-ca-cert\" property." },
-	{ "phase2-client-cert", "Contains the \"phase 2\" client certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." },
-	{ "phase2-client-cert-password", "The password used to access the \"phase2\" client certificate stored in \"phase2-client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login." },
-	{ "phase2-client-cert-password-flags", "Flags indicating how to handle the \"phase2-client-cert-password\" property." },
-	{ "phase2-domain-suffix-match", "Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication.  If a matching dNSName is found, this constraint is met.  If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison." },
-	{ "phase2-private-key", "Contains the \"phase 2\" inner private key when the \"phase2-auth\" or \"phase2-autheap\" property is set to \"tls\". Key data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the \"phase2-private-key-password\" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte, and as with the blob scheme the \"phase2-private-key-password\" property must be set to the password used to decode the PKCS#12 private key and certificate." },
-	{ "phase2-private-key-password", "The password used to decrypt the \"phase 2\" private key specified in the \"phase2-private-key\" property when the private key either uses the path scheme, or is a PKCS#12 format key." },
-	{ "phase2-private-key-password-flags", "Flags indicating how to handle the \"phase2-private-key-password\" property." },
-	{ "phase2-subject-match", "Substring to be matched against the subject of the certificate presented by the authentication server during the inner \"phase 2\" authentication. When unset, no verification of the authentication server certificate's subject is performed.  This property provides little security, if any, and its use is deprecated in favor of NMSetting8021x:phase2-domain-suffix-match." },
-	{ "pin", "PIN used for EAP authentication methods." },
-	{ "pin-flags", "Flags indicating how to handle the \"pin\" property." },
-	{ "private-key", "Contains the private key when the \"eap\" property is set to \"tls\". Key data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the \"private-key-password\" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte, and as with the blob scheme the \"private-key-password\" property must be set to the password used to decode the PKCS#12 private key and certificate. WARNING: \"private-key\" is not a \"secret\" property, and thus unencrypted private key data using the BLOB scheme may be readable by unprivileged users.  Private keys should always be encrypted with a private key password to prevent unauthorized access to unencrypted private key data." },
-	{ "private-key-password", "The password used to decrypt the private key specified in the \"private-key\" property when the private key either uses the path scheme, or if the private key is a PKCS#12 format key." },
-	{ "private-key-password-flags", "Flags indicating how to handle the \"private-key-password\" property." },
-	{ "subject-match", "Substring to be matched against the subject of the certificate presented by the authentication server. When unset, no verification of the authentication server certificate's subject is performed.  This property provides little security, if any, and its use is deprecated in favor of NMSetting8021x:domain-suffix-match." },
-	{ "system-ca-certs", "When TRUE, overrides the \"ca-path\" and \"phase2-ca-path\" properties using the system CA directory specified at configure time with the --system-ca-path switch.  The certificates in this directory are added to the verification chain in addition to any certificates specified by the \"ca-cert\" and \"phase2-ca-cert\" properties. If the path provided with --system-ca-path is rather a file name (bundle of trusted CA certificates), it overrides \"ca-cert\" and \"phase2-ca-cert\" properties instead (sets ca_cert/ca_cert2 options for wpa_supplicant)." },
-};
-  
-NmcPropertyDesc setting_802_3_ethernet[] = {
-	{ "auto-negotiate", "If TRUE, enforce auto-negotiation of port speed and duplex mode.  If FALSE, \"speed\" and \"duplex\" properties should be both set or link configuration will be skipped." },
-	{ "cloned-mac-address", "If specified, request that the device use this MAC address instead. This is known as MAC cloning or spoofing. Beside explicitly specifing a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address if the device has one (otherwise this is treated as \"preserve\"). \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"preserve\" (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\"." },
-	{ "duplex", "Can be specified only when \"auto-negotiate\" is \"off\". In that case, statically configures the device to use that specified duplex mode, either \"half\" or \"full\". Must be set together with the \"speed\" property if specified. Before specifying a duplex mode be sure your device supports it." },
-	{ "generate-mac-address-mask", "With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting \"FE:FF:FF:00:00:00\" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the \"random\" or \"stable\" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of \"FE:FF:FF:00:00:00 68:F7:28:00:00:00\" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of \"02:00:00:00:00:00 00:00:00:00:00:00\" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more then one additional MAC addresses, one of them is chosen randomly. For example, \"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00\" will create a fully scrambled MAC address, randomly locally or globally administered." },
-	{ "mac-address", "If specified, this connection will only apply to the Ethernet device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing)." },
-	{ "mac-address-blacklist", "If specified, this connection will never apply to the Ethernet device whose permanent MAC address matches an address in the list.  Each MAC address is in the standard hex-digits-and-colons notation (00:11:22:33:44:55)." },
-	{ "mtu", "If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "port", "Specific port type to use if multiple the device supports multiple attachment methods.  One of \"tp\" (Twisted Pair), \"aui\" (Attachment Unit Interface), \"bnc\" (Thin Ethernet) or \"mii\" (Media Independent Interface. If the device supports only one port type, this setting is ignored." },
-	{ "s390-nettype", "s390 network device type; one of \"qeth\", \"lcs\", or \"ctc\", representing the different types of virtual network devices available on s390 systems." },
-	{ "s390-options", "Dictionary of key/value pairs of s390-specific device options.  Both keys and values must be strings.  Allowed keys include \"portno\", \"layer2\", \"portname\", \"protocol\", among others.  Key names must contain only alphanumeric characters (ie, [a-zA-Z0-9])." },
-	{ "s390-subchannels", "Identifies specific subchannels that this network device uses for communication with z/VM or s390 host.  Like the \"mac-address\" property for non-z/VM devices, this property can be used to ensure this connection only applies to the network device that uses these subchannels.  The list should contain exactly 3 strings, and each string may only be composed of hexadecimal characters and the period (.) character." },
-	{ "speed", "Can be set to a value grater than zero only when \"auto-negotiate\" is \"off\". In that case, statically configures the device to use that specified speed. In Mbit/s, ie 100 == 100Mbit/s. Must be set together with the \"duplex\" property when non-zero. Before specifying a speed value be sure your device supports it." },
-	{ "wake-on-lan", "The NMSettingWiredWakeOnLan options to enable. Not all devices support all options. May be any combination of NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST (0x4), NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST (0x8), NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST (0x10), NM_SETTING_WIRED_WAKE_ON_LAN_ARP (0x20), NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC (0x40) or the special values NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (0x1) (to use global settings) and NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (0x8000) (to disable management of Wake-on-LAN in NetworkManager)." },
-	{ "wake-on-lan-password", "If specified, the password used with magic-packet-based Wake-on-LAN, represented as an Ethernet MAC address.  If NULL, no password will be required." },
-};
-  
-NmcPropertyDesc setting_adsl[] = {
-	{ "encapsulation", "Encapsulation of ADSL connection.  Can be \"vcmux\" or \"llc\"." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "password", "Password used to authenticate with the ADSL service." },
-	{ "password-flags", "Flags indicating how to handle the \"password\" property." },
-	{ "protocol", "ADSL connection protocol.  Can be \"pppoa\", \"pppoe\" or \"ipoatm\"." },
-	{ "username", "Username used to authenticate with the ADSL service." },
-	{ "vci", "VCI of ADSL connection" },
-	{ "vpi", "VPI of ADSL connection" },
-};
-  
-NmcPropertyDesc setting_bluetooth[] = {
-	{ "bdaddr", "The Bluetooth address of the device." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "type", "Either \"dun\" for Dial-Up Networking connections or \"panu\" for Personal Area Networking connections to devices supporting the NAP profile." },
-};
-  
-NmcPropertyDesc setting_bond[] = {
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "options", "Dictionary of key/value pairs of bonding options.  Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, [a-zA-Z0-9])." },
-};
-  
-NmcPropertyDesc setting_bridge[] = {
-	{ "ageing-time", "The Ethernet MAC address aging time, in seconds." },
-	{ "forward-delay", "The Spanning Tree Protocol (STP) forwarding delay, in seconds." },
-	{ "hello-time", "The Spanning Tree Protocol (STP) hello time, in seconds." },
-	{ "mac-address", "If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. When matching an existing (outside NetworkManager created) bridge, this MAC address must match." },
-	{ "max-age", "The Spanning Tree Protocol (STP) maximum message age, in seconds." },
-	{ "multicast-snooping", "Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "priority", "Sets the Spanning Tree Protocol (STP) priority for this bridge.  Lower values are \"better\"; the lowest priority bridge will be elected the root bridge." },
-	{ "stp", "Controls whether Spanning Tree Protocol (STP) is enabled for this bridge." },
-};
-  
-NmcPropertyDesc setting_bridge_port[] = {
-	{ "hairpin-mode", "Enables or disabled \"hairpin mode\" for the port, which allows frames to be sent back out through the port the frame was received on." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "path-cost", "The Spanning Tree Protocol (STP) port cost for destinations via this port." },
-	{ "priority", "The Spanning Tree Protocol (STP) priority of this bridge port." },
-};
-  
-NmcPropertyDesc setting_cdma[] = {
-	{ "mtu", "If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "number", "The number to dial to establish the connection to the CDMA-based mobile broadband network, if any.  If not specified, the default number (#777) is used when required." },
-	{ "password", "The password used to authenticate with the network, if required.  Many providers do not require a password, or accept any password.  But if a password is required, it is specified here." },
-	{ "password-flags", "Flags indicating how to handle the \"password\" property." },
-	{ "username", "The username used to authenticate with the network, if required.  Many providers do not require a username, or accept any username.  But if a username is required, it is specified here." },
-};
-  
-NmcPropertyDesc setting_connection[] = {
-	{ "autoconnect", "Whether or not the connection should be automatically connected by NetworkManager when the resources for the connection are available. TRUE to automatically activate the connection, FALSE to require manual intervention to activate the connection." },
-	{ "autoconnect-priority", "The autoconnect priority. If the connection is set to autoconnect, connections with higher priority will be preferred. Defaults to 0. The higher number means higher priority." },
-	{ "autoconnect-retries", "The number of times a connection should be tried when autoctivating before giving up. Zero means forever, -1 means the global default (4 times if not overridden)." },
-	{ "autoconnect-slaves", "Whether or not slaves of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for master connections. The permitted values are: 0: leave slave connections untouched, 1: activate all the slave connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-slaves is read to determine the real value. If it is default as well, this fallbacks to 0." },
-	{ "gateway-ping-timeout", "If greater than zero, delay success of IP addressing until either the timeout is reached, or an IP gateway replies to a ping." },
-	{ "id", "A human readable unique identifier for the connection, like \"Work Wi-Fi\" or \"T-Mobile 3G\"." },
-	{ "interface-name", "The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface." },
-	{ "lldp", "Whether LLDP is enabled for the connection." },
-	{ "master", "Interface name of the master device or UUID of the master connection." },
-	{ "metered", "Whether the connection is metered. When updating this property on a currently activated connection, the change takes effect immediately." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "permissions", "An array of strings defining what access a given user has to this connection.  If this is NULL or empty, all users are allowed to access this connection; otherwise users are allowed if and only if they are in this list.  When this is not empty, the connection can be active only when one of the specified users is logged into an active session.  Each entry is of the form \"[type]:[id]:[reserved]\"; for example, \"user:dcbw:blah\". At this time only the \"user\" [type] is allowed.  Any other values are ignored and reserved for future use.  [id] is the username that this permission refers to, which may not contain the \":\" character. Any [reserved] information present must be ignored and is reserved for future use.  All of [type], [id], and [reserved] must be valid UTF-8." },
-	{ "read-only", "FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified." },
-	{ "secondaries", "List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported." },
-	{ "slave-type", "Setting name of the device type of this slave's master connection (eg, \"bond\"), or NULL if this connection is not a slave." },
-	{ "stable-id", "Token to generate stable IDs for the connection. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. Note that also the interface name of the activating connection and a per-host secret key is included into the address generation so that the same stable-id on different hosts/devices yields different addresses. If the value is unset, an ID unique for the connection is used. Specifing a stable-id allows multiple connections to generate the same addresses. Another use is to generate IDs at runtime via dynamic substitutions. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-boot, or every time. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}/${BOOT}\" to create a unique id for this connection that changes with every reboot. Note that two connections only use the same effective id if their stable-id is also identical before performing dynamic substitutions." },
-	{ "timestamp", "The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved)." },
-	{ "type", "Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc)." },
-	{ "uuid", "A universally unique identifier for the connection, for example generated with libuuid.  It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network.  For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\")." },
-	{ "zone", "The trust level of a the connection.  Free form case-insensitive string (for example \"Home\", \"Work\", \"Public\").  NULL or unspecified zone means the connection will be placed in the default zone as defined by the firewall. When updating this property on a currently activated connection, the change takes effect immediately." },
-};
-  
-NmcPropertyDesc setting_dcb[] = {
-	{ "app-fcoe-flags", "Specifies the NMSettingDcbFlags for the DCB FCoE application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." },
-	{ "app-fcoe-mode", "The FCoE controller mode; either \"fabric\" (default) or \"vn2vn\"." },
-	{ "app-fcoe-priority", "The highest User Priority (0 - 7) which FCoE frames should use, or -1 for default priority.  Only used when the \"app-fcoe-flags\" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag." },
-	{ "app-fip-flags", "Specifies the NMSettingDcbFlags for the DCB FIP application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." },
-	{ "app-fip-priority", "The highest User Priority (0 - 7) which FIP frames should use, or -1 for default priority.  Only used when the \"app-fip-flags\" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag." },
-	{ "app-iscsi-flags", "Specifies the NMSettingDcbFlags for the DCB iSCSI application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." },
-	{ "app-iscsi-priority", "The highest User Priority (0 - 7) which iSCSI frames should use, or -1 for default priority. Only used when the \"app-iscsi-flags\" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "priority-bandwidth", "An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the percentage of bandwidth of the priority's assigned group that the priority may use.  The sum of all percentages for priorities which belong to the same group must total 100 percent." },
-	{ "priority-flow-control", "An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the corresponding priority should transmit priority pause." },
-	{ "priority-flow-control-flags", "Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." },
-	{ "priority-group-bandwidth", "An array of 8 uint values, where the array index corresponds to the Priority Group ID (0 - 7) and the value indicates the percentage of link bandwidth allocated to that group.  Allowed values are 0 - 100, and the sum of all values must total 100 percent." },
-	{ "priority-group-flags", "Specifies the NMSettingDcbFlags for DCB Priority Groups.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." },
-	{ "priority-group-id", "An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the Priority Group ID.  Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted group." },
-	{ "priority-strict-bandwidth", "An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group." },
-	{ "priority-traffic-class", "An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped." },
-};
-  
-NmcPropertyDesc setting_dummy[] = {
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-};
-  
-NmcPropertyDesc setting_generic[] = {
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-};
-  
-NmcPropertyDesc setting_gsm[] = {
-	{ "apn", "The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network.  The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9." },
-	{ "device-id", "The device unique identifier (as given by the WWAN management service) which this connection applies to.  If given, the connection will only apply to the specified device." },
-	{ "home-only", "When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made." },
-	{ "mtu", "If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "network-id", "The Network ID (GSM LAI format, ie MCC-MNC) to force specific network registration.  If the Network ID is specified, NetworkManager will attempt to force the device to register only on the specified network. This can be used to ensure that the device does not roam when direct roaming control of the device is not otherwise possible." },
-	{ "number", "Number to dial when establishing a PPP data session with the GSM-based mobile broadband network.  Many modems do not require PPP for connections to the mobile network and thus this property should be left blank, which allows NetworkManager to select the appropriate settings automatically." },
-	{ "password", "The password used to authenticate with the network, if required.  Many providers do not require a password, or accept any password.  But if a password is required, it is specified here." },
-	{ "password-flags", "Flags indicating how to handle the \"password\" property." },
-	{ "pin", "If the SIM is locked with a PIN it must be unlocked before any other operations are requested.  Specify the PIN here to allow operation of the device." },
-	{ "pin-flags", "Flags indicating how to handle the \"pin\" property." },
-	{ "sim-id", "The SIM card unique identifier (as given by the WWAN management service) which this connection applies to.  If given, the connection will apply to any device also allowed by \"device-id\" which contains a SIM card matching the given identifier." },
-	{ "sim-operator-id", "A MCC/MNC string like \"310260\" or \"21601\" identifying the specific mobile network operator which this connection applies to.  If given, the connection will apply to any device also allowed by \"device-id\" and \"sim-id\" which contains a SIM card provisioined by the given operator." },
-	{ "username", "The username used to authenticate with the network, if required.  Many providers do not require a username, or accept any username.  But if a username is required, it is specified here." },
-};
-  
-NmcPropertyDesc setting_infiniband[] = {
-	{ "mac-address", "If specified, this connection will only apply to the IPoIB device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing)." },
-	{ "mtu", "If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "p-key", "The InfiniBand P_Key to use for this device. A value of -1 means to use the default P_Key (aka \"the P_Key at index 0\").  Otherwise it is a 16-bit unsigned integer, whose high bit is set if it is a \"full membership\" P_Key." },
-	{ "parent", "The interface name of the parent device of this device. Normally NULL, but if the \"p_key\" property is set, then you must specify the base device by setting either this property or \"mac-address\"." },
-	{ "transport-mode", "The IP-over-InfiniBand transport mode. Either \"datagram\" or \"connected\"." },
-};
-  
-NmcPropertyDesc setting_ip_tunnel[] = {
-	{ "encapsulation-limit", "How many additional levels of encapsulation are permitted to be prepended to packets. This property applies only to IPv6 tunnels." },
-	{ "flow-label", "The flow label to assign to tunnel packets. This property applies only to IPv6 tunnels." },
-	{ "input-key", "The key used for tunnel input packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used." },
-	{ "local", "The local endpoint of the tunnel; the value can be empty, otherwise it must contain an IPv4 or IPv6 address." },
-	{ "mode", "The tunneling mode, for example NM_IP_TUNNEL_MODE_IPIP (1) or NM_IP_TUNNEL_MODE_GRE (2)." },
-	{ "mtu", "None" },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "output-key", "The key used for tunnel output packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used." },
-	{ "parent", "If given, specifies the parent interface name or parent connection UUID the new device will be bound to so that tunneled packets will only be routed via that interface." },
-	{ "path-mtu-discovery", "Whether to enable Path MTU Discovery on this tunnel." },
-	{ "remote", "The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 address." },
-	{ "tos", "The type of service (IPv4) or traffic class (IPv6) field to be set on tunneled packets." },
-	{ "ttl", "The TTL to assign to tunneled packets. 0 is a special value meaning that packets inherit the TTL value." },
-};
-  
-NmcPropertyDesc setting_ipv4[] = {
-	{ "addresses", "Array of IP addresses." },
-	{ "dad-timeout", "Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network.  If an address conflict is detected, the activation will fail.  A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or 3 seconds).  A value greater than zero is a timeout in milliseconds." },
-	{ "dhcp-client-id", "A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options. When the property is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which case the first byte is assumed to be the 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC address). If the property is not a hex string it is considered as a non-hardware-address client ID and the 'type' field is set to 0." },
-	{ "dhcp-fqdn", "If the \"dhcp-send-hostname\" property is TRUE, then the specified FQDN will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-hostname\" are mutually exclusive and cannot be set at the same time." },
-	{ "dhcp-hostname", "If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time." },
-	{ "dhcp-send-hostname", "If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer.  If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent." },
-	{ "dhcp-timeout", "A timeout for a DHCP transaction in seconds." },
-	{ "dns", "Array of IP addresses of DNS servers." },
-	{ "dns-options", "Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties." },
-	{ "dns-priority", "Intra-connection DNS priority. The relative priority to be used when determining the order of DNS servers in resolv.conf.  A lower value means that servers will be on top of the file.  Zero selects the default value, which is 50 for VPNs and 100 for other connections.  Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. For that, just specify the DNS servers in the desired order. When multiple devices have configurations with the same priority, the one with an active default route will be preferred. Note that when using dns=dnsmasq the order is meaningless since dnsmasq forwards queries to all known servers at the same time. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used." },
-	{ "dns-search", "Array of DNS search domains." },
-	{ "gateway", "The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set." },
-	{ "ignore-auto-dns", "When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used." },
-	{ "ignore-auto-routes", "When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used." },
-	{ "may-fail", "If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out.  Note that at least one IP configuration must succeed or overall network configuration will still fail.  For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully." },
-	{ "method", "IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration.  The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "never-default", "If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager." },
-	{ "route-metric", "The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is choosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric." },
-	{ "routes", "Array of IP routes." },
-};
-  
-NmcPropertyDesc setting_ipv6[] = {
-	{ "addr-gen-mode", "Configure method for creating the address for use with RFC4862 IPv6 Stateless Address Autoconfiguration. The permitted values are: \"eui64\", or \"stable-privacy\". If the property is set to \"eui64\", the addresses will be generated using the interface tokens derived from  hardware address. This makes the host part of the address to stay constant, making it possible to track host's presence when it changes networks. The address changes when the interface hardware is replaced. The value of \"stable-privacy\" enables use of cryptographically secure hash of a secret host-specific key along with the connection's stable-id and the network address as specified by RFC7217. This makes it impossible to use the address track host's presence, and makes the address stable when the network interface hardware is replaced. On D-Bus, the absence of an addr-gen-mode setting equals enabling \"stable-privacy\". For keyfile plugin, the absence of the setting on disk means \"eui64\" so that the property doesn't change on upgrade from older versions. Note that this setting is distinct from the Privacy Extensions as configured by \"ip6-privacy\" property and it does not affect the temporary addresses configured with this option." },
-	{ "addresses", "Array of IP addresses." },
-	{ "dad-timeout", "Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network.  If an address conflict is detected, the activation will fail.  A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or 3 seconds).  A value greater than zero is a timeout in milliseconds." },
-	{ "dhcp-hostname", "If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time." },
-	{ "dhcp-send-hostname", "If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer.  If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent." },
-	{ "dhcp-timeout", "A timeout for a DHCP transaction in seconds." },
-	{ "dns", "Array of IP addresses of DNS servers." },
-	{ "dns-options", "Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties." },
-	{ "dns-priority", "Intra-connection DNS priority. The relative priority to be used when determining the order of DNS servers in resolv.conf.  A lower value means that servers will be on top of the file.  Zero selects the default value, which is 50 for VPNs and 100 for other connections.  Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. For that, just specify the DNS servers in the desired order. When multiple devices have configurations with the same priority, the one with an active default route will be preferred. Note that when using dns=dnsmasq the order is meaningless since dnsmasq forwards queries to all known servers at the same time. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used." },
-	{ "dns-search", "Array of DNS search domains." },
-	{ "gateway", "The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set." },
-	{ "ignore-auto-dns", "When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used." },
-	{ "ignore-auto-routes", "When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used." },
-	{ "ip6-privacy", "Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941.  If enabled, it makes the kernel generate a temporary IPv6 address in addition to the public one generated from MAC address via modified EUI-64.  This enhances privacy, but could cause problems in some applications, on the other hand.  The permitted values are: -1: unknown, 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary addresses). Having a per-connection setting set to \"-1\" (unknown) means fallback to global configuration \"ipv6.ip6-privacy\". If also global configuration is unspecified or set to \"-1\", fallback to read \"/proc/sys/net/ipv6/conf/default/use_tempaddr\". Note that this setting is distinct from the Stable Privacy addresses that can be enabled with the \"addr-gen-mode\" property's \"stable-privacy\" setting as another way of avoiding host tracking with IPv6 addresses." },
-	{ "may-fail", "If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out.  Note that at least one IP configuration must succeed or overall network configuration will still fail.  For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully." },
-	{ "method", "IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration.  The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "never-default", "If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager." },
-	{ "route-metric", "The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is choosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric." },
-	{ "routes", "Array of IP routes." },
-	{ "token", "Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode." },
-};
-  
-NmcPropertyDesc setting_macsec[] = {
-	{ "encrypt", "Whether the transmitted traffic must be encrypted." },
-	{ "mka-cak", "The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement." },
-	{ "mka-cak-flags", "Flags indicating how to handle the \"mka-cak\" property." },
-	{ "mka-ckn", "The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement." },
-	{ "mode", "Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "parent", "If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property." },
-	{ "port", "The port component of the SCI (Secure Channel Identifier), between 1 and 65534." },
-	{ "validation", "Specifies the validation mode for incoming frames." },
-};
-  
-NmcPropertyDesc setting_macvlan[] = {
-	{ "mode", "The macvlan mode, which specifies the communication mechanism between multiple macvlans on the same lower device." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "parent", "If given, specifies the parent interface name or parent connection UUID from which this MAC-VLAN interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property." },
-	{ "promiscuous", "Whether the interface should be put in promiscuous mode." },
-	{ "tap", "Whether the interface should be a MACVTAP." },
-};
-  
-NmcPropertyDesc setting_ppp[] = {
-	{ "baud", "If non-zero, instruct pppd to set the serial port to the specified baudrate.  This value should normally be left as 0 to automatically choose the speed." },
-	{ "crtscts", "If TRUE, specify that pppd should set the serial port to use hardware flow control with RTS and CTS signals.  This value should normally be set to FALSE." },
-	{ "lcp-echo-failure", "If non-zero, instruct pppd to presume the connection to the peer has failed if the specified number of LCP echo-requests go unanswered by the peer.  The \"lcp-echo-interval\" property must also be set to a non-zero value if this property is used." },
-	{ "lcp-echo-interval", "If non-zero, instruct pppd to send an LCP echo-request frame to the peer every n seconds (where n is the specified value).  Note that some PPP peers will respond to echo requests and some will not, and it is not possible to autodetect this." },
-	{ "mppe-stateful", "If TRUE, stateful MPPE is used.  See pppd documentation for more information on stateful MPPE." },
-	{ "mru", "If non-zero, instruct pppd to request that the peer send packets no larger than the specified size.  If non-zero, the MRU should be between 128 and 16384." },
-	{ "mtu", "If non-zero, instruct pppd to send packets no larger than the specified size." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "no-vj-comp", "If TRUE, Van Jacobsen TCP header compression will not be requested." },
-	{ "noauth", "If TRUE, do not require the other side (usually the PPP server) to authenticate itself to the client.  If FALSE, require authentication from the remote side.  In almost all cases, this should be TRUE." },
-	{ "nobsdcomp", "If TRUE, BSD compression will not be requested." },
-	{ "nodeflate", "If TRUE, \"deflate\" compression will not be requested." },
-	{ "refuse-chap", "If TRUE, the CHAP authentication method will not be used." },
-	{ "refuse-eap", "If TRUE, the EAP authentication method will not be used." },
-	{ "refuse-mschap", "If TRUE, the MSCHAP authentication method will not be used." },
-	{ "refuse-mschapv2", "If TRUE, the MSCHAPv2 authentication method will not be used." },
-	{ "refuse-pap", "If TRUE, the PAP authentication method will not be used." },
-	{ "require-mppe", "If TRUE, MPPE (Microsoft Point-to-Point Encrpytion) will be required for the PPP session.  If either 64-bit or 128-bit MPPE is not available the session will fail.  Note that MPPE is not used on mobile broadband connections." },
-	{ "require-mppe-128", "If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encrpytion) will be required for the PPP session, and the \"require-mppe\" property must also be set to TRUE.  If 128-bit MPPE is not available the session will fail." },
-};
-  
-NmcPropertyDesc setting_pppoe[] = {
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "password", "Password used to authenticate with the PPPoE service." },
-	{ "password-flags", "Flags indicating how to handle the \"password\" property." },
-	{ "service", "If specified, instruct PPPoE to only initiate sessions with access concentrators that provide the specified service.  For most providers, this should be left blank.  It is only required if there are multiple access concentrators or a specific service is known to be required." },
-	{ "username", "Username used to authenticate with the PPPoE service." },
-};
-  
-NmcPropertyDesc setting_proxy[] = {
-	{ "browser-only", "Whether the proxy configuration is for browser only." },
-	{ "method", "Method for proxy configuration, Default is NM_SETTING_PROXY_METHOD_NONE (0)" },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "pac-script", "PAC script for the connection." },
-	{ "pac-url", "PAC URL for obtaining PAC file." },
-};
-  
-NmcPropertyDesc setting_serial[] = {
-	{ "baud", "Speed to use for communication over the serial port.  Note that this value usually has no effect for mobile broadband modems as they generally ignore speed settings and use the highest available speed." },
-	{ "bits", "Byte-width of the serial communication. The 8 in \"8n1\" for example." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "parity", "Parity setting of the serial port." },
-	{ "send-delay", "Time to delay between each byte sent to the modem, in microseconds." },
-	{ "stopbits", "Number of stop bits for communication on the serial port.  Either 1 or 2. The 1 in \"8n1\" for example." },
-};
-  
-NmcPropertyDesc setting_team[] = {
-	{ "config", "The JSON configuration for the team network interface.  The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used.  See man teamd.conf for the format details." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-};
-  
-NmcPropertyDesc setting_team_port[] = {
-	{ "config", "The JSON configuration for the team port. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-};
-  
-NmcPropertyDesc setting_tun[] = {
-	{ "group", "The group ID which will own the device. If set to NULL everyone will be able to use the device." },
-	{ "mode", "The operating mode of the virtual device. Allowed values are NM_SETTING_TUN_MODE_TUN (1) to create a layer 3 device and NM_SETTING_TUN_MODE_TAP (2) to create an Ethernet-like layer 2 one." },
-	{ "multi-queue", "If the property is set to TRUE, the interface will support multiple file descriptors (queues) to parallelize packet sending or receiving. Otherwise, the interface will only support a single queue." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "owner", "The user ID which will own the device. If set to NULL everyone will be able to use the device." },
-	{ "pi", "If TRUE the interface will prepend a 4 byte header describing the physical interface to the packets." },
-	{ "vnet-hdr", "If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio network header." },
-};
-  
-NmcPropertyDesc setting_user[] = {
-	{ "data", "A dictionary of key/value pairs with user data. This data is ignored by NetworkManager and can be used at the users discretion. The keys only support a strict ascii format, but the values can be arbitrary UTF8 strings up to a certain length." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-};
-  
-NmcPropertyDesc setting_vlan[] = {
-	{ "egress-priority-map", "For outgoing packets, a list of mappings from Linux SKB priorities to 802.1p priorities.  The mapping is given in the format \"from:to\" where both \"from\" and \"to\" are unsigned integers, ie \"7:3\"." },
-	{ "flags", "One or more flags which control the behavior and features of the VLAN interface.  Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use of the GVRP protocol), and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose binding of the interface to its master device's operating state). NM_VLAN_FLAG_MVRP (0x8) (use of the MVRP protocol). The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, but it used to be 0. To preserve backward compatibility, the default-value in the D-Bus API continues to be 0 and a missing property on D-Bus is still considered as 0." },
-	{ "id", "The VLAN identifier that the interface created by this connection should be assigned. The valid range is from 0 to 4094, without the reserved id 4095." },
-	{ "ingress-priority-map", "For incoming packets, a list of mappings from 802.1p priorities to Linux SKB priorities.  The mapping is given in the format \"from:to\" where both \"from\" and \"to\" are unsigned integers, ie \"7:3\"." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "parent", "If given, specifies the parent interface name or parent connection UUID from which this VLAN interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property." },
-};
-  
-NmcPropertyDesc setting_vpn[] = {
-	{ "data", "Dictionary of key/value pairs of VPN plugin specific data.  Both keys and values must be strings." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "persistent", "If the VPN service supports persistence, and this property is TRUE, the VPN will attempt to stay connected across link changes and outages, until explicitly disconnected." },
-	{ "secrets", "Dictionary of key/value pairs of VPN plugin specific secrets like passwords or private keys.  Both keys and values must be strings." },
-	{ "service-type", "D-Bus service name of the VPN plugin that this setting uses to connect to its network.  i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin." },
-	{ "timeout", "Timeout for the VPN service to establish the connection. Some services may take quite a long time to connect. Value of 0 means a default timeout, which is 60 seconds (unless overriden by vpn.timeout in configuration file). Values greater than zero mean timeout in seconds." },
-	{ "user-name", "If the VPN connection requires a user name for authentication, that name should be provided here.  If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty.  If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection." },
-};
-  
-NmcPropertyDesc setting_vxlan[] = {
-	{ "ageing", "Specifies the lifetime in seconds of FDB entries learnt by the kernel." },
-	{ "destination-port", "Specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint." },
-	{ "id", "Specifies the VXLAN Network Identifer (or VXLAN Segment Identifier) to use." },
-	{ "l2-miss", "Specifies whether netlink LL ADDR miss notifications are generated." },
-	{ "l3-miss", "Specifies whether netlink IP ADDR miss notifications are generated." },
-	{ "learning", "Specifies whether unknown source link layer addresses and IP addresses are entered into the VXLAN device forwarding database." },
-	{ "limit", "Specifies the maximum number of FDB entries. A value of zero means that the kernel will store unlimited entries." },
-	{ "local", "If given, specifies the source IP address to use in outgoing packets." },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "parent", "If given, specifies the parent interface name or parent connection UUID." },
-	{ "proxy", "Specifies whether ARP proxy is turned on." },
-	{ "remote", "Specifies the unicast destination IP address to use in outgoing packets when the destination link layer address is not known in the VXLAN device forwarding database, or the multicast IP address to join." },
-	{ "rsc", "Specifies whether route short circuit is turned on." },
-	{ "source-port-max", "Specifies the maximum UDP source port to communicate to the remote VXLAN tunnel endpoint." },
-	{ "source-port-min", "Specifies the minimum UDP source port to communicate to the remote VXLAN tunnel endpoint." },
-	{ "tos", "Specifies the TOS value to use in outgoing packets." },
-	{ "ttl", "Specifies the time-to-live value to use in outgoing packets." },
-};
-  
-NmcPropertyDesc setting_wimax[] = {
-	{ "mac-address", "If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1" },
-	{ "name", "The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." },
-	{ "network-name", "Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1" },
-};
-  
-
-typedef struct {
-	const char *name;
-	NmcPropertyDesc *properties;
-	int n_properties;
-} NmcSettingDesc;
-
-NmcSettingDesc all_settings[] = {
-
-	{ "802-11-olpc-mesh", setting_802_11_olpc_mesh, 4 },
-	{ "802-11-wireless", setting_802_11_wireless, 17 },
-	{ "802-11-wireless-security", setting_802_11_wireless_security, 18 },
-	{ "802-1x", setting_802_1x, 45 },
-	{ "802-3-ethernet", setting_802_3_ethernet, 15 },
-	{ "adsl", setting_adsl, 8 },
-	{ "bluetooth", setting_bluetooth, 3 },
-	{ "bond", setting_bond, 2 },
-	{ "bridge", setting_bridge, 9 },
-	{ "bridge-port", setting_bridge_port, 4 },
-	{ "cdma", setting_cdma, 6 },
-	{ "connection", setting_connection, 20 },
-	{ "dcb", setting_dcb, 16 },
-	{ "dummy", setting_dummy, 1 },
-	{ "generic", setting_generic, 1 },
-	{ "gsm", setting_gsm, 14 },
-	{ "infiniband", setting_infiniband, 6 },
-	{ "ip-tunnel", setting_ip_tunnel, 13 },
-	{ "ipv4", setting_ipv4, 20 },
-	{ "ipv6", setting_ipv6, 21 },
-	{ "macsec", setting_macsec, 9 },
-	{ "macvlan", setting_macvlan, 5 },
-	{ "ppp", setting_ppp, 19 },
-	{ "pppoe", setting_pppoe, 5 },
-	{ "proxy", setting_proxy, 5 },
-	{ "serial", setting_serial, 6 },
-	{ "team", setting_team, 2 },
-	{ "team-port", setting_team_port, 2 },
-	{ "tun", setting_tun, 7 },
-	{ "user", setting_user, 2 },
-	{ "vlan", setting_vlan, 6 },
-	{ "vpn", setting_vpn, 7 },
-	{ "vxlan", setting_vxlan, 17 },
-	{ "wimax", setting_wimax, 3 },
-};
-
-static int
-find_by_name (gconstpointer keyv, gconstpointer cmpv)
-{
-	const char *key = keyv;
-	struct { const char *name; gpointer data; } *cmp = (gpointer)cmpv;
-
-	return strcmp (key, cmp->name);
-}
-
-static const char *
-nmc_setting_get_property_doc (NMSetting *setting, const char *prop)
-{
-	NmcSettingDesc *setting_desc;
-	NmcPropertyDesc *property_desc;
-
-	setting_desc = bsearch (nm_setting_get_name (setting),
-	                        all_settings, G_N_ELEMENTS (all_settings),
-	                        sizeof (NmcSettingDesc), find_by_name);
-	if (!setting_desc)
-		return NULL;
-	property_desc = bsearch (prop,
-	                         setting_desc->properties, setting_desc->n_properties,
-	                         sizeof (NmcPropertyDesc), find_by_name);
-	if (!property_desc)
-		return NULL;
-	return property_desc->docs;
-}
-  
\ No newline at end of file
diff --git a/clients/cli/settings-docs.xsl b/clients/cli/settings-docs.xsl
deleted file mode 100644
index 996644bd..00000000
--- a/clients/cli/settings-docs.xsl
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xsl:stylesheet version="1.0"
-                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-
-  <xsl:output
-      method="text"
-      doctype-public="-//OASIS//DTD DocBook XML V4.3//EN"
-      doctype-system="http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
-      />
-
-  <xsl:template match="nm-setting-docs">/* Generated file. Do not edit. */
-
-typedef struct {
-	const char *name;
-	const char *docs;
-} NmcPropertyDesc;
-<xsl:apply-templates select="setting" mode="properties"><xsl:sort select="@name"/></xsl:apply-templates>
-
-typedef struct {
-	const char *name;
-	NmcPropertyDesc *properties;
-	int n_properties;
-} NmcSettingDesc;
-
-NmcSettingDesc all_settings[] = {
-<xsl:apply-templates select="setting" mode="settings"><xsl:sort select="@name"/></xsl:apply-templates>
-};
-
-static int
-find_by_name (gconstpointer keyv, gconstpointer cmpv)
-{
-	const char *key = keyv;
-	struct { const char *name; gpointer data; } *cmp = (gpointer)cmpv;
-
-	return strcmp (key, cmp->name);
-}
-
-static const char *
-nmc_setting_get_property_doc (NMSetting *setting, const char *prop)
-{
-	NmcSettingDesc *setting_desc;
-	NmcPropertyDesc *property_desc;
-
-	setting_desc = bsearch (nm_setting_get_name (setting),
-	                        all_settings, G_N_ELEMENTS (all_settings),
-	                        sizeof (NmcSettingDesc), find_by_name);
-	if (!setting_desc)
-		return NULL;
-	property_desc = bsearch (prop,
-	                         setting_desc->properties, setting_desc->n_properties,
-	                         sizeof (NmcPropertyDesc), find_by_name);
-	if (!property_desc)
-		return NULL;
-	return property_desc->docs;
-}
-  </xsl:template>
-
-  <xsl:template match="setting" mode="properties">
-NmcPropertyDesc setting_<xsl:value-of select="translate(@name,'-','_')"/>[] = {<xsl:apply-templates select="property"><xsl:sort select="@name"/></xsl:apply-templates>
-};
-  </xsl:template>
-
-  <xsl:template match="property">
-    <xsl:variable name="docs">
-      <xsl:call-template name="escape_quotes">
-	<xsl:with-param name="string" select="@description"/>
-      </xsl:call-template>
-    </xsl:variable>
-	{ "<xsl:value-of select="@name"/>", "<xsl:value-of select="$docs"/>" },</xsl:template>
-
-  <xsl:template match="setting" mode="settings">
-	{ "<xsl:value-of select="@name"/>", setting_<xsl:value-of select="translate(@name,'-','_')"/>, <xsl:value-of select="count(./property)"/> },</xsl:template>
-
-    <xsl:template name="escape_quotes">
-	<xsl:param name="string" />
-	<xsl:choose>
-	    <xsl:when test="contains($string, '&quot;')">
-		<xsl:value-of select="substring-before($string, '&quot;')" />\&quot;<xsl:call-template name="escape_quotes"><xsl:with-param name="string" select="substring-after($string, '&quot;')" /></xsl:call-template>
-	    </xsl:when>
-	    <xsl:otherwise>
-		<xsl:value-of select="$string" />
-	    </xsl:otherwise>
-	</xsl:choose>
-    </xsl:template>
-
-</xsl:stylesheet>
diff --git a/clients/cli/settings.c b/clients/cli/settings.c
index e0f045ac..e0db1b5b 100644
--- a/clients/cli/settings.c
+++ b/clients/cli/settings.c
@@ -25,5793 +25,15 @@
 #include <arpa/inet.h>
 
 #include "nm-common-macros.h"
-#include "utils.h"
-#include "common.h"
-#include "nm-vpn-helpers.h"
-
-/* Forward declarations */
-static char *wep_key_type_to_string (NMWepKeyType type);
-
-typedef enum {
-	NMC_PROPERTY_GET_PRETTY,
-	NMC_PROPERTY_GET_PARSABLE,
-} NmcPropertyGetType;
-
-/* Helper macro to define fields */
-#define SETTING_FIELD(setting) { setting, N_(setting), 0, NULL, FALSE, FALSE, 0 }
-
-/* Available fields for NM_SETTING_CONNECTION_SETTING_NAME */
-NmcOutputField nmc_fields_setting_connection[] = {
-	SETTING_FIELD ("name"),                                      /* 0 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_ID),                    /* 1 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_UUID),                  /* 2 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_STABLE_ID),             /* 3 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_INTERFACE_NAME),        /* 4 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_TYPE),                  /* 5 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT),           /* 6 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY),  /* 7 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES),   /* 8 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_TIMESTAMP),             /* 9 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_READ_ONLY),             /* 10 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_PERMISSIONS),           /* 11 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_ZONE),                  /* 12 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_MASTER),                /* 13 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_SLAVE_TYPE),            /* 14 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES),    /* 15 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_SECONDARIES),           /* 16 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT),  /* 17 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_METERED),               /* 18 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_LLDP),                  /* 19 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_CONNECTION_ALL     "name"","\
-                                              NM_SETTING_CONNECTION_ID","\
-                                              NM_SETTING_CONNECTION_UUID","\
-                                              NM_SETTING_CONNECTION_STABLE_ID","\
-                                              NM_SETTING_CONNECTION_INTERFACE_NAME","\
-                                              NM_SETTING_CONNECTION_TYPE","\
-                                              NM_SETTING_CONNECTION_AUTOCONNECT","\
-                                              NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY","\
-                                              NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES","\
-                                              NM_SETTING_CONNECTION_TIMESTAMP","\
-                                              NM_SETTING_CONNECTION_READ_ONLY","\
-                                              NM_SETTING_CONNECTION_PERMISSIONS","\
-                                              NM_SETTING_CONNECTION_ZONE","\
-                                              NM_SETTING_CONNECTION_MASTER","\
-                                              NM_SETTING_CONNECTION_SLAVE_TYPE","\
-                                              NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES","\
-                                              NM_SETTING_CONNECTION_SECONDARIES","\
-                                              NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT","\
-                                              NM_SETTING_CONNECTION_METERED","\
-                                              NM_SETTING_CONNECTION_LLDP
-
-/* Available fields for NM_SETTING_WIRED_SETTING_NAME */
-NmcOutputField nmc_fields_setting_wired[] = {
-	SETTING_FIELD ("name"),                                  /* 0 */
-	SETTING_FIELD (NM_SETTING_WIRED_PORT),                   /* 1 */
-	SETTING_FIELD (NM_SETTING_WIRED_SPEED),                  /* 2 */
-	SETTING_FIELD (NM_SETTING_WIRED_DUPLEX),                 /* 3 */
-	SETTING_FIELD (NM_SETTING_WIRED_AUTO_NEGOTIATE),         /* 4 */
-	SETTING_FIELD (NM_SETTING_WIRED_MAC_ADDRESS),            /* 5 */
-	SETTING_FIELD (NM_SETTING_WIRED_CLONED_MAC_ADDRESS),     /* 6 */
-	SETTING_FIELD (NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK), /* 7 */
-	SETTING_FIELD (NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST),  /* 8 */
-	SETTING_FIELD (NM_SETTING_WIRED_MTU),                    /* 9 */
-	SETTING_FIELD (NM_SETTING_WIRED_S390_SUBCHANNELS),       /* 10 */
-	SETTING_FIELD (NM_SETTING_WIRED_S390_NETTYPE),           /* 11 */
-	SETTING_FIELD (NM_SETTING_WIRED_S390_OPTIONS),           /* 12 */
-	SETTING_FIELD (NM_SETTING_WIRED_WAKE_ON_LAN),            /* 13 */
-	SETTING_FIELD (NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD),   /* 14 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_WIRED_ALL     "name"","\
-                                         NM_SETTING_WIRED_PORT","\
-                                         NM_SETTING_WIRED_SPEED","\
-                                         NM_SETTING_WIRED_DUPLEX","\
-                                         NM_SETTING_WIRED_AUTO_NEGOTIATE","\
-                                         NM_SETTING_WIRED_MAC_ADDRESS","\
-                                         NM_SETTING_WIRED_CLONED_MAC_ADDRESS","\
-                                         NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK","\
-                                         NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST","\
-                                         NM_SETTING_WIRED_MTU","\
-                                         NM_SETTING_WIRED_S390_SUBCHANNELS","\
-                                         NM_SETTING_WIRED_S390_NETTYPE","\
-                                         NM_SETTING_WIRED_S390_OPTIONS","\
-                                         NM_SETTING_WIRED_WAKE_ON_LAN","\
-                                         NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD
-
-/* Available fields for NM_SETTING_802_1X_SETTING_NAME */
-NmcOutputField nmc_fields_setting_8021X[] = {
-	SETTING_FIELD ("name"),                                               /* 0 */
-	SETTING_FIELD (NM_SETTING_802_1X_EAP),                                /* 1 */
-	SETTING_FIELD (NM_SETTING_802_1X_IDENTITY),                           /* 2 */
-	SETTING_FIELD (NM_SETTING_802_1X_ANONYMOUS_IDENTITY),                 /* 3 */
-	SETTING_FIELD (NM_SETTING_802_1X_PAC_FILE),                           /* 4 */
-	SETTING_FIELD (NM_SETTING_802_1X_CA_CERT),                            /* 5 */
-	SETTING_FIELD (NM_SETTING_802_1X_CA_CERT_PASSWORD),                   /* 6 */
-	SETTING_FIELD (NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS),             /* 7 */
-	SETTING_FIELD (NM_SETTING_802_1X_CA_PATH),                            /* 8 */
-	SETTING_FIELD (NM_SETTING_802_1X_SUBJECT_MATCH),                      /* 9 */
-	SETTING_FIELD (NM_SETTING_802_1X_ALTSUBJECT_MATCHES),                 /* 10 */
-	SETTING_FIELD (NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH),                /* 11 */
-	SETTING_FIELD (NM_SETTING_802_1X_CLIENT_CERT),                        /* 12 */
-	SETTING_FIELD (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD),               /* 13 */
-	SETTING_FIELD (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS),         /* 14 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE1_PEAPVER),                     /* 15 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE1_PEAPLABEL),                   /* 16 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING),           /* 17 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE1_AUTH_FLAGS),                  /* 18 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_AUTH),                        /* 19 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_AUTHEAP),                     /* 20 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD),            /* 21 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS),      /* 22 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_CA_CERT),                     /* 23 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_CA_PATH),                     /* 24 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH),               /* 25 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES),          /* 26 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH),         /* 27 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_CLIENT_CERT),                 /* 28 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD),        /* 29 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS),  /* 30 */
-	SETTING_FIELD (NM_SETTING_802_1X_PASSWORD),                           /* 31 */
-	SETTING_FIELD (NM_SETTING_802_1X_PASSWORD_FLAGS),                     /* 32 */
-	SETTING_FIELD (NM_SETTING_802_1X_PASSWORD_RAW),                       /* 33 */
-	SETTING_FIELD (NM_SETTING_802_1X_PASSWORD_RAW_FLAGS),                 /* 34 */
-	SETTING_FIELD (NM_SETTING_802_1X_PRIVATE_KEY),                        /* 35 */
-	SETTING_FIELD (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD),               /* 36 */
-	SETTING_FIELD (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS),         /* 37 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY),                 /* 38 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD),        /* 39 */
-	SETTING_FIELD (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS),  /* 40 */
-	SETTING_FIELD (NM_SETTING_802_1X_PIN),                                /* 41 */
-	SETTING_FIELD (NM_SETTING_802_1X_PIN_FLAGS),                          /* 42 */
-	SETTING_FIELD (NM_SETTING_802_1X_SYSTEM_CA_CERTS),                    /* 43 */
-	SETTING_FIELD (NM_SETTING_802_1X_AUTH_TIMEOUT),                       /* 44 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_802_1X_ALL     "name"","\
-                                          NM_SETTING_802_1X_EAP","\
-                                          NM_SETTING_802_1X_IDENTITY","\
-                                          NM_SETTING_802_1X_ANONYMOUS_IDENTITY","\
-                                          NM_SETTING_802_1X_PAC_FILE","\
-                                          NM_SETTING_802_1X_CA_CERT","\
-                                          NM_SETTING_802_1X_CA_CERT_PASSWORD","\
-                                          NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS","\
-                                          NM_SETTING_802_1X_CA_PATH","\
-                                          NM_SETTING_802_1X_SUBJECT_MATCH","\
-                                          NM_SETTING_802_1X_ALTSUBJECT_MATCHES","\
-                                          NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH","\
-                                          NM_SETTING_802_1X_CLIENT_CERT","\
-                                          NM_SETTING_802_1X_CLIENT_CERT_PASSWORD","\
-                                          NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS","\
-                                          NM_SETTING_802_1X_PHASE1_PEAPVER","\
-                                          NM_SETTING_802_1X_PHASE1_PEAPLABEL","\
-                                          NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING","\
-                                          NM_SETTING_802_1X_PHASE1_AUTH_FLAGS","\
-                                          NM_SETTING_802_1X_PHASE2_AUTH","\
-                                          NM_SETTING_802_1X_PHASE2_AUTHEAP","\
-                                          NM_SETTING_802_1X_PHASE2_CA_CERT","\
-                                          NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD","\
-                                          NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS","\
-                                          NM_SETTING_802_1X_PHASE2_CA_PATH","\
-                                          NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH","\
-                                          NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES","\
-                                          NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH","\
-                                          NM_SETTING_802_1X_PHASE2_CLIENT_CERT","\
-                                          NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD","\
-                                          NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS","\
-                                          NM_SETTING_802_1X_PASSWORD","\
-                                          NM_SETTING_802_1X_PASSWORD_FLAGS","\
-                                          NM_SETTING_802_1X_PASSWORD_RAW","\
-                                          NM_SETTING_802_1X_PASSWORD_RAW_FLAGS","\
-                                          NM_SETTING_802_1X_PRIVATE_KEY","\
-                                          NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD","\
-                                          NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS","\
-                                          NM_SETTING_802_1X_PHASE2_PRIVATE_KEY","\
-                                          NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD","\
-                                          NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS","\
-                                          NM_SETTING_802_1X_PIN","\
-                                          NM_SETTING_802_1X_PIN_FLAGS","\
-                                          NM_SETTING_802_1X_SYSTEM_CA_CERTS","\
-                                          NM_SETTING_802_1X_AUTH_TIMEOUT
-
-/* Available fields for NM_SETTING_WIRELESS_SETTING_NAME */
-NmcOutputField nmc_fields_setting_wireless[] = {
-	SETTING_FIELD ("name"),                                        /* 0 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SSID),                      /* 1 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_MODE),                      /* 2 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_BAND),                      /* 3 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_CHANNEL),                   /* 4 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_BSSID),                     /* 5 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_RATE),                      /* 6 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_TX_POWER),                  /* 7 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS),               /* 8 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS),        /* 9 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK), /* 10 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST),     /* 11 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION), /* 12 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_MTU),                       /* 13 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SEEN_BSSIDS),               /* 14 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_HIDDEN),                    /* 15 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_POWERSAVE),                 /* 16 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_WIRELESS_ALL     "name"","\
-                                            NM_SETTING_WIRELESS_SSID","\
-                                            NM_SETTING_WIRELESS_MODE","\
-                                            NM_SETTING_WIRELESS_BAND","\
-                                            NM_SETTING_WIRELESS_CHANNEL","\
-                                            NM_SETTING_WIRELESS_BSSID","\
-                                            NM_SETTING_WIRELESS_RATE","\
-                                            NM_SETTING_WIRELESS_TX_POWER","\
-                                            NM_SETTING_WIRELESS_MAC_ADDRESS","\
-                                            NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS","\
-                                            NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK","\
-                                            NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST","\
-                                            NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION","\
-                                            NM_SETTING_WIRELESS_MTU","\
-                                            NM_SETTING_WIRELESS_SEEN_BSSIDS","\
-                                            NM_SETTING_WIRELESS_HIDDEN"," \
-                                            NM_SETTING_WIRELESS_POWERSAVE
-
-/* Available fields for NM_SETTING_WIRELESS_SECURITY_SETTING_NAME */
-NmcOutputField nmc_fields_setting_wireless_security[] = {
-	SETTING_FIELD ("name"),                                            /* 0 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_KEY_MGMT),             /* 1 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX),        /* 2 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_AUTH_ALG),             /* 3 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_PROTO),                /* 4 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_PAIRWISE),             /* 5 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_GROUP),                /* 6 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME),        /* 7 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_WEP_KEY0),             /* 8 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_WEP_KEY1),             /* 9 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_WEP_KEY2),             /* 10 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_WEP_KEY3),             /* 11 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS),        /* 12 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE),         /* 13 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_PSK),                  /* 14 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS),            /* 15 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD),        /* 16 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS),  /* 17 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_WIRELESS_SECURITY_ALL     "name"","\
-                                                     NM_SETTING_WIRELESS_SECURITY_KEY_MGMT","\
-                                                     NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX","\
-                                                     NM_SETTING_WIRELESS_SECURITY_AUTH_ALG","\
-                                                     NM_SETTING_WIRELESS_SECURITY_PROTO","\
-                                                     NM_SETTING_WIRELESS_SECURITY_PAIRWISE","\
-                                                     NM_SETTING_WIRELESS_SECURITY_GROUP","\
-                                                     NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME","\
-                                                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY0","\
-                                                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY1","\
-                                                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY2","\
-                                                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY3","\
-                                                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS","\
-                                                     NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE","\
-                                                     NM_SETTING_WIRELESS_SECURITY_PSK","\
-                                                     NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS","\
-                                                     NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD","\
-                                                     NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS
-
-/* Available fields for NM_SETTING_IP4_CONFIG_SETTING_NAME */
-NmcOutputField nmc_fields_setting_ip4_config[] = {
-	SETTING_FIELD ("name"),                                   /* 0 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_METHOD),              /* 1 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS),                 /* 2 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_SEARCH),          /* 3 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_OPTIONS),         /* 4 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_PRIORITY),        /* 5 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_ADDRESSES),           /* 6 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_GATEWAY),             /* 7 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES),              /* 8 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTE_METRIC),        /* 9 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES),  /* 10 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS),     /* 11 */
-	SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID),     /* 12 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_TIMEOUT),        /* 13 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME),  /* 14 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME),       /* 15 */
-	SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_FQDN),          /* 16 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT),       /* 17 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL),            /* 18 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DAD_TIMEOUT),         /* 19 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_IP4_CONFIG_ALL     "name"","\
-                                              NM_SETTING_IP_CONFIG_METHOD","\
-                                              NM_SETTING_IP_CONFIG_DNS","\
-                                              NM_SETTING_IP_CONFIG_DNS_SEARCH","\
-                                              NM_SETTING_IP_CONFIG_DNS_OPTIONS","\
-                                              NM_SETTING_IP_CONFIG_DNS_PRIORITY","\
-                                              NM_SETTING_IP_CONFIG_ADDRESSES","\
-                                              NM_SETTING_IP_CONFIG_GATEWAY","\
-                                              NM_SETTING_IP_CONFIG_ROUTES","\
-                                              NM_SETTING_IP_CONFIG_ROUTE_METRIC","\
-                                              NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES","\
-                                              NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS","\
-                                              NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID","\
-                                              NM_SETTING_IP_CONFIG_DHCP_TIMEOUT","\
-                                              NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME","\
-                                              NM_SETTING_IP_CONFIG_DHCP_HOSTNAME","\
-                                              NM_SETTING_IP4_CONFIG_DHCP_FQDN","\
-                                              NM_SETTING_IP_CONFIG_NEVER_DEFAULT","\
-                                              NM_SETTING_IP_CONFIG_MAY_FAIL","\
-                                              NM_SETTING_IP_CONFIG_DAD_TIMEOUT
-
-/* Available fields for NM_SETTING_IP6_CONFIG_SETTING_NAME */
-NmcOutputField nmc_fields_setting_ip6_config[] = {
-	SETTING_FIELD ("name"),                                   /* 0 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_METHOD),              /* 1 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS),                 /* 2 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_SEARCH),          /* 3 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_OPTIONS),         /* 4 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_PRIORITY),        /* 5 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_ADDRESSES),           /* 6 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_GATEWAY),             /* 7 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES),              /* 8 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTE_METRIC),        /* 9 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES),  /* 10 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS),     /* 11 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT),       /* 12 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL),            /* 13 */
-	SETTING_FIELD (NM_SETTING_IP6_CONFIG_IP6_PRIVACY),        /* 14 */
-	SETTING_FIELD (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE),      /* 15 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME),  /* 16 */
-	SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME),       /* 17 */
-	SETTING_FIELD (NM_SETTING_IP6_CONFIG_TOKEN),              /* 18 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_IP6_CONFIG_ALL     "name"","\
-                                              NM_SETTING_IP_CONFIG_METHOD","\
-                                              NM_SETTING_IP_CONFIG_DNS","\
-                                              NM_SETTING_IP_CONFIG_DNS_SEARCH","\
-                                              NM_SETTING_IP_CONFIG_DNS_OPTIONS","\
-                                              NM_SETTING_IP_CONFIG_DNS_PRIORITY","\
-                                              NM_SETTING_IP_CONFIG_ADDRESSES","\
-                                              NM_SETTING_IP_CONFIG_GATEWAY","\
-                                              NM_SETTING_IP_CONFIG_ROUTES","\
-                                              NM_SETTING_IP_CONFIG_ROUTE_METRIC","\
-                                              NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES","\
-                                              NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS","\
-                                              NM_SETTING_IP_CONFIG_NEVER_DEFAULT","\
-                                              NM_SETTING_IP_CONFIG_MAY_FAIL","\
-                                              NM_SETTING_IP6_CONFIG_IP6_PRIVACY","\
-                                              NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE","\
-                                              NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME","\
-                                              NM_SETTING_IP_CONFIG_DHCP_HOSTNAME","\
-                                              NM_SETTING_IP6_CONFIG_TOKEN
-
-/* Available fields for NM_SETTING_SERIAL_SETTING_NAME */
-NmcOutputField nmc_fields_setting_serial[] = {
-	SETTING_FIELD ("name"),                        /* 0 */
-	SETTING_FIELD (NM_SETTING_SERIAL_BAUD),        /* 1 */
-	SETTING_FIELD (NM_SETTING_SERIAL_BITS),        /* 2 */
-	SETTING_FIELD (NM_SETTING_SERIAL_PARITY),      /* 3 */
-	SETTING_FIELD (NM_SETTING_SERIAL_STOPBITS),    /* 4 */
-	SETTING_FIELD (NM_SETTING_SERIAL_SEND_DELAY),  /* 5 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_SERIAL_ALL     "name"","\
-                                          NM_SETTING_SERIAL_BAUD","\
-                                          NM_SETTING_SERIAL_BITS","\
-                                          NM_SETTING_SERIAL_PARITY","\
-                                          NM_SETTING_SERIAL_STOPBITS","\
-                                          NM_SETTING_SERIAL_SEND_DELAY
-
-/* Available fields for NM_SETTING_PPP_SETTING_NAME */
-NmcOutputField nmc_fields_setting_ppp[] = {
-	SETTING_FIELD ("name"),                            /* 0 */
-	SETTING_FIELD (NM_SETTING_PPP_NOAUTH),             /* 1 */
-	SETTING_FIELD (NM_SETTING_PPP_REFUSE_EAP),         /* 2 */
-	SETTING_FIELD (NM_SETTING_PPP_REFUSE_PAP),         /* 3 */
-	SETTING_FIELD (NM_SETTING_PPP_REFUSE_CHAP),        /* 4 */
-	SETTING_FIELD (NM_SETTING_PPP_REFUSE_MSCHAP),      /* 5 */
-	SETTING_FIELD (NM_SETTING_PPP_REFUSE_MSCHAPV2),    /* 6 */
-	SETTING_FIELD (NM_SETTING_PPP_NOBSDCOMP),          /* 7 */
-	SETTING_FIELD (NM_SETTING_PPP_NODEFLATE),          /* 8 */
-	SETTING_FIELD (NM_SETTING_PPP_NO_VJ_COMP),         /* 9 */
-	SETTING_FIELD (NM_SETTING_PPP_REQUIRE_MPPE),       /* 10 */
-	SETTING_FIELD (NM_SETTING_PPP_REQUIRE_MPPE_128),   /* 11 */
-	SETTING_FIELD (NM_SETTING_PPP_MPPE_STATEFUL),      /* 12 */
-	SETTING_FIELD (NM_SETTING_PPP_CRTSCTS),            /* 13 */
-	SETTING_FIELD (NM_SETTING_PPP_BAUD),               /* 14 */
-	SETTING_FIELD (NM_SETTING_PPP_MRU),                /* 15 */
-	SETTING_FIELD (NM_SETTING_PPP_MTU),                /* 16 */
-	SETTING_FIELD (NM_SETTING_PPP_LCP_ECHO_FAILURE),   /* 17 */
-	SETTING_FIELD (NM_SETTING_PPP_LCP_ECHO_INTERVAL),  /* 18 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_PPP_ALL     "name"","\
-                                       NM_SETTING_PPP_NOAUTH","\
-                                       NM_SETTING_PPP_REFUSE_EAP","\
-                                       NM_SETTING_PPP_REFUSE_PAP","\
-                                       NM_SETTING_PPP_REFUSE_CHAP","\
-                                       NM_SETTING_PPP_REFUSE_MSCHAP","\
-                                       NM_SETTING_PPP_REFUSE_MSCHAPV2","\
-                                       NM_SETTING_PPP_NOBSDCOMP","\
-                                       NM_SETTING_PPP_NODEFLATE","\
-                                       NM_SETTING_PPP_NO_VJ_COMP","\
-                                       NM_SETTING_PPP_REQUIRE_MPPE","\
-                                       NM_SETTING_PPP_REQUIRE_MPPE_128","\
-                                       NM_SETTING_PPP_MPPE_STATEFUL","\
-                                       NM_SETTING_PPP_CRTSCTS","\
-                                       NM_SETTING_PPP_BAUD","\
-                                       NM_SETTING_PPP_MRU","\
-                                       NM_SETTING_PPP_MTU","\
-                                       NM_SETTING_PPP_LCP_ECHO_FAILURE","\
-                                       NM_SETTING_PPP_LCP_ECHO_INTERVAL
-
-/* Available fields for NM_SETTING_PPPOE_SETTING_NAME */
-NmcOutputField nmc_fields_setting_pppoe[] = {
-	SETTING_FIELD ("name"),                           /* 0 */
-	SETTING_FIELD (NM_SETTING_PPPOE_SERVICE),         /* 1 */
-	SETTING_FIELD (NM_SETTING_PPPOE_USERNAME),        /* 2 */
-	SETTING_FIELD (NM_SETTING_PPPOE_PASSWORD),        /* 3 */
-	SETTING_FIELD (NM_SETTING_PPPOE_PASSWORD_FLAGS),  /* 4 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_PPPOE_ALL     "name"","\
-                                         NM_SETTING_PPPOE_SERVICE","\
-                                         NM_SETTING_PPPOE_USERNAME","\
-                                         NM_SETTING_PPPOE_PASSWORD","\
-                                         NM_SETTING_PPPOE_PASSWORD_FLAGS
-
-/* Available fields for NM_SETTING_ADSL_SETTING_NAME */
-NmcOutputField nmc_fields_setting_adsl[] = {
-	SETTING_FIELD ("name"),                          /* 0 */
-	SETTING_FIELD (NM_SETTING_ADSL_USERNAME),        /* 1 */
-	SETTING_FIELD (NM_SETTING_ADSL_PASSWORD),        /* 2 */
-	SETTING_FIELD (NM_SETTING_ADSL_PASSWORD_FLAGS),  /* 3 */
-	SETTING_FIELD (NM_SETTING_ADSL_PROTOCOL),        /* 4 */
-	SETTING_FIELD (NM_SETTING_ADSL_ENCAPSULATION),   /* 5 */
-	SETTING_FIELD (NM_SETTING_ADSL_VPI),             /* 6 */
-	SETTING_FIELD (NM_SETTING_ADSL_VCI),             /* 7 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_ADSL_ALL     "name"","\
-                                        NM_SETTING_ADSL_USERNAME","\
-                                        NM_SETTING_ADSL_PASSWORD","\
-                                        NM_SETTING_ADSL_PASSWORD_FLAGS","\
-                                        NM_SETTING_ADSL_PROTOCOL","\
-                                        NM_SETTING_ADSL_ENCAPSULATION","\
-                                        NM_SETTING_ADSL_VPI","\
-                                        NM_SETTING_ADSL_VCI
-
-/* Available fields for NM_SETTING_GSM_SETTING_NAME */
-NmcOutputField nmc_fields_setting_gsm[] = {
-	SETTING_FIELD ("name"),                         /* 0 */
-	SETTING_FIELD (NM_SETTING_GSM_NUMBER),          /* 1 */
-	SETTING_FIELD (NM_SETTING_GSM_USERNAME),        /* 2 */
-	SETTING_FIELD (NM_SETTING_GSM_PASSWORD),        /* 3 */
-	SETTING_FIELD (NM_SETTING_GSM_PASSWORD_FLAGS),  /* 4 */
-	SETTING_FIELD (NM_SETTING_GSM_APN),             /* 5 */
-	SETTING_FIELD (NM_SETTING_GSM_NETWORK_ID),      /* 6 */
-	SETTING_FIELD (NM_SETTING_GSM_PIN),             /* 7 */
-	SETTING_FIELD (NM_SETTING_GSM_PIN_FLAGS),       /* 8 */
-	SETTING_FIELD (NM_SETTING_GSM_HOME_ONLY),       /* 9 */
-	SETTING_FIELD (NM_SETTING_GSM_DEVICE_ID),       /* 10 */
-	SETTING_FIELD (NM_SETTING_GSM_SIM_ID),          /* 11 */
-	SETTING_FIELD (NM_SETTING_GSM_SIM_OPERATOR_ID), /* 12 */
-	SETTING_FIELD (NM_SETTING_GSM_MTU),             /* 13 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_GSM_ALL     "name"","\
-                                       NM_SETTING_GSM_NUMBER","\
-                                       NM_SETTING_GSM_USERNAME","\
-                                       NM_SETTING_GSM_PASSWORD","\
-                                       NM_SETTING_GSM_PASSWORD_FLAGS","\
-                                       NM_SETTING_GSM_APN","\
-                                       NM_SETTING_GSM_NETWORK_ID","\
-                                       NM_SETTING_GSM_PIN","\
-                                       NM_SETTING_GSM_PIN_FLAGS","\
-                                       NM_SETTING_GSM_HOME_ONLY","\
-                                       NM_SETTING_GSM_DEVICE_ID","\
-                                       NM_SETTING_GSM_SIM_ID","\
-                                       NM_SETTING_GSM_SIM_OPERATOR_ID","\
-                                       NM_SETTING_GSM_MTU
-
-/* Available fields for NM_SETTING_CDMA_SETTING_NAME */
-NmcOutputField nmc_fields_setting_cdma[] = {
-	SETTING_FIELD ("name"),                          /* 0 */
-	SETTING_FIELD (NM_SETTING_CDMA_NUMBER),          /* 1 */
-	SETTING_FIELD (NM_SETTING_CDMA_USERNAME),        /* 2 */
-	SETTING_FIELD (NM_SETTING_CDMA_PASSWORD),        /* 3 */
-	SETTING_FIELD (NM_SETTING_CDMA_PASSWORD_FLAGS),  /* 4 */
-	SETTING_FIELD (NM_SETTING_CDMA_MTU),             /* 5 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_CDMA_ALL     "name"","\
-                                        NM_SETTING_CDMA_NUMBER","\
-                                        NM_SETTING_CDMA_USERNAME","\
-                                        NM_SETTING_CDMA_PASSWORD","\
-                                        NM_SETTING_CDMA_PASSWORD_FLAGS","\
-                                        NM_SETTING_CDMA_MTU
-
-/* Available fields for NM_SETTING_BLUETOOTH_SETTING_NAME */
-NmcOutputField nmc_fields_setting_bluetooth[] = {
-	SETTING_FIELD ("name"),                       /* 0 */
-	SETTING_FIELD (NM_SETTING_BLUETOOTH_BDADDR),  /* 1 */
-	SETTING_FIELD (NM_SETTING_BLUETOOTH_TYPE),    /* 2 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_BLUETOOTH_ALL     "name"","\
-                                             NM_SETTING_BLUETOOTH_BDADDR","\
-                                             NM_SETTING_BLUETOOTH_TYPE
-
-/* Available fields for NM_SETTING_OLPC_MESH_SETTING_NAME */
-NmcOutputField nmc_fields_setting_olpc_mesh[] = {
-	SETTING_FIELD ("name"),                                     /* 0 */
-	SETTING_FIELD (NM_SETTING_OLPC_MESH_SSID),                  /* 1 */
-	SETTING_FIELD (NM_SETTING_OLPC_MESH_CHANNEL),               /* 2 */
-	SETTING_FIELD (NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS),  /* 3 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_OLPC_MESH_ALL     "name"","\
-                                             NM_SETTING_OLPC_MESH_SSID","\
-                                             NM_SETTING_OLPC_MESH_CHANNEL","\
-                                             NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS
-
-/* Available fields for NM_SETTING_VPN_SETTING_NAME */
-NmcOutputField nmc_fields_setting_vpn[] = {
-	SETTING_FIELD ("name"),                       /* 0 */
-	SETTING_FIELD (NM_SETTING_VPN_SERVICE_TYPE),  /* 1 */
-	SETTING_FIELD (NM_SETTING_VPN_USER_NAME),     /* 2 */
-	SETTING_FIELD (NM_SETTING_VPN_DATA),          /* 3 */
-	SETTING_FIELD (NM_SETTING_VPN_SECRETS),       /* 4 */
-	SETTING_FIELD (NM_SETTING_VPN_PERSISTENT),    /* 5 */
-	SETTING_FIELD (NM_SETTING_VPN_TIMEOUT),       /* 6 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_VPN_ALL     "name"","\
-                                       NM_SETTING_VPN_SERVICE_TYPE","\
-                                       NM_SETTING_VPN_USER_NAME","\
-                                       NM_SETTING_VPN_DATA","\
-                                       NM_SETTING_VPN_SECRETS","\
-                                       NM_SETTING_VPN_PERSISTENT","\
-                                       NM_SETTING_VPN_TIMEOUT
-
-/* Available fields for NM_SETTING_WIMAX_SETTING_NAME */
-NmcOutputField nmc_fields_setting_wimax[] = {
-	SETTING_FIELD ("name"),                         /* 0 */
-	SETTING_FIELD (NM_SETTING_WIMAX_MAC_ADDRESS),   /* 1 */
-	SETTING_FIELD (NM_SETTING_WIMAX_NETWORK_NAME),  /* 2 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_WIMAX_ALL     "name"","\
-                                         NM_SETTING_WIMAX_MAC_ADDRESS","\
-                                         NM_SETTING_WIMAX_NETWORK_NAME
-
-/* Available fields for NM_SETTING_INFINIBAND_SETTING_NAME */
-NmcOutputField nmc_fields_setting_infiniband[] = {
-	SETTING_FIELD ("name"),                                /* 0 */
-	SETTING_FIELD (NM_SETTING_INFINIBAND_MAC_ADDRESS),     /* 1 */
-	SETTING_FIELD (NM_SETTING_INFINIBAND_MTU),             /* 2 */
-	SETTING_FIELD (NM_SETTING_INFINIBAND_TRANSPORT_MODE),  /* 3 */
-	SETTING_FIELD (NM_SETTING_INFINIBAND_P_KEY),           /* 4 */
-	SETTING_FIELD (NM_SETTING_INFINIBAND_PARENT),          /* 5 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_INFINIBAND_ALL     "name"","\
-                                              NM_SETTING_INFINIBAND_MAC_ADDRESS","\
-                                              NM_SETTING_INFINIBAND_MTU"," \
-                                              NM_SETTING_INFINIBAND_TRANSPORT_MODE"," \
-                                              NM_SETTING_INFINIBAND_P_KEY"," \
-                                              NM_SETTING_INFINIBAND_PARENT
-
-/* Available fields for NM_SETTING_BOND_SETTING_NAME */
-NmcOutputField nmc_fields_setting_bond[] = {
-	SETTING_FIELD ("name"),                   /* 0 */
-	SETTING_FIELD (NM_SETTING_BOND_OPTIONS),  /* 1 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_BOND_ALL     "name"","\
-                                        NM_SETTING_BOND_OPTIONS
-
-/* Available fields for NM_SETTING_VLAN_SETTING_NAME */
-NmcOutputField nmc_fields_setting_vlan[] = {
-	SETTING_FIELD ("name"),                                /* 0 */
-	SETTING_FIELD (NM_SETTING_VLAN_PARENT),                /* 1 */
-	SETTING_FIELD (NM_SETTING_VLAN_ID),                    /* 2 */
-	SETTING_FIELD (NM_SETTING_VLAN_FLAGS),                 /* 3 */
-	SETTING_FIELD (NM_SETTING_VLAN_INGRESS_PRIORITY_MAP),  /* 4 */
-	SETTING_FIELD (NM_SETTING_VLAN_EGRESS_PRIORITY_MAP),   /* 5 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_VLAN_ALL     "name"","\
-                                        NM_SETTING_VLAN_PARENT","\
-                                        NM_SETTING_VLAN_ID","\
-                                        NM_SETTING_VLAN_FLAGS","\
-                                        NM_SETTING_VLAN_INGRESS_PRIORITY_MAP","\
-                                        NM_SETTING_VLAN_EGRESS_PRIORITY_MAP
-
-/* Available fields for NM_SETTING_BRIDGE_SETTING_NAME */
-NmcOutputField nmc_fields_setting_bridge[] = {
-	SETTING_FIELD ("name"),                                /* 0 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_MAC_ADDRESS),         /* 1 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_STP),                 /* 2 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_PRIORITY),            /* 3 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_FORWARD_DELAY),       /* 4 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_HELLO_TIME),          /* 5 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_MAX_AGE),             /* 6 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_AGEING_TIME),         /* 7 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_MULTICAST_SNOOPING),  /* 8 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_BRIDGE_ALL    "name"","\
-                                         NM_SETTING_BRIDGE_MAC_ADDRESS","\
-                                         NM_SETTING_BRIDGE_STP","\
-                                         NM_SETTING_BRIDGE_PRIORITY","\
-                                         NM_SETTING_BRIDGE_FORWARD_DELAY","\
-                                         NM_SETTING_BRIDGE_HELLO_TIME","\
-                                         NM_SETTING_BRIDGE_MAX_AGE","\
-                                         NM_SETTING_BRIDGE_AGEING_TIME","\
-                                         NM_SETTING_BRIDGE_MULTICAST_SNOOPING
-
-/* Available fields for NM_SETTING_BRIDGE_PORT_SETTING_NAME */
-NmcOutputField nmc_fields_setting_bridge_port[] = {
-	SETTING_FIELD ("name"),                               /* 0 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_PORT_PRIORITY),      /* 1 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_PORT_PATH_COST),     /* 2 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE),  /* 3 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_BRIDGE_PORT_ALL    "name"","\
-                                              NM_SETTING_BRIDGE_PORT_PRIORITY","\
-                                              NM_SETTING_BRIDGE_PORT_PATH_COST","\
-                                              NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE
-
-/* Available fields for NM_SETTING_TEAM_SETTING_NAME */
-NmcOutputField nmc_fields_setting_team[] = {
-	SETTING_FIELD ("name"),                  /* 0 */
-	SETTING_FIELD (NM_SETTING_TEAM_CONFIG),  /* 1 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_TEAM_ALL     "name"","\
-                                        NM_SETTING_TEAM_CONFIG
-
-/* Available fields for NM_SETTING_TEAM_PORT_SETTING_NAME */
-NmcOutputField nmc_fields_setting_team_port[] = {
-	SETTING_FIELD ("name"),                       /* 0 */
-	SETTING_FIELD (NM_SETTING_TEAM_PORT_CONFIG),  /* 1 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_TEAM_PORT_ALL     "name"","\
-                                             NM_SETTING_TEAM_PORT_CONFIG
-
-/* Available fields for NM_SETTING_DCB_SETTING_NAME */
-NmcOutputField nmc_fields_setting_dcb[] = {
-	SETTING_FIELD ("name"),                                      /* 0 */
-	SETTING_FIELD (NM_SETTING_DCB_APP_FCOE_FLAGS),               /* 1 */
-	SETTING_FIELD (NM_SETTING_DCB_APP_FCOE_PRIORITY),            /* 2 */
-	SETTING_FIELD (NM_SETTING_DCB_APP_FCOE_MODE),                /* 3 */
-	SETTING_FIELD (NM_SETTING_DCB_APP_ISCSI_FLAGS),              /* 4 */
-	SETTING_FIELD (NM_SETTING_DCB_APP_ISCSI_PRIORITY),           /* 5 */
-	SETTING_FIELD (NM_SETTING_DCB_APP_FIP_FLAGS),                /* 6 */
-	SETTING_FIELD (NM_SETTING_DCB_APP_FIP_PRIORITY),             /* 7 */
-	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS),  /* 8 */
-	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL),        /* 9 */
-	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS),         /* 10 */
-	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_GROUP_ID),            /* 11 */
-	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH),     /* 12 */
-	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_BANDWIDTH),           /* 13 */
-	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH),    /* 14 */
-	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS),       /* 15 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_DCB_ALL     "name"","\
-                                       NM_SETTING_DCB_APP_FCOE_FLAGS","\
-                                       NM_SETTING_DCB_APP_FCOE_PRIORITY","\
-                                       NM_SETTING_DCB_APP_FCOE_MODE","\
-                                       NM_SETTING_DCB_APP_ISCSI_FLAGS","\
-                                       NM_SETTING_DCB_APP_ISCSI_PRIORITY","\
-                                       NM_SETTING_DCB_APP_FIP_FLAGS","\
-                                       NM_SETTING_DCB_APP_FIP_PRIORITY","\
-                                       NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS","\
-                                       NM_SETTING_DCB_PRIORITY_FLOW_CONTROL","\
-                                       NM_SETTING_DCB_PRIORITY_GROUP_FLAGS","\
-                                       NM_SETTING_DCB_PRIORITY_GROUP_ID","\
-                                       NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH","\
-                                       NM_SETTING_DCB_PRIORITY_BANDWIDTH","\
-                                       NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH","\
-                                       NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS
-
-/* Available fields for NM_SETTING_DUMMY_SETTING_NAME */
-NmcOutputField nmc_fields_setting_dummy[] = {
-	SETTING_FIELD ("name"),                                /* 0 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_DUMMY_ALL       "name"
-
-/* Available fields for NM_SETTING_TUN_SETTING_NAME */
-NmcOutputField nmc_fields_setting_tun[] = {
-	SETTING_FIELD ("name"),                                /* 0 */
-	SETTING_FIELD (NM_SETTING_TUN_MODE),                   /* 1 */
-	SETTING_FIELD (NM_SETTING_TUN_OWNER),                  /* 2 */
-	SETTING_FIELD (NM_SETTING_TUN_GROUP),                  /* 3 */
-	SETTING_FIELD (NM_SETTING_TUN_PI),                     /* 4 */
-	SETTING_FIELD (NM_SETTING_TUN_VNET_HDR),               /* 5 */
-	SETTING_FIELD (NM_SETTING_TUN_MULTI_QUEUE),            /* 6 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_TUN_ALL     "name"","\
-                                       NM_SETTING_TUN_MODE","\
-                                       NM_SETTING_TUN_OWNER","\
-                                       NM_SETTING_TUN_GROUP","\
-                                       NM_SETTING_TUN_PI","\
-                                       NM_SETTING_TUN_VNET_HDR","\
-                                       NM_SETTING_TUN_MULTI_QUEUE
-
-/* Available fields for NM_SETTING_IP_TUNNEL_SETTING_NAME */
-NmcOutputField nmc_fields_setting_ip_tunnel[] = {
-	SETTING_FIELD ("name"),                                       /* 0 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_MODE),                    /* 1 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_PARENT),                  /* 2 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_LOCAL),                   /* 3 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_REMOTE),                  /* 4 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_TTL),                     /* 5 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_TOS),                     /* 6 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY),      /* 7 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_INPUT_KEY),               /* 8 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_OUTPUT_KEY),              /* 9 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT),     /* 10 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_FLOW_LABEL),              /* 11 */
-	SETTING_FIELD (NM_SETTING_IP_TUNNEL_MTU),                     /* 12 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_IP_TUNNEL_ALL     "name"","\
-                                              NM_SETTING_IP_TUNNEL_MODE","\
-                                              NM_SETTING_IP_TUNNEL_PARENT","\
-                                              NM_SETTING_IP_TUNNEL_LOCAL","\
-                                              NM_SETTING_IP_TUNNEL_REMOTE","\
-                                              NM_SETTING_IP_TUNNEL_TTL","\
-                                              NM_SETTING_IP_TUNNEL_TOS","\
-                                              NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY","\
-                                              NM_SETTING_IP_TUNNEL_INPUT_KEY","\
-                                              NM_SETTING_IP_TUNNEL_OUTPUT_KEY","\
-                                              NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT","\
-                                              NM_SETTING_IP_TUNNEL_FLOW_LABEL","\
-                                              NM_SETTING_IP_TUNNEL_MTU
-
-/* Available fields for NM_SETTING_MACSEC_SETTING_NAME */
-NmcOutputField nmc_fields_setting_macsec[] = {
-	SETTING_FIELD ("name"),                                 /* 0 */
-	SETTING_FIELD (NM_SETTING_MACSEC_PARENT),               /* 1 */
-	SETTING_FIELD (NM_SETTING_MACSEC_MODE),                 /* 2 */
-	SETTING_FIELD (NM_SETTING_MACSEC_ENCRYPT),              /* 3 */
-	SETTING_FIELD (NM_SETTING_MACSEC_MKA_CAK),              /* 4 */
-	SETTING_FIELD (NM_SETTING_MACSEC_MKA_CAK_FLAGS),        /* 5 */
-	SETTING_FIELD (NM_SETTING_MACSEC_MKA_CKN),              /* 6 */
-	SETTING_FIELD (NM_SETTING_MACSEC_PORT),                 /* 7 */
-	SETTING_FIELD (NM_SETTING_MACSEC_VALIDATION),           /* 8 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_MACSEC_ALL     "name"","\
-                                           NM_SETTING_MACSEC_PARENT","\
-                                           NM_SETTING_MACSEC_MODE","\
-                                           NM_SETTING_MACSEC_ENCRYPT","\
-                                           NM_SETTING_MACSEC_MKA_CAK","\
-                                           NM_SETTING_MACSEC_MKA_CAK_FLAGS","\
-                                           NM_SETTING_MACSEC_MKA_CKN","\
-                                           NM_SETTING_MACSEC_PORT","\
-                                           NM_SETTING_MACSEC_VALIDATION
-
-/* Available fields for NM_SETTING_MACVLAN_SETTING_NAME */
-NmcOutputField nmc_fields_setting_macvlan[] = {
-	SETTING_FIELD ("name"),                                 /* 0 */
-	SETTING_FIELD (NM_SETTING_MACVLAN_PARENT),              /* 1 */
-	SETTING_FIELD (NM_SETTING_MACVLAN_MODE),                /* 2 */
-	SETTING_FIELD (NM_SETTING_MACVLAN_PROMISCUOUS),         /* 3 */
-	SETTING_FIELD (NM_SETTING_MACVLAN_TAP),                 /* 4 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_MACVLAN_ALL     "name"","\
-                                           NM_SETTING_MACVLAN_PARENT","\
-                                           NM_SETTING_MACVLAN_MODE","\
-                                           NM_SETTING_MACVLAN_PROMISCUOUS","\
-                                           NM_SETTING_MACVLAN_TAP
-
-/* Available fields for NM_SETTING_VXLAN_SETTING_NAME */
-NmcOutputField nmc_fields_setting_vxlan[] = {
-	SETTING_FIELD ("name"),                            /* 0 */
-	SETTING_FIELD (NM_SETTING_VXLAN_PARENT),           /* 1 */
-	SETTING_FIELD (NM_SETTING_VXLAN_ID),               /* 2 */
-	SETTING_FIELD (NM_SETTING_VXLAN_LOCAL),            /* 3 */
-	SETTING_FIELD (NM_SETTING_VXLAN_REMOTE),           /* 4 */
-	SETTING_FIELD (NM_SETTING_VXLAN_SOURCE_PORT_MIN),  /* 5 */
-	SETTING_FIELD (NM_SETTING_VXLAN_SOURCE_PORT_MAX),  /* 6 */
-	SETTING_FIELD (NM_SETTING_VXLAN_DESTINATION_PORT), /* 7 */
-	SETTING_FIELD (NM_SETTING_VXLAN_TOS),              /* 8 */
-	SETTING_FIELD (NM_SETTING_VXLAN_TTL),              /* 9 */
-	SETTING_FIELD (NM_SETTING_VXLAN_AGEING),           /* 10 */
-	SETTING_FIELD (NM_SETTING_VXLAN_LIMIT),            /* 11 */
-	SETTING_FIELD (NM_SETTING_VXLAN_LEARNING),         /* 12 */
-	SETTING_FIELD (NM_SETTING_VXLAN_PROXY),            /* 13 */
-	SETTING_FIELD (NM_SETTING_VXLAN_RSC),              /* 14 */
-	SETTING_FIELD (NM_SETTING_VXLAN_L2_MISS),          /* 15 */
-	SETTING_FIELD (NM_SETTING_VXLAN_L3_MISS),          /* 16 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_VXLAN_ALL         "name"","\
-                                             NM_SETTING_VXLAN_PARENT","\
-                                             NM_SETTING_VXLAN_ID","\
-                                             NM_SETTING_VXLAN_LOCAL","\
-                                             NM_SETTING_VXLAN_REMOTE","\
-                                             NM_SETTING_VXLAN_SOURCE_PORT_MIN","\
-                                             NM_SETTING_VXLAN_SOURCE_PORT_MAX","\
-                                             NM_SETTING_VXLAN_DESTINATION_PORT","\
-                                             NM_SETTING_VXLAN_TOS","\
-                                             NM_SETTING_VXLAN_TTL","\
-                                             NM_SETTING_VXLAN_AGEING","\
-                                             NM_SETTING_VXLAN_LIMIT","\
-                                             NM_SETTING_VXLAN_LEARNING","\
-                                             NM_SETTING_VXLAN_PROXY","\
-                                             NM_SETTING_VXLAN_RSC","\
-                                             NM_SETTING_VXLAN_L2_MISS","\
-                                             NM_SETTING_VXLAN_L3_MISS
-
-/* Available fields for NM_SETTING_PROXY_SETTING_NAME */
-NmcOutputField nmc_fields_setting_proxy[] = {
-	SETTING_FIELD ("name"),                            /* 0 */
-	SETTING_FIELD (NM_SETTING_PROXY_METHOD),           /* 1 */
-	SETTING_FIELD (NM_SETTING_PROXY_BROWSER_ONLY),     /* 2 */
-	SETTING_FIELD (NM_SETTING_PROXY_PAC_URL),          /* 3 */
-	SETTING_FIELD (NM_SETTING_PROXY_PAC_SCRIPT),       /* 4 */
-	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
-};
-#define NMC_FIELDS_SETTING_PROXY_ALL         "name"","\
-                                             NM_SETTING_PROXY_METHOD","\
-                                             NM_SETTING_PROXY_BROWSER_ONLY","\
-                                             NM_SETTING_PROXY_PAC_URL","\
-                                             NM_SETTING_PROXY_PAC_SCRIPT
-/*----------------------------------------------------------------------------*/
-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, NmcPropertyGetType get_type)
-{
-	GString *flag_str;
-
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		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, NmcPropertyGetType get_type)
-{
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		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 *
-autoconnect_slaves_to_string (NMSettingConnectionAutoconnectSlaves autoconnect_slaves,
-                              NmcPropertyGetType get_type)
-{
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		return g_strdup_printf ("%d", autoconnect_slaves);
-
-	switch (autoconnect_slaves) {
-	case NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO:
-		return g_strdup_printf (_("%d (no)"), autoconnect_slaves);
-	case NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES:
-		return g_strdup_printf (_("%d (yes)"), autoconnect_slaves);
-	case NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT:
-	default:
-		return g_strdup_printf (_("%d (default)"), autoconnect_slaves);
-	}
-}
-
-static char *
-secret_flags_to_string (guint32 flags, NmcPropertyGetType get_type)
-{
-	GString *flag_str;
-
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		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);
-}
-
-
-/*  generic helper macros for property functions */
-#define DEFINE_GETTER(func_name, property_name) \
-	static char * \
-	func_name (NMSetting *setting, NmcPropertyGetType get_type) \
-	{ \
-		char *s; \
-		GValue val = G_VALUE_INIT; \
-		g_value_init (&val, G_TYPE_STRING); \
-		g_object_get_property (G_OBJECT (setting), property_name, &val); \
-		s = g_value_dup_string (&val); \
-		g_value_unset (&val); \
-		return s; \
-	}
-
-#define DEFINE_GETTER_WITH_DEFAULT(func_name, property_name, check_is_default) \
-	static char * \
-	func_name (NMSetting *setting, NmcPropertyGetType get_type) \
-	{ \
-		const char *s; \
-		char *s_full; \
-		GValue val = G_VALUE_INIT; \
-		\
-		if ((check_is_default)) { \
-			if (get_type == NMC_PROPERTY_GET_PARSABLE) \
-				return g_strdup (""); \
-			return g_strdup (_("(default)")); \
-		} \
-		\
-		g_value_init (&val, G_TYPE_STRING); \
-		g_object_get_property (G_OBJECT (setting), property_name, &val); \
-		s = g_value_get_string (&val); \
-		if (get_type == NMC_PROPERTY_GET_PARSABLE) \
-			s_full = g_strdup (s && *s ? s : " "); \
-		else \
-			s_full = s ? g_strdup_printf ("\"%s\"", s) : g_strdup (""); \
-		g_value_unset (&val); \
-		return s_full; \
-	}
-
-#define DEFINE_SECRET_FLAGS_GETTER(func_name, property_name) \
-	static char * \
-	func_name (NMSetting *setting, NmcPropertyGetType get_type) \
-	{ \
-		guint v; \
-		GValue val = G_VALUE_INIT; \
-		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 secret_flags_to_string (v, get_type); \
-	}
-
-#define DEFINE_SETTER_STR_LIST_MULTI(def_func, s_macro, set_func) \
-	static gboolean \
-	def_func (NMSetting *setting, \
-	          const char *prop, \
-	          const char *val, \
-	          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 (val, " \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 (NMSetting *setting, const char *prop, const char *val, GError **error) \
-	{ \
-		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 (val, ",", 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(def_func, s_macro, num_func, rem_func) \
-	static gboolean \
-	def_func (NMSetting *setting, const char *prop, const char *option, guint32 idx, GError **error) \
-	{ \
-		guint32 num; \
-		if (option) { \
-			g_set_error (error, 1, 0, _("index '%s' is not valid"), option); \
-			return FALSE; \
-		} \
-		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 (s_macro (setting), idx); \
-		return TRUE; \
-	}
-
-#define DEFINE_REMOVER_INDEX_OR_VALUE(def_func, s_macro, num_func, rem_func_idx, rem_func_val) \
-	static gboolean \
-	def_func (NMSetting *setting, const char *prop, const char *value, guint32 idx, GError **error) \
-	{ \
-		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 (NMSetting *setting, const char *prop, const char *option, guint32 idx, GError **error) \
-	{ \
-		gboolean success = FALSE; \
-		if (option && *option) { \
-			success = rem_func (s_macro (setting), option); \
-			if (!success) \
-				g_set_error (error, 1, 0, _("invalid option '%s'"), option); \
-		} else \
-			g_set_error_literal (error, 1, 0, _("missing option")); \
-		return success; \
-	}
-
-#define DEFINE_ALLOWED_VAL_FUNC(def_func, valid_values) \
-	static const char ** \
-	def_func (NMSetting *setting, const char *prop) \
-	{ \
-		return valid_values; \
-	}
-
-#define DEFINE_ALLOWED_FOR_ENUMS(def_func, get_type_func, min, max) \
-	static const char ** \
-	def_func (NMSetting *setting, const char *prop) \
-	{ \
-		static const char **words = NULL; \
-		if (G_UNLIKELY (!words)) \
-			words = nm_utils_enum_get_values (get_type_func(), min, max); \
-		return words; \
-	}
-
-#define DEFINE_SETTER_MAC_BLACKLIST(def_func, s_macro, add_func) \
-	static gboolean \
-	def_func (NMSetting *setting, const char *prop, const char *val, GError **error) \
-	{ \
-		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 (val, " \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;
-}
-
-/* Validate 'val' number against to int property spec */
-static gboolean
-validate_int (NMSetting *setting, const char* prop, gint val, GError **error)
-{
-	GParamSpec *pspec;
-	GValue value = G_VALUE_INIT;
-	gboolean success = TRUE;
-
-	g_value_init (&value, G_TYPE_INT);
-	g_value_set_int (&value, val);
-	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), prop);
-	g_assert (G_IS_PARAM_SPEC (pspec));
-	if (g_param_value_validate (pspec, &value)) {
-		GParamSpecInt *pspec_int = (GParamSpecInt *) pspec;
-		g_set_error (error, 1, 0, _("'%d' is not valid; use <%d-%d>"),
-		             val, pspec_int->minimum, pspec_int->maximum);
-		success = FALSE;
-	}
-	g_value_unset (&value);
-	return success;
-}
-
-static gboolean
-validate_int64 (NMSetting *setting, const char* prop, gint64 val, GError **error)
-{
-	GParamSpec *pspec;
-	GValue value = G_VALUE_INIT;
-	gboolean success = TRUE;
-
-	g_value_init (&value, G_TYPE_INT64);
-	g_value_set_int64 (&value, val);
-	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), prop);
-	g_assert (G_IS_PARAM_SPEC (pspec));
-	if (g_param_value_validate (pspec, &value)) {
-		GParamSpecInt64 *pspec_int = (GParamSpecInt64 *) pspec;
-		G_STATIC_ASSERT (sizeof (long long) >= sizeof (gint64));
-		g_set_error (error, 1, 0, _("'%lld' is not valid; use <%lld-%lld>"),
-		             (long long) val, (long long) pspec_int->minimum, (long long) pspec_int->maximum);
-		success = FALSE;
-	}
-	g_value_unset (&value);
-	return success;
-}
-
-/* Validate 'val' number against to uint property spec */
-static gboolean
-validate_uint (NMSetting *setting, const char* prop, guint val, GError **error)
-{
-	GParamSpec *pspec;
-	GValue value = G_VALUE_INIT;
-	gboolean success = TRUE;
-
-	g_value_init (&value, G_TYPE_UINT);
-	g_value_set_uint (&value, val);
-	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), prop);
-	g_assert (G_IS_PARAM_SPEC (pspec));
-	if (g_param_value_validate (pspec, &value)) {
-		GParamSpecUInt *pspec_uint = (GParamSpecUInt *) pspec;
-		g_set_error (error, 1, 0, _("'%u' is not valid; use <%u-%u>"),
-		             val, pspec_uint->minimum, pspec_uint->maximum);
-		success = FALSE;
-	}
-	g_value_unset (&value);
-	return success;
-}
-
-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;
-}
-
-/* --- generic property setter functions --- */
-static gboolean
-nmc_property_set_string (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	g_object_set (setting, prop, val, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_set_uint (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	unsigned long val_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_uint (val, TRUE, 0, G_MAXUINT, &val_int)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid number (or out of range)"), val);
-		return FALSE;
-	}
-
-	/* Validate the number according to the property spec */
-	if (!validate_uint (setting, prop, (guint) val_int, error))
-		return FALSE;
-
-	g_object_set (setting, prop, (guint) val_int, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_set_int (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	long int val_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_int (val, TRUE, G_MININT, G_MAXINT, &val_int)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid number (or out of range)"), val);
-		return FALSE;
-	}
-
-	/* Validate the number according to the property spec */
-	if (!validate_int (setting, prop, (gint) val_int, error))
-		return FALSE;
-
-	g_object_set (setting, prop, (gint) val_int, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_set_int64 (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	long val_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_int (val, FALSE, 0, 0, &val_int)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid number (or out of range)"), val);
-		return FALSE;
-	}
-
-	/* Validate the number according to the property spec */
-	if (!validate_int64 (setting, prop, (gint64) val_int, error))
-		return FALSE;
-
-	g_object_set (setting, prop, (gint64) val_int, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_set_flags (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	unsigned long val_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_uint (val, TRUE, 0, G_MAXUINT, &val_int)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid number (or out of range)"), val);
-		return FALSE;
-	}
-
-	/* Validate the flags according to the property spec */
-	if (!validate_flags (setting, prop, (guint) val_int, error))
-		return FALSE;
-
-	g_object_set (setting, prop, (guint) val_int, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_set_bool (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	gboolean val_bool;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_bool (val, &val_bool, error))
-		return FALSE;
-
-	g_object_set (setting, prop, val_bool, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_set_trilean (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	long int val_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_int (val, TRUE, -1, 1, &val_int)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid value; use -1, 0 or 1"), val);
-		return FALSE;
-	}
-
-	g_object_set (setting, prop, val_int, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_set_ssid (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	GBytes *ssid;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (strlen (val) > 32) {
-		g_set_error (error, 1, 0, _("'%s' is not valid"), val);
-		return FALSE;
-	}
-
-	ssid = g_bytes_new (val, strlen (val));
-	g_object_set (setting, prop, ssid, NULL);
-	g_bytes_unref (ssid);
-	return TRUE;
-}
-
-static gboolean
-_property_set_mac (NMSetting *setting, const char *prop, const char *val, gboolean cloned_mac_addr, GError **error)
-{
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (   (!cloned_mac_addr || !NM_CLONED_MAC_IS_SPECIAL (val))
-	    && !nm_utils_hwaddr_valid (val, ETH_ALEN)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid Ethernet MAC"), val);
-		return FALSE;
-	}
-
-	g_object_set (setting, prop, val, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_set_mac (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return _property_set_mac (setting, prop, val, FALSE, error);
-}
-
-static gboolean
-nmc_property_set_mac_cloned (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return _property_set_mac (setting, prop, val, TRUE, error);
-}
-
-static gboolean
-nmc_property_set_mtu (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	const char *mtu = val;
-
-	if (strcmp (mtu, "auto") == 0)
-		mtu = "0";
-
-	return nmc_property_set_uint (setting, prop, mtu, error);
-}
-
-static gboolean
-nmc_property_set_ifname (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nm_utils_is_valid_iface_name (val, error))
-		return FALSE;
-	g_object_set (setting, prop, val, NULL);
-	return TRUE;
-}
-
-#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 gboolean
-nmc_property_set_secret_flags (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL, **iter;
-	unsigned long flags = 0, val_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, " \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;
-		g_print (_("Warning: '%s' sum is higher than all flags => all flags set\n"), val);
-	}
-
-	g_object_set (setting, prop, (guint) flags, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_set_vpn_service (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	gs_free char *service_name = NULL;
-
-	service_name = nm_vpn_plugin_info_list_find_service_type (nm_vpn_get_plugin_infos (), val);
-	g_object_set (setting, prop, service_name ? : val, NULL);
-	return TRUE;
-}
-
-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 *val, GError **error)
-{
-	gs_free char *val_strip = NULL;
-	gs_strfreev char **strv = NULL;
-	const char *delimiters = " \t,";
-	char **iter;
-	long int val_int;
-	GBytes *bytes;
-	GByteArray *array = NULL;
-	gboolean success = TRUE;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	val_strip = g_strstrip (g_strdup (val));
-
-	/* 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++) {
-		guint8 v8;
-
-		if (!nmc_string_to_int_base (g_strstrip (*iter), 16, TRUE, 0, 255, &val_int)) {
-			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 = val_int;
-		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;
-}
-
-/* === GetFunc, SetFunc, RemoveFunc, DescribeFunc, ValuesFunc
-       functions for all properties of all settings === */
-
-/* --- NM_SETTING_802_1X_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_802_1X_get_eap, NM_SETTING_802_1X_EAP)
-DEFINE_GETTER (nmc_property_802_1X_get_identity, NM_SETTING_802_1X_IDENTITY)
-DEFINE_GETTER (nmc_property_802_1X_get_anonymous_identity, NM_SETTING_802_1X_ANONYMOUS_IDENTITY)
-DEFINE_GETTER (nmc_property_802_1X_get_pac_file, NM_SETTING_802_1X_PAC_FILE)
-DEFINE_GETTER (nmc_property_802_1X_get_ca_cert_password, NM_SETTING_802_1X_CA_CERT_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_ca_cert_password_flags, NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS)
-DEFINE_GETTER (nmc_property_802_1X_get_ca_path, NM_SETTING_802_1X_CA_PATH)
-DEFINE_GETTER (nmc_property_802_1X_get_subject_match, NM_SETTING_802_1X_SUBJECT_MATCH)
-DEFINE_GETTER (nmc_property_802_1X_get_altsubject_matches, NM_SETTING_802_1X_ALTSUBJECT_MATCHES)
-DEFINE_GETTER (nmc_property_802_1X_get_domain_suffix_match, NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH)
-DEFINE_GETTER (nmc_property_802_1X_get_client_cert_password, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_client_cert_password_flags, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS)
-DEFINE_GETTER (nmc_property_802_1X_get_phase1_peapver, NM_SETTING_802_1X_PHASE1_PEAPVER)
-DEFINE_GETTER (nmc_property_802_1X_get_phase1_peaplabel, NM_SETTING_802_1X_PHASE1_PEAPLABEL)
-DEFINE_GETTER (nmc_property_802_1X_get_phase1_fast_provisioning, NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING)
-DEFINE_GETTER (nmc_property_802_1X_get_phase2_auth, NM_SETTING_802_1X_PHASE2_AUTH)
-DEFINE_GETTER (nmc_property_802_1X_get_phase2_autheap, NM_SETTING_802_1X_PHASE2_AUTHEAP)
-DEFINE_GETTER (nmc_property_802_1X_get_phase2_ca_cert_password, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_phase2_ca_cert_password_flags, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS)
-DEFINE_GETTER (nmc_property_802_1X_get_phase2_ca_path, NM_SETTING_802_1X_PHASE2_CA_PATH)
-DEFINE_GETTER (nmc_property_802_1X_get_phase2_subject_match, NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH)
-DEFINE_GETTER (nmc_property_802_1X_get_phase2_altsubject_matches, NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES)
-DEFINE_GETTER (nmc_property_802_1X_get_phase2_domain_suffix_match, NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH)
-DEFINE_GETTER (nmc_property_802_1X_get_phase2_client_cert_password, NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_phase2_client_cert_password_flags, NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS)
-DEFINE_GETTER (nmc_property_802_1X_get_password, NM_SETTING_802_1X_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_password_flags, NM_SETTING_802_1X_PASSWORD_FLAGS)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_password_raw_flags, NM_SETTING_802_1X_PASSWORD_RAW_FLAGS)
-DEFINE_GETTER (nmc_property_802_1X_get_private_key_password, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_private_key_password_flags, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS)
-DEFINE_GETTER (nmc_property_802_1X_get_phase2_private_key_password, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_phase2_private_key_password_flags, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS)
-DEFINE_GETTER (nmc_property_802_1X_get_pin, NM_SETTING_802_1X_PIN)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_pin_flags, NM_SETTING_802_1X_PIN_FLAGS)
-DEFINE_GETTER (nmc_property_802_1X_get_system_ca_certs, NM_SETTING_802_1X_SYSTEM_CA_CERTS)
-DEFINE_GETTER (nmc_property_802_1X_get_auth_timeout, NM_SETTING_802_1X_AUTH_TIMEOUT)
-
-static char *
-nmc_property_802_1X_get_ca_cert (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
-	char *ca_cert_str = NULL;
-
-	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 ca_cert_str;
-}
-
-static char *
-nmc_property_802_1X_get_client_cert (NMSetting *setting,
-                                     NmcPropertyGetType get_type,
-                                     gboolean show_secrets)
-{
-	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
-	char *cert_str = NULL;
-
-	switch (nm_setting_802_1x_get_client_cert_scheme (s_8021X)) {
-	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
-		if (show_secrets)
-			cert_str = bytes_to_string (nm_setting_802_1x_get_client_cert_blob (s_8021X));
-		else
-			cert_str = g_strdup (_("<hidden>"));
-		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 cert_str;
-}
-
-static char *
-nmc_property_802_1X_get_client_cert_full (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	return nmc_property_802_1X_get_client_cert (setting, get_type, TRUE);
-}
-
-static char *
-nmc_property_802_1X_get_phase2_ca_cert (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
-	char *phase2_ca_cert_str = NULL;
-
-	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 phase2_ca_cert_str;
-}
-
-static char *
-nmc_property_802_1X_get_phase2_client_cert (NMSetting *setting,
-                                            NmcPropertyGetType get_type,
-                                            gboolean show_secrets)
-{
-	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
-	char *cert_str = NULL;
-
-	switch (nm_setting_802_1x_get_phase2_client_cert_scheme (s_8021X)) {
-	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
-		if (show_secrets)
-			cert_str = bytes_to_string (nm_setting_802_1x_get_phase2_client_cert_blob (s_8021X));
-		else
-			cert_str = g_strdup (_("<hidden>"));
-		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 cert_str;
-}
-
-static char *
-nmc_property_802_1X_get_phase2_client_cert_full (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	return nmc_property_802_1X_get_phase2_client_cert (setting, get_type, TRUE);
-}
-
-static char *
-nmc_property_802_1X_get_password_raw (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
-	return bytes_to_string (nm_setting_802_1x_get_password_raw (s_8021X));
-}
-
-static char *
-nmc_property_802_1X_get_private_key (NMSetting *setting,
-                                     NmcPropertyGetType get_type,
-                                     gboolean show_secrets)
-{
-	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
-	char *key_str = NULL;
-
-	switch (nm_setting_802_1x_get_private_key_scheme (s_8021X)) {
-	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
-		if (show_secrets)
-			key_str = bytes_to_string (nm_setting_802_1x_get_private_key_blob (s_8021X));
-		else
-			key_str = g_strdup (_("<hidden>"));
-		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 key_str;
-}
-
-static char *
-nmc_property_802_1X_get_private_key_full (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	return nmc_property_802_1X_get_private_key (setting, get_type, TRUE);
-}
-
-static char *
-nmc_property_802_1X_get_phase2_private_key (NMSetting *setting,
-                                            NmcPropertyGetType get_type,
-                                            gboolean show_secrets)
-{
-	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
-	char *key_str = NULL;
-
-	switch (nm_setting_802_1x_get_phase2_private_key_scheme (s_8021X)) {
-	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
-		if (show_secrets)
-			key_str = bytes_to_string (nm_setting_802_1x_get_phase2_private_key_blob (s_8021X));
-		else
-			key_str = g_strdup (_("<hidden>"));
-		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 key_str;
-}
-
-static char *
-nmc_property_802_1X_get_phase2_private_key_full (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	return nmc_property_802_1X_get_phase2_private_key (setting, get_type, TRUE);
-}
-
-#define DEFINE_SETTER_STR_LIST(def_func, set_func) \
-	static gboolean \
-	def_func (NMSetting *setting, const char *prop, const char *val, GError **error) \
-	{ \
-		char **strv = NULL; \
-		guint i = 0; \
-		\
-		g_return_val_if_fail (error == NULL || *error == NULL, FALSE); \
-		\
-		strv = nmc_strsplit_set (val, " \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 (NMSetting *setting, const char *prop, const char *val, GError **error) \
-	{ \
-		char *val_strip = g_strstrip (g_strdup (val)); \
-		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 (NMSetting *setting, const char *prop, const char *val, GError **error) \
-	{ \
-		char **strv = NULL; \
-		char *val_strip = g_strstrip (g_strdup (val)); \
-		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; \
-	}
-
-/* 'eap' */
-static const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", NULL };
-
-DEFINE_SETTER_STR_LIST_MULTI (check_and_add_802_1X_eap,
-                              NM_SETTING_802_1X,
-                              nm_setting_802_1x_add_eap_method)
-static gboolean
-nmc_property_802_1X_set_eap (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_add_802_1X_eap (setting, prop, val, valid_eap, 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 (nmc_property_802_1X_remove_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_ALLOWED_VAL_FUNC (nmc_property_802_1X_allowed_eap, valid_eap)
-
-/* 'ca-cert' */
-DEFINE_SETTER_CERT (nmc_property_802_1X_set_ca_cert, nm_setting_802_1x_set_ca_cert)
-
-static const char *
-nmc_property_802_1X_describe_ca_cert (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'altsubject-matches' */
-DEFINE_SETTER_STR_LIST (nmc_property_802_1X_set_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 (nmc_property_802_1X_remove_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)
-
-/* 'client-cert' */
-DEFINE_SETTER_CERT (nmc_property_802_1X_set_client_cert, nm_setting_802_1x_set_client_cert)
-
-static const char *
-nmc_property_802_1X_describe_client_cert (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'phase2-ca-cert' */
-DEFINE_SETTER_CERT (nmc_property_802_1X_set_phase2_ca_cert, nm_setting_802_1x_set_phase2_ca_cert)
-
-static const char *
-nmc_property_802_1X_describe_phase2_ca_cert (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'phase2-altsubject-matches' */
-DEFINE_SETTER_STR_LIST (nmc_property_802_1X_set_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 (nmc_property_802_1X_remove_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)
-
-/* 'phase2-client-cert' */
-DEFINE_SETTER_CERT (nmc_property_802_1X_set_phase2_client_cert, nm_setting_802_1x_set_phase2_client_cert)
-
-static const char *
-nmc_property_802_1X_describe_phase2_client_cert (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'private-key' */
-DEFINE_SETTER_PRIV_KEY (nmc_property_802_1X_set_private_key,
-                        nm_setting_802_1x_get_private_key_password,
-                        nm_setting_802_1x_set_private_key)
-
-/* 'phase2-private-key' */
-DEFINE_SETTER_PRIV_KEY (nmc_property_802_1X_set_phase2_private_key,
-                        nm_setting_802_1x_get_phase2_private_key_password,
-                        nm_setting_802_1x_set_phase2_private_key)
-
-static const char *
-nmc_property_802_1X_describe_private_key (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'phase1-peapver' */
-static const char *_802_1X_valid_phase1_peapvers[] = { "0", "1", NULL };
-
-static gboolean
-nmc_property_802_1X_set_phase1_peapver (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, _802_1X_valid_phase1_peapvers, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_802_1X_allowed_phase1_peapver, _802_1X_valid_phase1_peapvers)
-
-/* 'phase1-peaplabel' */
-static const char *_802_1X_valid_phase1_peaplabels[] = { "0", "1", NULL };
-
-static gboolean
-nmc_property_802_1X_set_phase1_peaplabel (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, _802_1X_valid_phase1_peaplabels, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_802_1X_allowed_phase1_peaplabel, _802_1X_valid_phase1_peaplabels)
-
-/* 'phase1-fast-provisioning' */
-static const char *_802_1X_valid_phase1_fast_provisionings[] = { "0", "1", "2", "3", NULL };
-
-static gboolean
-nmc_property_802_1X_set_phase1_fast_provisioning (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, _802_1X_valid_phase1_fast_provisionings, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_802_1X_allowed_phase1_fast_provisioning, _802_1X_valid_phase1_fast_provisionings)
-
-/* 'phase2-auth' */
-static const char *_802_1X_valid_phase2_auths[] =
-	{ "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", "tls", NULL };
-
-static gboolean
-nmc_property_802_1X_set_phase2_auth (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, _802_1X_valid_phase2_auths, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_802_1X_allowed_phase2_auth, _802_1X_valid_phase2_auths)
-
-/* 'phase2-autheap' */
-static const char *_802_1X_valid_phase2_autheaps[] = { "md5", "mschapv2", "otp", "gtc", "tls", NULL };
-static gboolean
-nmc_property_802_1X_set_phase2_autheap (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, _802_1X_valid_phase2_autheaps, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_802_1X_allowed_phase2_autheap, _802_1X_valid_phase2_autheaps)
-
-/* 'password-raw' */
-static gboolean
-nmc_property_802_1X_set_password_raw (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return nmc_property_set_bytes (setting, prop, val, error);
-}
-
-static const char *
-nmc_property_802_1X_describe_password_raw (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-static char *
-nmc_property_802_1X_get_phase1_auth_flags (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSetting8021x *s_8021x = NM_SETTING_802_1X (setting);
-	NMSetting8021xAuthFlags flags;
-	char *tmp, *str;
-
-	flags = nm_setting_802_1x_get_phase1_auth_flags (s_8021x);
-	tmp = nm_utils_enum_to_str (nm_setting_802_1x_auth_flags_get_type (), flags);
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		str = g_strdup_printf ("%s", tmp && *tmp ? tmp : "none");
-	else
-		str = g_strdup_printf ("%d (%s)", flags, tmp && *tmp ? tmp : "none");
-	g_free (tmp);
-	return str;
-}
-
-static gboolean
-nmc_property_802_1X_set_phase1_auth_flags (NMSetting *setting, const char *prop,
-                                           const char *val, GError **error)
-{
-	NMSetting8021xAuthFlags flags;
-	gs_free char *err_token = NULL;
-	gboolean ret;
-	long int t;
-
-	if (nmc_string_to_int_base (val, 0, TRUE,
-	                            NM_SETTING_802_1X_AUTH_FLAGS_NONE,
-	                            NM_SETTING_802_1X_AUTH_FLAGS_ALL,
-	                            &t))
-		flags = (NMSetting8021xAuthFlags) t;
-	else {
-		ret = nm_utils_enum_from_str (nm_setting_802_1x_auth_flags_get_type (), val,
-		                              (int *) &flags, &err_token);
-
-		if (!ret) {
-			if (g_ascii_strcasecmp (err_token, "none") == 0)
-				flags = NM_SETTING_802_1X_AUTH_FLAGS_NONE;
-			else {
-				g_set_error (error, 1, 0, _("invalid option '%s', use a combination of [%s]"),
-				             err_token,
-				             nm_utils_enum_to_str (nm_setting_802_1x_auth_flags_get_type (),
-				                                   NM_SETTING_802_1X_AUTH_FLAGS_ALL));
-				return FALSE;
-			}
-		}
-	}
-
-	g_object_set (setting, prop, (guint) flags, NULL);
-	return TRUE;
-}
-
-
-/* --- NM_SETTING_ADSL_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_adsl_get_username, NM_SETTING_ADSL_USERNAME)
-DEFINE_GETTER (nmc_property_adsl_get_password, NM_SETTING_ADSL_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_adsl_get_password_flags, NM_SETTING_ADSL_PASSWORD_FLAGS)
-DEFINE_GETTER (nmc_property_adsl_get_protocol, NM_SETTING_ADSL_PROTOCOL)
-DEFINE_GETTER (nmc_property_adsl_get_encapsulation, NM_SETTING_ADSL_ENCAPSULATION)
-DEFINE_GETTER (nmc_property_adsl_get_vpi, NM_SETTING_ADSL_VPI)
-DEFINE_GETTER (nmc_property_adsl_get_vci, NM_SETTING_ADSL_VCI)
-
-/* 'protocol' */
-static const char *adsl_valid_protocols[] = {
-	NM_SETTING_ADSL_PROTOCOL_PPPOA,
-	NM_SETTING_ADSL_PROTOCOL_PPPOE,
-	NM_SETTING_ADSL_PROTOCOL_IPOATM,
-	NULL
-};
-
-static gboolean
-nmc_property_adsl_set_protocol (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, adsl_valid_protocols, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_adsl_allowed_protocol, adsl_valid_protocols)
-
-/* 'encapsulation' */
-static const char *adsl_valid_encapsulations[] = {
-	NM_SETTING_ADSL_ENCAPSULATION_VCMUX,
-	NM_SETTING_ADSL_ENCAPSULATION_LLC,
-	NULL
-};
-
-static gboolean
-nmc_property_adsl_set_encapsulation (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, adsl_valid_encapsulations, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_adsl_allowed_encapsulation, adsl_valid_encapsulations)
-
-
-/* --- NM_SETTING_BLUETOOTH_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_bluetooth_get_bdaddr, NM_SETTING_BLUETOOTH_BDADDR)
-DEFINE_GETTER (nmc_property_bluetooth_get_type, NM_SETTING_BLUETOOTH_TYPE)
-
-/* 'type' */
-static gboolean
-nmc_property_bluetooth_set_type (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	const char *types[] = {
-	    NM_SETTING_BLUETOOTH_TYPE_DUN,
-	    NM_SETTING_BLUETOOTH_TYPE_PANU,
-	    NULL };
-
-	return check_and_set_string (setting, prop, val, types, error);
-}
-
-/* --- NM_SETTING_BOND_SETTING_NAME property functions --- */
-/* 'options' */
-static char *
-nmc_property_bond_get_options (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingBond *s_bond = NM_SETTING_BOND (setting);
-	GString *bond_options_s;
-	int i;
-
-	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 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;
-}
-
-/* Validate bonding 'options' values */
-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 (nmc_property_bond_set_options,
-                       NM_SETTING_BOND,
-                       NMSettingBond,
-                       _bond_add_option,
-                       nm_setting_bond_get_valid_options,
-                       _validate_bond_option_value)
-DEFINE_REMOVER_OPTION (nmc_property_bond_remove_option_options,
-                       NM_SETTING_BOND,
-                       _validate_and_remove_bond_option)
-
-static const char *
-nmc_property_bond_describe_options (NMSetting *setting, const char *prop)
-{
-	static char *desc = NULL;
-	const char **valid_options;
-	char *options_str;
-
-	if (G_UNLIKELY (desc == NULL)) {
-		valid_options = nm_setting_bond_get_valid_options (NM_SETTING_BOND (setting));
-		options_str = g_strjoinv (", ", (char **) valid_options);
-
-		desc = 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);
-		g_free (options_str);
-	}
-	return desc;
-}
-
-static const char **
-nmc_property_bond_allowed_options (NMSetting *setting, const char *prop)
-{
-	return nm_setting_bond_get_valid_options (NM_SETTING_BOND (setting));
-}
-
-
-/* --- NM_SETTING_BRIDGE_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_bridge_get_mac_address, NM_SETTING_BRIDGE_MAC_ADDRESS)
-DEFINE_GETTER (nmc_property_bridge_get_stp, NM_SETTING_BRIDGE_STP)
-DEFINE_GETTER (nmc_property_bridge_get_priority, NM_SETTING_BRIDGE_PRIORITY)
-DEFINE_GETTER (nmc_property_bridge_get_forward_delay, NM_SETTING_BRIDGE_FORWARD_DELAY)
-DEFINE_GETTER (nmc_property_bridge_get_hello_time, NM_SETTING_BRIDGE_HELLO_TIME)
-DEFINE_GETTER (nmc_property_bridge_get_max_age, NM_SETTING_BRIDGE_MAX_AGE)
-DEFINE_GETTER (nmc_property_bridge_get_ageing_time, NM_SETTING_BRIDGE_AGEING_TIME)
-DEFINE_GETTER (nmc_property_bridge_get_multicast_snooping, NM_SETTING_BRIDGE_MULTICAST_SNOOPING)
-
-
-/* --- NM_SETTING_BRIDGE_PORT_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_bridge_port_get_priority, NM_SETTING_BRIDGE_PORT_PRIORITY)
-DEFINE_GETTER (nmc_property_bridge_port_get_path_cost, NM_SETTING_BRIDGE_PORT_PATH_COST)
-DEFINE_GETTER (nmc_property_bridge_port_get_hairpin_mode, NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE)
-
-
-/* --- NM_SETTING_CDMA_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_cdma_get_number, NM_SETTING_CDMA_NUMBER)
-DEFINE_GETTER (nmc_property_cdma_get_username, NM_SETTING_CDMA_USERNAME)
-DEFINE_GETTER (nmc_property_cdma_get_password, NM_SETTING_CDMA_PASSWORD)
-DEFINE_GETTER (nmc_property_cdma_get_mtu, NM_SETTING_CDMA_MTU)
-
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_cdma_get_password_flags, NM_SETTING_CDMA_PASSWORD_FLAGS)
-
 
-/* --- NM_SETTING_CONNECTION_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_connection_get_id, NM_SETTING_CONNECTION_ID)
-DEFINE_GETTER (nmc_property_connection_get_uuid, NM_SETTING_CONNECTION_UUID)
-DEFINE_GETTER (nmc_property_connection_get_stable_id, NM_SETTING_CONNECTION_STABLE_ID)
-DEFINE_GETTER (nmc_property_connection_get_interface_name, NM_SETTING_CONNECTION_INTERFACE_NAME)
-DEFINE_GETTER (nmc_property_connection_get_type, NM_SETTING_CONNECTION_TYPE)
-DEFINE_GETTER (nmc_property_connection_get_autoconnect, NM_SETTING_CONNECTION_AUTOCONNECT)
-DEFINE_GETTER (nmc_property_connection_get_autoconnect_priority, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY)
-DEFINE_GETTER (nmc_property_connection_get_timestamp, NM_SETTING_CONNECTION_TIMESTAMP)
-DEFINE_GETTER (nmc_property_connection_get_read_only, NM_SETTING_CONNECTION_READ_ONLY)
-
-static char *
-nmc_property_connection_get_autoconnect_retries (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingConnection *s_con = NM_SETTING_CONNECTION (setting);
-	gint retries;
-
-	retries = nm_setting_connection_get_autoconnect_retries (s_con);
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		return g_strdup_printf ("%d", retries);
-
-	switch (retries) {
-	case -1:
-		return g_strdup_printf (_("%d (default)"), retries);
-	case 0:
-		return g_strdup_printf (_("%d (forever)"), retries);
-	default:
-		return g_strdup_printf ("%d", retries);
-	}
-}
-
-static char *
-nmc_property_connection_get_permissions (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingConnection *s_con = NM_SETTING_CONNECTION (setting);
-	GString *perm = NULL;
-	const char *perm_item;
-	const char *perm_type;
-	int i;
-
-	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 g_string_free (perm, FALSE);
-	}
-
-	/* No value from get_permission */
-	return g_string_free (perm, TRUE);
-}
-
-DEFINE_GETTER (nmc_property_connection_get_zone, NM_SETTING_CONNECTION_ZONE)
-DEFINE_GETTER (nmc_property_connection_get_master, NM_SETTING_CONNECTION_MASTER)
-DEFINE_GETTER (nmc_property_connection_get_slave_type, NM_SETTING_CONNECTION_SLAVE_TYPE)
-
-static char *
-nmc_property_connection_get_autoconnect_slaves (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingConnection *s_con = NM_SETTING_CONNECTION (setting);
-	return autoconnect_slaves_to_string (nm_setting_connection_get_autoconnect_slaves (s_con), get_type);
-}
-
-DEFINE_GETTER (nmc_property_connection_get_secondaries, NM_SETTING_CONNECTION_SECONDARIES)
-DEFINE_GETTER (nmc_property_connection_get_gateway_ping_timeout, NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT)
-
-static gboolean
-nmc_property_connection_set_type (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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), prop, val, NULL);
-	return TRUE;
-}
-
-#if 0
-/*
- * Setting/removing UUID has been forbidden.
- * Should it be enabled later, this function can be used.
- */
-static gboolean
-nmc_property_con_set_uuid (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nm_utils_is_uuid (val)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid UUID"), val);
-		return FALSE;
-	}
-	g_object_set (setting, prop, val, NULL);
-	return TRUE;
-}
-#endif
-
-/* 'permissions' */
-/* 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
-nmc_property_connection_set_permissions (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL;
-	guint i = 0;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, " \t,", 0);
-	if (!verify_string_list (strv, prop, 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 (nmc_property_connection_remove_permissions,
-                               NM_SETTING_CONNECTION,
-                               nm_setting_connection_get_num_permissions,
-                               nm_setting_connection_remove_permission,
-                               _validate_and_remove_connection_permission)
-
-static const char *
-nmc_property_connection_describe_permissions (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'master' */
-static gboolean
-nmc_property_con_set_master (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!val)
-		;
-	else if (!*val)
-		val = NULL;
-	else if (   !nm_utils_is_valid_iface_name (val, NULL)
-	         && !nm_utils_is_uuid (val)) {
-		g_set_error (error, 1, 0,
-		             _("'%s' is not valid master; use ifname or connection UUID"),
-		             val);
-		return FALSE;
-	}
-	g_object_set (setting, prop, val, NULL);
-	return TRUE;
-}
-
-/* 'slave-type' */
-static const char *con_valid_slave_types[] = {
-	NM_SETTING_BOND_SETTING_NAME,
-	NM_SETTING_BRIDGE_SETTING_NAME,
-	NM_SETTING_TEAM_SETTING_NAME,
-	NULL
-};
-
-static gboolean
-nmc_property_con_set_slave_type (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, con_valid_slave_types, error);
-}
-
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_con_allowed_slave_type, con_valid_slave_types)
-
-/* 'secondaries' */
-static gboolean
-nmc_property_connection_set_secondaries (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	const GPtrArray *connections;
-	NMConnection *con;
-	char **strv = NULL, **iter;
-	guint i = 0;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	connections = nm_client_get_connections (nm_cli.client);
-	strv = nmc_strsplit_set (val, " \t,", 0);
-	for (iter = strv; iter && *iter; iter++) {
-		if (**iter == '\0')
-			continue;
-
-		if (nm_utils_is_uuid (*iter)) {
-			con = nmc_find_connection (connections, "uuid", *iter, NULL, FALSE);
-			if (!con)
-				g_print (_("Warning: %s is not an UUID of any existing connection profile\n"), *iter);
-			else {
-				/* Currenly NM only supports VPN connections as secondaries */
-				if (!nm_connection_is_type (con, NM_SETTING_VPN_SETTING_NAME)) {
-					g_set_error (error, 1, 0, _("'%s' is not a VPN connection profile"), *iter);
-					g_strfreev (strv);
-					return FALSE;
-				}
-			}
-		} else {
-			con = nmc_find_connection (connections, "id", *iter, NULL, FALSE);
-			if (!con) {
-				g_set_error (error, 1, 0, _("'%s' is not a name of any exiting profile"), *iter);
-				g_strfreev (strv);
-				return FALSE;
-			}
-
-			/* Currenly NM only supports VPN connections as secondaries */
-			if (!nm_connection_is_type (con, NM_SETTING_VPN_SETTING_NAME)) {
-				g_set_error (error, 1, 0, _("'%s' is not a VPN connection profile"), *iter);
-				g_strfreev (strv);
-				return FALSE;
-			}
-
-			/* translate id to uuid */
-			g_free (*iter);
-			*iter = g_strdup (nm_connection_get_uuid (con));
-		}
-	}
-
-	while (strv && strv[i])
-		nm_setting_connection_add_secondary (NM_SETTING_CONNECTION (setting), strv[i++]);
-	g_strfreev (strv);
-
-	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 (nmc_property_connection_remove_secondaries,
-                               NM_SETTING_CONNECTION,
-                               nm_setting_connection_get_num_secondaries,
-                               nm_setting_connection_remove_secondary,
-                               _validate_and_remove_connection_secondary)
-
-static const char *
-nmc_property_connection_describe_secondaries (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'metered' */
-static char *
-nmc_property_connection_get_metered (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingConnection *s_conn = NM_SETTING_CONNECTION (setting);
-
-	if (get_type == NMC_PROPERTY_GET_PARSABLE) {
-		switch (nm_setting_connection_get_metered (s_conn)) {
-		case NM_METERED_YES:
-			return g_strdup ("yes");
-		case NM_METERED_NO:
-			return g_strdup ("no");
-		case NM_METERED_UNKNOWN:
-		default:
-			return g_strdup ("unknown");
-		}
-	}
-	switch (nm_setting_connection_get_metered (s_conn)) {
-	case NM_METERED_YES:
-		return g_strdup (_("yes"));
-	case NM_METERED_NO:
-		return g_strdup (_("no"));
-	case NM_METERED_UNKNOWN:
-	default:
-		return g_strdup (_("unknown"));
-	}
-}
-
-static gboolean
-nmc_property_connection_set_metered (NMSetting *setting, const char *prop,
-                                     const char *val, GError **error)
-{
-	NMMetered metered;
-	NMCTriStateValue ts_val;
-
-	if (!nmc_string_to_tristate (val, &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, prop, metered, NULL);
-	return TRUE;
-}
-
-static const char *
-nmc_property_connection_describe_metered (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-static const char *metered_valid_values[] = { "yes", "no", "unknown", NULL };
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_connection_allowed_metered, metered_valid_values)
-
-/* 'lldp' */
-static char *
-nmc_property_connection_get_lldp (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingConnection *s_conn = NM_SETTING_CONNECTION (setting);
-	NMSettingConnectionLldp lldp;
-	char *tmp, *str;
-
-	lldp = nm_setting_connection_get_lldp (s_conn);
-	tmp = nm_utils_enum_to_str (nm_setting_connection_lldp_get_type (), lldp);
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		str = g_strdup_printf ("%s", tmp && *tmp ? tmp : "default");
-	else
-		str = g_strdup_printf ("%d (%s)", lldp, tmp && *tmp ? tmp : "default");
-	g_free (tmp);
-	return str;
-}
-
-static gboolean
-nmc_property_connection_set_lldp (NMSetting *setting, const char *prop,
-                                  const char *val, GError **error)
-{
-	NMSettingConnectionLldp lldp;
-	gboolean ret;
-	long int t;
-
-	if (nmc_string_to_int_base (val, 0, TRUE,
-	                           NM_SETTING_CONNECTION_LLDP_DEFAULT,
-	                           NM_SETTING_CONNECTION_LLDP_ENABLE_RX,
-	                           &t))
-		lldp = t;
-	else {
-		ret = nm_utils_enum_from_str (nm_setting_connection_lldp_get_type (), val,
-		                              (int *) &lldp, NULL);
-
-		if (!ret) {
-			if (g_ascii_strcasecmp (val, "enable") == 0)
-				lldp = NM_SETTING_CONNECTION_LLDP_ENABLE_RX;
-			else {
-				g_set_error (error, 1, 0, _("invalid option '%s', use one of [%s]"),
-				             val, "default,disable,enable-rx,enable");
-				return FALSE;
-			}
-		}
-	}
-
-	g_object_set (setting, prop, lldp, NULL);
-	return TRUE;
-}
-
-static const char *lldp_valid_values[] = { "default", "disable", "enable-rx", NULL };
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_connection_allowed_lldp, lldp_valid_values)
-
-
-/* --- NM_SETTING_DCB_SETTING_NAME property functions --- */
-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 char * \
-	func_name (NMSetting *setting, NmcPropertyGetType get_type) \
-	{ \
-		guint v; \
-		GValue val = G_VALUE_INIT; \
-		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 dcb_flags_to_string (v); \
-	}
-
-static char *
-dcb_app_priority_to_string (gint priority)
-{
-	return (priority == -1) ? g_strdup (_("-1 (unset)")) : g_strdup_printf ("%d", priority);
-}
-
-#define DEFINE_DCB_APP_PRIORITY_GETTER(func_name, property_name) \
-	static char * \
-	func_name (NMSetting *setting, NmcPropertyGetType get_type) \
-	{ \
-		int v; \
-		GValue val = G_VALUE_INIT; \
-		g_value_init (&val, G_TYPE_INT); \
-		g_object_get_property (G_OBJECT (setting), property_name, &val); \
-		v = g_value_get_int (&val); \
-		g_value_unset (&val); \
-		return dcb_app_priority_to_string (v); \
-	}
-
-#define DEFINE_DCB_BOOL_GETTER(func_name, getter_func_name) \
-	static char * \
-	func_name (NMSetting *setting, NmcPropertyGetType get_type) \
-	{ \
-		NMSettingDcb *s_dcb = NM_SETTING_DCB (setting); \
-		GString *str; \
-		guint i; \
- \
-		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 g_string_free (str, FALSE); \
-	}
-
-#define DEFINE_DCB_UINT_GETTER(func_name, getter_func_name) \
-	static char * \
-	func_name (NMSetting *setting, NmcPropertyGetType get_type) \
-	{ \
-		NMSettingDcb *s_dcb = NM_SETTING_DCB (setting); \
-		GString *str; \
-		guint i; \
- \
-		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 g_string_free (str, FALSE); \
-	}
-
-DEFINE_DCB_FLAGS_GETTER (nmc_property_dcb_get_app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_FLAGS)
-DEFINE_DCB_APP_PRIORITY_GETTER (nmc_property_dcb_get_app_fcoe_priority, NM_SETTING_DCB_APP_FCOE_PRIORITY)
-DEFINE_GETTER (nmc_property_dcb_get_app_fcoe_mode, NM_SETTING_DCB_APP_FCOE_MODE)
-DEFINE_DCB_FLAGS_GETTER (nmc_property_dcb_get_app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_FLAGS)
-DEFINE_DCB_APP_PRIORITY_GETTER (nmc_property_dcb_get_app_iscsi_priority, NM_SETTING_DCB_APP_ISCSI_PRIORITY)
-DEFINE_DCB_FLAGS_GETTER (nmc_property_dcb_get_app_fip_flags, NM_SETTING_DCB_APP_FIP_FLAGS)
-DEFINE_DCB_APP_PRIORITY_GETTER (nmc_property_dcb_get_app_fip_priority, NM_SETTING_DCB_APP_FIP_PRIORITY)
-
-DEFINE_DCB_FLAGS_GETTER (nmc_property_dcb_get_pfc_flags, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS)
-DEFINE_DCB_BOOL_GETTER (nmc_property_dcb_get_pfc, nm_setting_dcb_get_priority_flow_control)
-
-DEFINE_DCB_FLAGS_GETTER (nmc_property_dcb_get_pg_flags, NM_SETTING_DCB_PRIORITY_GROUP_FLAGS)
-DEFINE_DCB_UINT_GETTER (nmc_property_dcb_get_pg_group_id, nm_setting_dcb_get_priority_group_id)
-DEFINE_DCB_UINT_GETTER (nmc_property_dcb_get_pg_group_bandwidth, nm_setting_dcb_get_priority_group_bandwidth)
-DEFINE_DCB_UINT_GETTER (nmc_property_dcb_get_pg_bandwidth, nm_setting_dcb_get_priority_bandwidth)
-DEFINE_DCB_BOOL_GETTER (nmc_property_dcb_get_pg_strict, nm_setting_dcb_get_priority_strict_bandwidth)
-DEFINE_DCB_UINT_GETTER (nmc_property_dcb_get_pg_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
-nmc_property_dcb_set_flags (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 */
-	if (nmc_string_to_int_base (val, 0, TRUE, 0, DCB_ALL_FLAGS, &t))
-		flags = (guint) t;
-	else {
-		/* Check for individual flag numbers */
-		strv = nmc_strsplit_set (val, " \t,", 0);
-		for (iter = strv; iter && *iter; iter++) {
-			if (!nmc_string_to_int_base (*iter, 0, TRUE, 0, DCB_ALL_FLAGS, &t))
-				t = -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, prop, (guint) flags, error))
-		return FALSE;
-
-	g_object_set (setting, prop, (guint) flags, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_dcb_set_priority (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	long int priority = 0;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_int (val, FALSE, -1, 7, &priority)) {
-		g_set_error (error, 1, 0, _("'%s' is not a DCB app priority"), val);
-		return FALSE;
-	}
-
-	/* Validate the number according to the property spec */
-	if (!validate_int (setting, prop, (gint) priority, error))
-		return FALSE;
-
-	g_object_set (setting, prop, (gint) priority, NULL);
-	return TRUE;
-}
-
-static gboolean
-dcb_parse_uint_array (const char *val,
-                      guint max,
-                      guint other,
-                      guint *out_array,
-                      GError **error)
-{
-	char **items, **iter;
-	guint i = 0;
-
-	g_return_val_if_fail (out_array != NULL, FALSE);
-
-	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"));
-		goto error;
-	}
-
-	for (iter = items; iter && *iter; iter++) {
-		long int num = 0;
-		gboolean success;
-
-		*iter = g_strstrip (*iter);
-		success = nmc_string_to_int_base (*iter, 10, TRUE, 0, other ? other : max, &num);
-
-		/* If number is greater than 'max' it must equal 'other' */
-		if (success && other && (num > max) && (num != other))
-			success = FALSE;
-
-		if (!success) {
-			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);
-			}
-			goto error;
-		}
-		out_array[i++] = (guint) num;
-	}
-
-	return TRUE;
-
-error:
-	g_strfreev (items);
-	return FALSE;
-}
-
-static void
-dcb_check_feature_enabled (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))
-		g_print (_("Warning: changes will have no effect until '%s' includes 1 (enabled)\n\n"), flags_prop);
-}
-
-static gboolean
-nmc_property_dcb_set_pfc (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 (val, 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 (NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_dcb_set_pg_group_id (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 (val, 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 (NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_dcb_set_pg_group_bandwidth (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 (val, 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 (NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_dcb_set_pg_bandwidth (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 (val, 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 (NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_dcb_set_pg_strict (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 (val, 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 (NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_dcb_set_pg_traffic_class (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 (val, 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 (NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS);
-	return TRUE;
-}
-
-/* 'app-fcoe-mode' */
-static const char *_dcb_valid_fcoe_modes[] = { NM_SETTING_DCB_FCOE_MODE_FABRIC,
-                                               NM_SETTING_DCB_FCOE_MODE_VN2VN,
-                                               NULL };
-
-static gboolean
-nmc_property_dcb_set_app_fcoe_mode (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, _dcb_valid_fcoe_modes, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_dcb_allowed_app_fcoe_modes, _dcb_valid_fcoe_modes)
-
-
-/* --- NM_SETTING_GSM_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_gsm_get_number, NM_SETTING_GSM_NUMBER)
-DEFINE_GETTER (nmc_property_gsm_get_username, NM_SETTING_GSM_USERNAME)
-DEFINE_GETTER (nmc_property_gsm_get_password, NM_SETTING_GSM_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_gsm_get_password_flags, NM_SETTING_GSM_PASSWORD_FLAGS)
-DEFINE_GETTER (nmc_property_gsm_get_apn, NM_SETTING_GSM_APN)
-DEFINE_GETTER (nmc_property_gsm_get_network_id, NM_SETTING_GSM_NETWORK_ID)
-DEFINE_GETTER (nmc_property_gsm_get_pin, NM_SETTING_GSM_PIN)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_gsm_get_pin_flags, NM_SETTING_GSM_PIN_FLAGS)
-DEFINE_GETTER (nmc_property_gsm_get_home_only, NM_SETTING_GSM_HOME_ONLY)
-DEFINE_GETTER (nmc_property_gsm_get_device_id, NM_SETTING_GSM_DEVICE_ID)
-DEFINE_GETTER (nmc_property_gsm_get_sim_id, NM_SETTING_GSM_SIM_ID)
-DEFINE_GETTER (nmc_property_gsm_get_sim_operator_id, NM_SETTING_GSM_SIM_OPERATOR_ID)
-DEFINE_GETTER (nmc_property_gsm_get_mtu, NM_SETTING_GSM_MTU)
-
-static gboolean
-nmc_property_gsm_set_sim_operator_id (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	const char *p = val;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (strlen (val) != 5 && strlen (val) != 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,
-	              val,
-	              NULL);
-	return TRUE;
-}
-
-
-/* --- NM_SETTING_INFINIBAND_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_ib_get_mac_address, NM_SETTING_INFINIBAND_MAC_ADDRESS)
-DEFINE_GETTER (nmc_property_ib_get_transport_mode, NM_SETTING_INFINIBAND_TRANSPORT_MODE)
-
-/* 'mac-address' */
-static gboolean
-nmc_property_ib_set_mac (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nm_utils_hwaddr_valid (val, INFINIBAND_ALEN)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid InfiniBand MAC"), val);
-		return FALSE;
-	}
-
-	g_object_set (setting, prop, val, NULL);
-	return TRUE;
-}
-
-/* 'transport-mode' */
-static const char *ib_valid_transport_modes[] = { "datagram", "connected", NULL };
-
-static gboolean
-nmc_property_ib_set_transport_mode (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, ib_valid_transport_modes, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_ib_allowed_transport_mode, ib_valid_transport_modes)
-
-/* 'p-key' */
-static gboolean
-nmc_property_ib_set_p_key (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	gboolean p_key_valid = FALSE;
-	long p_key_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!strncasecmp (val, "0x", 2))
-		p_key_valid = nmc_string_to_int_base (val + 2, 16, TRUE, 0, G_MAXUINT16, &p_key_int);
-	else
-		p_key_valid = nmc_string_to_int (val, TRUE, -1, G_MAXUINT16, &p_key_int);
-
-	if (!p_key_valid) {
-		if (strcmp (val, "default") == 0)
-			p_key_int = -1;
-		else {
-			g_set_error (error, 1, 0, _("'%s' is not a valid IBoIP P_Key"), val);
-			return FALSE;
-		}
-	}
-	g_object_set (setting, prop, (gint) p_key_int, NULL);
-	return TRUE;
-}
-
-
-static char *
-nmc_property_ib_get_mtu (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingInfiniband *s_infiniband = NM_SETTING_INFINIBAND (setting);
-	int mtu;
-
-	mtu = nm_setting_infiniband_get_mtu (s_infiniband);
-	if (mtu == 0)
-		return g_strdup (_("auto"));
-	else
-		return g_strdup_printf ("%d", mtu);
-}
-
-static char *
-nmc_property_ib_get_p_key (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingInfiniband *s_infiniband = NM_SETTING_INFINIBAND (setting);
-	int p_key;
-
-	p_key = nm_setting_infiniband_get_p_key (s_infiniband);
-	if (p_key == -1)
-		return g_strdup (_("default"));
-	else
-		return g_strdup_printf ("0x%04x", p_key);
-}
-
-DEFINE_GETTER (nmc_property_ib_get_parent, NM_SETTING_INFINIBAND_PARENT)
-
-
-/* --- NM_SETTING_IP_TUNNEL_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_ip_tunnel_get_parent, NM_SETTING_IP_TUNNEL_PARENT);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_local, NM_SETTING_IP_TUNNEL_LOCAL);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_remote, NM_SETTING_IP_TUNNEL_REMOTE);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_ttl, NM_SETTING_IP_TUNNEL_TTL);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_tos, NM_SETTING_IP_TUNNEL_TOS);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_path_mtu_discovery, NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_input_key, NM_SETTING_IP_TUNNEL_INPUT_KEY);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_output_key, NM_SETTING_IP_TUNNEL_OUTPUT_KEY);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_encapsulation_limit, NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_flow_label, NM_SETTING_IP_TUNNEL_FLOW_LABEL);
-DEFINE_GETTER (nmc_property_ip_tunnel_get_mtu, NM_SETTING_IP_TUNNEL_MTU);
-
-static char *
-nmc_property_ip_tunnel_get_mode (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingIPTunnel *s_ip_tunnel = NM_SETTING_IP_TUNNEL (setting);
-	NMIPTunnelMode mode;
-
-	mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel);
-	return nm_utils_enum_to_str (nm_ip_tunnel_mode_get_type (), mode);
-}
-
-static gboolean
-nmc_property_ip_tunnel_set_mode (NMSetting *setting, const char *prop,
-                                  const char *val, GError **error)
-{
-	NMIPTunnelMode mode;
-	gboolean ret;
-
-	ret = nm_utils_enum_from_str (nm_ip_tunnel_mode_get_type(), val,
-	                               (int *) &mode, NULL);
-
-	if (!ret) {
-		gs_free const char **values = NULL;
-		gs_free char *values_str = NULL;
-
-		values = nm_utils_enum_get_values (nm_ip_tunnel_mode_get_type (),
-		                                   NM_IP_TUNNEL_MODE_UNKNOWN + 1,
-		                                   G_MAXINT);
-		values_str = g_strjoinv (",", (char **) values);
-		g_set_error (error, 1, 0, _("invalid mode '%s', use one of %s"),
-		             val, values_str);
-
-		return FALSE;
-	}
-
-	g_object_set (setting, prop, mode, NULL);
-	return TRUE;
-}
-
-DEFINE_ALLOWED_FOR_ENUMS (nmc_property_ip_tunnel_allowed_mode,
-                          nm_ip_tunnel_mode_get_type,
-                          NM_IP_TUNNEL_MODE_UNKNOWN + 1, G_MAXINT)
-
-
-/* --- NM_SETTING_IP4_CONFIG_SETTING_NAME property functions --- */
-/* --- IP4 / IP6 shared functions --- */
-static NMIPAddress *
-_parse_ip_address (int family, const char *address, GError **error)
-{
-	char *value = g_strdup (address);
-	NMIPAddress *ipaddr;
-
-	ipaddr = nmc_parse_and_build_address (family, g_strstrip (value), error);
-	g_free (value);
-	return ipaddr;
-}
-
-DEFINE_GETTER (nmc_property_ipv4_get_method, NM_SETTING_IP_CONFIG_METHOD)
-DEFINE_GETTER (nmc_property_ipv4_get_dns, NM_SETTING_IP_CONFIG_DNS)
-DEFINE_GETTER (nmc_property_ipv4_get_dns_search, NM_SETTING_IP_CONFIG_DNS_SEARCH)
-DEFINE_GETTER_WITH_DEFAULT (nmc_property_ipv4_get_dns_options, NM_SETTING_IP_CONFIG_DNS_OPTIONS, !nm_setting_ip_config_has_dns_options ((NMSettingIPConfig *) setting))
-DEFINE_GETTER (nmc_property_ipv4_get_dns_priority, NM_SETTING_IP_CONFIG_DNS_PRIORITY)
-
-static char *
-nmc_property_ip_get_addresses (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
-	GString *printable;
-	guint32 num_addresses, i;
-	NMIPAddress *addr;
-
-	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 g_string_free (printable, FALSE);
-}
-
-static char *
-nmc_property_ipvx_get_routes (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
-	GString *printable;
-	guint32 num_routes, i;
-	NMIPRoute *route;
-
-	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 (g_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 == NMC_PROPERTY_GET_PARSABLE) {
-			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 g_string_free (printable, FALSE);
-}
-
-static char *
-nmc_property_ipv4_get_routes (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	return nmc_property_ipvx_get_routes (setting, get_type);
-}
-
-DEFINE_GETTER (nmc_property_ipv4_get_gateway, NM_SETTING_IP_CONFIG_GATEWAY)
-DEFINE_GETTER (nmc_property_ipv4_get_route_metric, NM_SETTING_IP_CONFIG_ROUTE_METRIC)
-DEFINE_GETTER (nmc_property_ipv4_get_ignore_auto_routes, NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES)
-DEFINE_GETTER (nmc_property_ipv4_get_ignore_auto_dns, NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS)
-DEFINE_GETTER (nmc_property_ipv4_get_dhcp_client_id, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID)
-DEFINE_GETTER (nmc_property_ipv4_get_dhcp_timeout, NM_SETTING_IP_CONFIG_DHCP_TIMEOUT)
-DEFINE_GETTER (nmc_property_ipv4_get_dhcp_send_hostname, NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME)
-DEFINE_GETTER (nmc_property_ipv4_get_dhcp_hostname, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME)
-DEFINE_GETTER (nmc_property_ipv4_get_dhcp_fqdn, NM_SETTING_IP4_CONFIG_DHCP_FQDN)
-DEFINE_GETTER (nmc_property_ipv4_get_never_default, NM_SETTING_IP_CONFIG_NEVER_DEFAULT)
-DEFINE_GETTER (nmc_property_ipv4_get_may_fail, NM_SETTING_IP_CONFIG_MAY_FAIL)
-
-static char *
-nmc_property_ipv4_get_dad_timeout (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
-	gint dad_timeout;
-
-	dad_timeout = nm_setting_ip_config_get_dad_timeout (s_ip);
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		return g_strdup_printf ("%d", dad_timeout);
-
-	switch (dad_timeout) {
-	case -1:
-		return g_strdup_printf (_("%d (default)"), dad_timeout);
-	case 0:
-		return g_strdup_printf (_("%d (off)"), dad_timeout);
-	default:
-		return g_strdup_printf ("%d", dad_timeout);
-	}
-}
-
-/* 'method' */
-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
-nmc_property_ipv4_set_method (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	/* Silently accept "static" and convert to "manual" */
-	if (val && strlen (val) > 1 && matches (val, "static"))
-		val = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
-
-	return check_and_set_string (setting, prop, val, ipv4_valid_methods, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_ipv4_allowed_method, ipv4_valid_methods)
-
-/* 'dns' */
-static gboolean
-nmc_property_ipv4_set_dns (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL, **iter, *addr;
-	guint32 ip4_addr;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, " \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 (nmc_property_ipv4_remove_dns,
-                               NM_SETTING_IP_CONFIG,
-                               nm_setting_ip_config_get_num_dns,
-                               nm_setting_ip_config_remove_dns,
-                               _validate_and_remove_ipv4_dns)
-
-static const char *
-nmc_property_ipv4_describe_dns (NMSetting *setting, const char *prop)
-{
-	return _("Enter a list of IPv4 addresses of DNS servers.\n\n"
-	         "Example: 8.8.8.8, 8.8.4.4\n");
-}
-
-/* 'dns-search' */
-static gboolean
-nmc_property_ipv4_set_dns_search (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL;
-	guint i = 0;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, " \t,", 0);
-	if (!verify_string_list (strv, prop, 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 (nmc_property_ipv4_remove_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)
-
-/* 'dns-options' */
-static gboolean
-nmc_property_ipv4_set_dns_options (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 (val, " \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 (nmc_property_ipv4_remove_dns_option,
-                               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)
-
-/* 'addresses' */
-static NMIPAddress *
-_parse_ipv4_address (const char *address, GError **error)
-{
-	return _parse_ip_address (AF_INET, address, error);
-}
-
-static gboolean
-nmc_property_ipv4_set_addresses (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL, **iter;
-	NMIPAddress *ip4addr;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, ",", 0);
-	for (iter = strv; iter && *iter; iter++) {
-		ip4addr = _parse_ipv4_address (*iter, error);
-		if (!ip4addr) {
-			g_strfreev (strv);
-			return FALSE;
-		}
-		nm_setting_ip_config_add_address (NM_SETTING_IP_CONFIG (setting), ip4addr);
-		nm_ip_address_unref (ip4addr);
-	}
-	g_strfreev (strv);
-	return TRUE;
-}
-
-static gboolean
-_validate_and_remove_ipv4_address (NMSettingIPConfig *setting,
-                                   const char *address,
-                                   GError **error)
-{
-	NMIPAddress *ip4addr;
-	gboolean ret;
-
-	ip4addr = _parse_ipv4_address (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 (nmc_property_ipv4_remove_addresses,
-                               NM_SETTING_IP_CONFIG,
-                               nm_setting_ip_config_get_num_addresses,
-                               nm_setting_ip_config_remove_address,
-                               _validate_and_remove_ipv4_address)
-
-static const char *
-nmc_property_ipv4_describe_addresses (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'gateway' */
-static gboolean
-nmc_property_ipv4_set_gateway (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	NMIPAddress *ip4addr;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (strchr (val, '/')) {
-		g_set_error (error, 1, 0,
-	                     _("invalid gateway address '%s'"), val);
-		return FALSE;
-	}
-	ip4addr = _parse_ipv4_address (val, error);
-	if (!ip4addr)
-		return FALSE;
-
-	g_object_set (setting, prop, val, NULL);
-	nm_ip_address_unref (ip4addr);
-	return TRUE;
-}
-
-/* 'routes' */
-static NMIPRoute *
-_parse_ipv4_route (const char *route, GError **error)
-{
-	return nmc_parse_and_build_route (AF_INET, route, error);
-}
-
-static gboolean
-nmc_property_ipv4_set_routes (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL, **iter;
-	NMIPRoute *ip4route;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, ",", 0);
-	for (iter = strv; iter && *iter; iter++) {
-		ip4route = _parse_ipv4_route (*iter, error);
-		if (!ip4route) {
-			g_strfreev (strv);
-			return FALSE;
-		}
-		nm_setting_ip_config_add_route (NM_SETTING_IP_CONFIG (setting), ip4route);
-		nm_ip_route_unref (ip4route);
-	}
-	g_strfreev (strv);
-	return TRUE;
-}
-
-static gboolean
-_validate_and_remove_ipv4_route (NMSettingIPConfig *setting,
-                                 const char *route,
-                                 GError **error)
-{
-	NMIPRoute *ip4route;
-	gboolean ret;
-
-	ip4route = _parse_ipv4_route (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 (nmc_property_ipv4_remove_routes,
-                               NM_SETTING_IP_CONFIG,
-                               nm_setting_ip_config_get_num_routes,
-                               nm_setting_ip_config_remove_route,
-                               _validate_and_remove_ipv4_route)
-
-static const char *
-nmc_property_ipv4_describe_routes (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-
-/* --- NM_SETTING_IP6_CONFIG_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_ipv6_get_method, NM_SETTING_IP_CONFIG_METHOD)
-DEFINE_GETTER (nmc_property_ipv6_get_dns, NM_SETTING_IP_CONFIG_DNS)
-DEFINE_GETTER (nmc_property_ipv6_get_dns_search, NM_SETTING_IP_CONFIG_DNS_SEARCH)
-DEFINE_GETTER_WITH_DEFAULT (nmc_property_ipv6_get_dns_options, NM_SETTING_IP_CONFIG_DNS_OPTIONS, !nm_setting_ip_config_has_dns_options ((NMSettingIPConfig *) setting))
-DEFINE_GETTER (nmc_property_ipv6_get_dns_priority, NM_SETTING_IP_CONFIG_DNS_PRIORITY)
-
-static char *
-nmc_property_ipv6_get_routes (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	return nmc_property_ipvx_get_routes (setting, get_type);
-}
-
-DEFINE_GETTER (nmc_property_ipv6_get_gateway, NM_SETTING_IP_CONFIG_GATEWAY)
-DEFINE_GETTER (nmc_property_ipv6_get_route_metric, NM_SETTING_IP_CONFIG_ROUTE_METRIC)
-DEFINE_GETTER (nmc_property_ipv6_get_ignore_auto_routes, NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES)
-DEFINE_GETTER (nmc_property_ipv6_get_ignore_auto_dns, NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS)
-DEFINE_GETTER (nmc_property_ipv6_get_never_default, NM_SETTING_IP_CONFIG_NEVER_DEFAULT)
-DEFINE_GETTER (nmc_property_ipv6_get_may_fail, NM_SETTING_IP_CONFIG_MAY_FAIL)
-DEFINE_GETTER (nmc_property_ipv6_get_dhcp_send_hostname, NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME)
-DEFINE_GETTER (nmc_property_ipv6_get_dhcp_hostname, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME)
-DEFINE_GETTER (nmc_property_ipv6_get_token, NM_SETTING_IP6_CONFIG_TOKEN)
-
-static char *
-nmc_property_ipv6_get_ip6_privacy (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG (setting);
-	return ip6_privacy_to_string (nm_setting_ip6_config_get_ip6_privacy (s_ip6), get_type);
-}
-
-/* 'method' */
-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
-nmc_property_ipv6_set_method (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	/* Silently accept "static" and convert to "manual" */
-	if (val && strlen (val) > 1 && matches (val, "static"))
-		val = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
-
-	return check_and_set_string (setting, prop, val, ipv6_valid_methods, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_ipv6_allowed_method, ipv6_valid_methods)
-
-/* 'dns' */
-static gboolean
-nmc_property_ipv6_set_dns (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL, **iter, *addr;
-	struct in6_addr ip6_addr;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, " \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 (nmc_property_ipv6_remove_dns,
-                               NM_SETTING_IP_CONFIG,
-                               nm_setting_ip_config_get_num_dns,
-                               nm_setting_ip_config_remove_dns,
-                               _validate_and_remove_ipv6_dns)
-
-static const char *
-nmc_property_ipv6_describe_dns (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'dns-search' */
-static gboolean
-nmc_property_ipv6_set_dns_search (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL;
-	guint i = 0;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, " \t,", 0);
-	if (!verify_string_list (strv, prop, 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 (nmc_property_ipv6_remove_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)
-
-/* 'dns-options' */
-static gboolean
-nmc_property_ipv6_set_dns_options (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 (val, " \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 (nmc_property_ipv6_remove_dns_option,
-                               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)
-
-/* 'addresses' */
-static NMIPAddress *
-_parse_ipv6_address (const char *address, GError **error)
-{
-	return _parse_ip_address (AF_INET6, address, error);
-}
-
-static gboolean
-nmc_property_ipv6_set_addresses (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL, **iter;
-	NMIPAddress *ip6addr;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, ",", 0);
-	for (iter = strv; iter && *iter; iter++) {
-		ip6addr = _parse_ipv6_address (*iter, error);
-		if (!ip6addr) {
-			g_strfreev (strv);
-			return FALSE;
-		}
-		nm_setting_ip_config_add_address (NM_SETTING_IP_CONFIG (setting), ip6addr);
-		nm_ip_address_unref (ip6addr);
-	}
-	g_strfreev (strv);
-	return TRUE;
-}
-
-static gboolean
-_validate_and_remove_ipv6_address (NMSettingIPConfig *setting,
-                                   const char *address,
-                                   GError **error)
-{
-	NMIPAddress *ip6addr;
-	gboolean ret;
-
-	ip6addr = _parse_ipv6_address (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 (nmc_property_ipv6_remove_addresses,
-                               NM_SETTING_IP_CONFIG,
-                               nm_setting_ip_config_get_num_addresses,
-                               nm_setting_ip_config_remove_address,
-                               _validate_and_remove_ipv6_address)
-
-static const char *
-nmc_property_ipv6_describe_addresses (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-/* 'gateway' */
-static gboolean
-nmc_property_ipv6_set_gateway (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	NMIPAddress *ip6addr;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (strchr (val, '/')) {
-		g_set_error (error, 1, 0,
-	                     _("invalid gateway address '%s'"), val);
-		return FALSE;
-	}
-	ip6addr = _parse_ipv6_address (val, error);
-	if (!ip6addr)
-		return FALSE;
-
-	g_object_set (setting, prop, val, NULL);
-	nm_ip_address_unref (ip6addr);
-	return TRUE;
-}
-
-/* 'routes' */
-static NMIPRoute *
-_parse_ipv6_route (const char *route, GError **error)
-{
-	return nmc_parse_and_build_route (AF_INET6, route, error);
-}
-
-static gboolean
-nmc_property_ipv6_set_routes (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL, **iter;
-	NMIPRoute *ip6route;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	strv = nmc_strsplit_set (val, ",", 0);
-	for (iter = strv; iter && *iter; iter++) {
-		ip6route = _parse_ipv6_route (*iter, error);
-		if (!ip6route) {
-			g_strfreev (strv);
-			return FALSE;
-		}
-		nm_setting_ip_config_add_route (NM_SETTING_IP_CONFIG (setting), ip6route);
-		nm_ip_route_unref (ip6route);
-	}
-	g_strfreev (strv);
-	return TRUE;
-}
-
-static gboolean
-_validate_and_remove_ipv6_route (NMSettingIPConfig *setting,
-                                 const char *route,
-                                 GError **error)
-{
-	NMIPRoute *ip6route;
-	gboolean ret;
-
-	ip6route = _parse_ipv6_route (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 (nmc_property_ipv6_remove_routes,
-                               NM_SETTING_IP_CONFIG,
-                               nm_setting_ip_config_get_num_routes,
-                               nm_setting_ip_config_remove_route,
-                               _validate_and_remove_ipv6_route)
-
-static const char *
-nmc_property_ipv6_describe_routes (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-static gboolean
-nmc_property_ipv6_set_ip6_privacy (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	unsigned long val_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_uint (val, FALSE, 0, 0, &val_int)) {
-		g_set_error (error, 1, 0, _("'%s' is not a number"), val);
-		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"), val);
-		return FALSE;
-	}
-
-	g_object_set (setting, prop, val_int, NULL);
-	return TRUE;
-}
-
-/* 'addr_gen_mode' */
-static char *
-nmc_property_ipv6_get_addr_gen_mode (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG (setting);
-	NMSettingIP6ConfigAddrGenMode addr_gen_mode;
-
-	addr_gen_mode = nm_setting_ip6_config_get_addr_gen_mode (s_ip6);
-	return nm_utils_enum_to_str (nm_setting_ip6_config_addr_gen_mode_get_type (), addr_gen_mode);
-}
-
-
-static gboolean
-nmc_property_ipv6_set_addr_gen_mode (NMSetting *setting, const char *prop,
-                                     const char *val, GError **error)
-{
-	NMSettingIP6ConfigAddrGenMode addr_gen_mode;
-
-	if (!nm_utils_enum_from_str (nm_setting_ip6_config_addr_gen_mode_get_type (), val,
-	                             (int *) &addr_gen_mode, NULL)) {
-		g_set_error (error, 1, 0, _("invalid option '%s', use one of [%s]"),
-		             val, "eui64,stable-privacy");
-			return FALSE;
-	}
-
-	g_object_set (setting, prop, addr_gen_mode, NULL);
-	return TRUE;
-}
-
-DEFINE_ALLOWED_FOR_ENUMS (nmc_property_ipv6_allowed_addr_gen_mode,
-                          nm_setting_ip6_config_addr_gen_mode_get_type,
-                          G_MININT, G_MAXINT)
-
-
-/* --- NM_SETTING_MACSEC_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_macsec_get_parent, NM_SETTING_MACSEC_PARENT)
-DEFINE_GETTER (nmc_property_macsec_get_encrypt, NM_SETTING_MACSEC_ENCRYPT)
-DEFINE_GETTER (nmc_property_macsec_get_mka_cak, NM_SETTING_MACSEC_MKA_CAK)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_macsec_get_mka_cak_flags, NM_SETTING_MACSEC_MKA_CAK_FLAGS)
-DEFINE_GETTER (nmc_property_macsec_get_mka_ckn, NM_SETTING_MACSEC_MKA_CKN)
-DEFINE_GETTER (nmc_property_macsec_get_port, NM_SETTING_MACSEC_PORT)
-
-/* 'mode' */
-static char *
-nmc_property_macsec_get_mode (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingMacsec *s_macsec = NM_SETTING_MACSEC (setting);
-	NMSettingMacsecMode mode;
-
-	mode = nm_setting_macsec_get_mode (s_macsec);
-	return nm_utils_enum_to_str (nm_setting_macsec_mode_get_type (), mode);
-}
-
-static gboolean
-nmc_property_macsec_set_mode (NMSetting *setting, const char *prop,
-                              const char *val, GError **error)
-{
-	NMSettingMacsecMode mode;
-	gs_free char *options = NULL;
-
-	if (!nm_utils_enum_from_str (nm_setting_macsec_mode_get_type (), val,
-	                             (int *) &mode, NULL)) {
-		options = g_strjoinv (",",
-		                      (char **) nm_utils_enum_get_values (nm_setting_macsec_mode_get_type (),
-		                                                          G_MININT,
-		                                                          G_MAXINT));
-		g_set_error (error, 1, 0, _("invalid option '%s', use one of [%s]"),
-		             val, options);
-			return FALSE;
-	}
-
-	g_object_set (setting, prop, mode, NULL);
-	return TRUE;
-}
-
-DEFINE_ALLOWED_FOR_ENUMS (nmc_property_macsec_allowed_mode,
-                          nm_setting_macsec_mode_get_type,
-                          G_MININT, G_MAXINT)
-
-/* 'validation' */
-static char *
-nmc_property_macsec_get_validation (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingMacsec *s_macsec = NM_SETTING_MACSEC (setting);
-	NMSettingMacsecValidation validation;
-
-	validation = nm_setting_macsec_get_validation (s_macsec);
-	return nm_utils_enum_to_str (nm_setting_macsec_validation_get_type (), validation);
-}
-
-static gboolean
-nmc_property_macsec_set_validation (NMSetting *setting, const char *prop,
-                                    const char *val, GError **error)
-{
-	NMSettingMacsecMode validation;
-	gs_free char *options = NULL;
-
-	if (!nm_utils_enum_from_str (nm_setting_macsec_validation_get_type (), val,
-	                             (int *) &validation, NULL)) {
-		options = g_strjoinv (",",
-		                      (char **) nm_utils_enum_get_values (nm_setting_macsec_validation_get_type (),
-		                                                          G_MININT,
-		                                                          G_MAXINT));
-		g_set_error (error, 1, 0, _("invalid option '%s', use one of [%s]"),
-		             val, options);
-			return FALSE;
-	}
-
-	g_object_set (setting, prop, validation, NULL);
-	return TRUE;
-}
-
-DEFINE_ALLOWED_FOR_ENUMS (nmc_property_macsec_allowed_validation,
-                          nm_setting_macsec_validation_get_type,
-                          G_MININT, G_MAXINT)
-
-
-/* --- NM_SETTING_MACVLAN_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_macvlan_get_parent, NM_SETTING_MACVLAN_PARENT)
-DEFINE_GETTER (nmc_property_macvlan_get_promiscuous, NM_SETTING_MACVLAN_PROMISCUOUS)
-DEFINE_GETTER (nmc_property_macvlan_get_tap, NM_SETTING_MACVLAN_TAP)
-
-static char *
-nmc_property_macvlan_get_mode (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingMacvlan *s_macvlan = NM_SETTING_MACVLAN (setting);
-	NMSettingMacvlanMode mode;
-	char *tmp, *str;
-
-	mode = nm_setting_macvlan_get_mode (s_macvlan);
-	tmp = nm_utils_enum_to_str (nm_setting_macvlan_mode_get_type (), mode);
-
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		str = g_strdup (tmp ? tmp : "");
-	else
-		str = g_strdup_printf ("%d (%s)", mode, tmp ? tmp : "");
-	g_free (tmp);
-
-	return str;
-}
-
-static gboolean
-nmc_property_macvlan_set_mode (NMSetting *setting, const char *prop,
-                               const char *val, GError **error)
-{
-	NMSettingMacvlanMode mode;
-	gs_free const char **options = NULL;
-	gs_free char *options_str = NULL;
-	long int t;
-	gboolean ret;
-
-	if (nmc_string_to_int_base (val, 0, TRUE, 0, _NM_SETTING_MACVLAN_MODE_NUM - 1, &t))
-		mode = (NMSettingMacvlanMode) t;
-	else {
-		ret = nm_utils_enum_from_str (nm_setting_macvlan_mode_get_type (), val,
-		                              (int *) &mode, NULL);
-
-		if (!ret) {
-				options = nm_utils_enum_get_values (nm_setting_macvlan_mode_get_type(),
-				                                    NM_SETTING_MACVLAN_MODE_UNKNOWN + 1,
-				                                    G_MAXINT);
-				options_str = g_strjoinv (",", (char **) options);
-				g_set_error (error, 1, 0, _("invalid option '%s', use one of [%s]"),
-				             val, options_str);
-				return FALSE;
-			}
-		}
-
-	g_object_set (setting, prop, (guint) mode, NULL);
-	return TRUE;
-}
-
-DEFINE_ALLOWED_FOR_ENUMS (nmc_property_macvlan_allowed_mode,
-                          nm_setting_macvlan_mode_get_type,
-                          NM_SETTING_MACVLAN_MODE_UNKNOWN + 1, G_MAXINT)
-
-
-/* --- NM_SETTING_OLPC_MESH_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_olpc_get_channel, NM_SETTING_OLPC_MESH_CHANNEL)
-DEFINE_GETTER (nmc_property_olpc_get_anycast_address, NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS)
-
-static char *
-nmc_property_olpc_get_ssid (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingOlpcMesh *s_olpc_mesh = NM_SETTING_OLPC_MESH (setting);
-	GBytes *ssid;
-	char *ssid_str = NULL;
-
-	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 ssid_str;
-}
-
-static gboolean
-nmc_property_olpc_set_channel (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	unsigned long chan_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_uint (val, TRUE, 1, 13, &chan_int)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid channel; use <1-13>"), val);
-		return FALSE;
-	}
-	g_object_set (setting, prop, chan_int, NULL);
-	return TRUE;
-}
-
-
-/* --- NM_SETTING_PPP_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_ppp_get_noauth, NM_SETTING_PPP_NOAUTH)
-DEFINE_GETTER (nmc_property_ppp_get_refuse_eap, NM_SETTING_PPP_REFUSE_EAP)
-DEFINE_GETTER (nmc_property_ppp_get_refuse_pap, NM_SETTING_PPP_REFUSE_PAP)
-DEFINE_GETTER (nmc_property_ppp_get_refuse_chap, NM_SETTING_PPP_REFUSE_CHAP)
-DEFINE_GETTER (nmc_property_ppp_get_refuse_mschap, NM_SETTING_PPP_REFUSE_MSCHAP)
-DEFINE_GETTER (nmc_property_ppp_get_refuse_mschapv2, NM_SETTING_PPP_REFUSE_MSCHAPV2)
-DEFINE_GETTER (nmc_property_ppp_get_nobsdcomp, NM_SETTING_PPP_NOBSDCOMP)
-DEFINE_GETTER (nmc_property_ppp_get_nodeflate, NM_SETTING_PPP_NODEFLATE)
-DEFINE_GETTER (nmc_property_ppp_get_no_vj_comp, NM_SETTING_PPP_NO_VJ_COMP)
-DEFINE_GETTER (nmc_property_ppp_get_require_mppe, NM_SETTING_PPP_REQUIRE_MPPE)
-DEFINE_GETTER (nmc_property_ppp_get_require_mppe_128, NM_SETTING_PPP_REQUIRE_MPPE_128)
-DEFINE_GETTER (nmc_property_ppp_get_mppe_stateful, NM_SETTING_PPP_MPPE_STATEFUL)
-DEFINE_GETTER (nmc_property_ppp_get_crtscts, NM_SETTING_PPP_CRTSCTS)
-DEFINE_GETTER (nmc_property_ppp_get_baud, NM_SETTING_PPP_BAUD)
-DEFINE_GETTER (nmc_property_ppp_get_mru, NM_SETTING_PPP_MRU)
-DEFINE_GETTER (nmc_property_ppp_get_mtu, NM_SETTING_PPP_MTU)
-DEFINE_GETTER (nmc_property_ppp_get_lcp_echo_failure, NM_SETTING_PPP_LCP_ECHO_FAILURE)
-DEFINE_GETTER (nmc_property_ppp_get_lcp_echo_interval, NM_SETTING_PPP_LCP_ECHO_INTERVAL)
-
-
-/* --- NM_SETTING_PPPOE_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_pppoe_get_service, NM_SETTING_PPPOE_SERVICE)
-DEFINE_GETTER (nmc_property_pppoe_get_username, NM_SETTING_PPPOE_USERNAME)
-DEFINE_GETTER (nmc_property_pppoe_get_password, NM_SETTING_PPPOE_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_pppoe_get_password_flags, NM_SETTING_PPPOE_PASSWORD_FLAGS)
-
-
-/* --- NM_SETTING_PROXY_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_proxy_get_browser_only, NM_SETTING_PROXY_BROWSER_ONLY)
-DEFINE_GETTER (nmc_property_proxy_get_pac_url, NM_SETTING_PROXY_PAC_URL)
-DEFINE_GETTER (nmc_property_proxy_get_pac_script, NM_SETTING_PROXY_PAC_SCRIPT)
-
-static char *
-nmc_property_proxy_get_method (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingProxy *s_proxy = NM_SETTING_PROXY (setting);
-	NMSettingProxyMethod method;
-
-	method = nm_setting_proxy_get_method (s_proxy);
-	return nm_utils_enum_to_str (nm_setting_proxy_method_get_type (), method);
-}
-
-static gboolean
-nmc_property_proxy_set_method (NMSetting *setting, const char *prop,
-                               const char *val, GError **error)
-{
-	int method;
-	gboolean ret;
-
-	ret = nm_utils_enum_from_str (nm_setting_proxy_method_get_type(), val,
-	                              &method, NULL);
-
-	if (!ret) {
-		gs_free const char **values = NULL;
-		gs_free char *values_str = NULL;
-
-		values = nm_utils_enum_get_values (nm_setting_proxy_method_get_type (),
-		                                   NM_SETTING_PROXY_METHOD_NONE,
-		                                   G_MAXINT);
-		values_str = g_strjoinv (",", (char **) values);
-		g_set_error (error, 1, 0, _("invalid method '%s', use one of %s"),
-		             val, values_str);
-
-		return FALSE;
-	}
-
-	g_object_set (setting, prop, method, NULL);
-	return TRUE;
-}
-
-DEFINE_ALLOWED_FOR_ENUMS (nmc_property_proxy_allowed_method,
-                          nm_setting_proxy_method_get_type,
-                          NM_SETTING_PROXY_METHOD_NONE, G_MAXINT)
-
-static gboolean
-nmc_property_proxy_set_pac_script (NMSetting *setting, const char *prop,
-                                   const char *val, GError **error)
-{
-	char *script = NULL;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_proxy_check_script (val, &script, error)) {
-		return FALSE;
-	}
-	g_object_set (setting, prop, script, NULL);
-	g_free (script);
-	return TRUE;
-}
-
-
-/* --- NM_SETTING_SERIAL_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_serial_get_baud, NM_SETTING_SERIAL_BAUD)
-DEFINE_GETTER (nmc_property_serial_get_bits, NM_SETTING_SERIAL_BITS)
-DEFINE_GETTER (nmc_property_serial_get_stopbits, NM_SETTING_SERIAL_STOPBITS)
-DEFINE_GETTER (nmc_property_serial_get_send_delay, NM_SETTING_SERIAL_SEND_DELAY)
-
-static char *
-nmc_property_serial_get_parity (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingSerial *s_serial = NM_SETTING_SERIAL (setting);
-
-	switch (nm_setting_serial_get_parity (s_serial)) {
-	case NM_SETTING_SERIAL_PARITY_EVEN:
-		return g_strdup ("even");
-	case NM_SETTING_SERIAL_PARITY_ODD:
-		return g_strdup ("odd");
-	default:
-	case NM_SETTING_SERIAL_PARITY_NONE:
-		return g_strdup ("none");
-	}
-}
-
-static gboolean
-nmc_property_serial_set_parity (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	NMSettingSerialParity parity;
-
-	if (val[0] == 'E' || val[0] == 'e')
-		parity = NM_SETTING_SERIAL_PARITY_EVEN;
-	else if (val[0] == 'O' || val[0] == 'o')
-		parity = NM_SETTING_SERIAL_PARITY_ODD;
-	else if (val[0] == 'N' || val[0] == 'n')
-		parity = NM_SETTING_SERIAL_PARITY_NONE;
-	else {
-		g_set_error (error, 1, 0, _("'%s' is not valid; use [e, o, n]"), val);
-		return FALSE;
-	}
-
-	g_object_set (setting, prop, parity, NULL);
-	return TRUE;
-}
-
-
-/* --- NM_SETTING_TEAM_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_team_get_config, NM_SETTING_TEAM_CONFIG)
-
-static gboolean
-nmc_property_team_set_config (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char *json = NULL;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_team_check_config (val, &json, error)) {
-		return FALSE;
-	}
-	g_object_set (setting, prop, json, NULL);
-	g_free (json);
-	return TRUE;
-}
-
-static const char *
-nmc_property_team_describe_config (NMSetting *setting, const char *prop)
-{
-	return _("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");
-}
-
-
-/* --- NM_SETTING_TEAM_PORT_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_team_port_get_config, NM_SETTING_TEAM_PORT_CONFIG)
-
-
-/* --- NM_SETTING_TUN_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_tun_get_owner, NM_SETTING_TUN_OWNER);
-DEFINE_GETTER (nmc_property_tun_get_group, NM_SETTING_TUN_GROUP);
-DEFINE_GETTER (nmc_property_tun_get_pi, NM_SETTING_TUN_PI);
-DEFINE_GETTER (nmc_property_tun_get_vnet_hdr, NM_SETTING_TUN_VNET_HDR);
-DEFINE_GETTER (nmc_property_tun_get_multi_queue, NM_SETTING_TUN_MULTI_QUEUE);
-
-static char *
-nmc_property_tun_get_mode (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingTun *s_tun = NM_SETTING_TUN (setting);
-	NMSettingTunMode mode;
-	char *tmp, *str;
-
-	mode = nm_setting_tun_get_mode (s_tun);
-	tmp = nm_utils_enum_to_str (nm_setting_tun_mode_get_type (), mode);
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		str = g_strdup_printf ("%s", tmp ? tmp : "");
-	else
-		str = g_strdup_printf ("%d (%s)", mode, tmp ? tmp : "");
-	g_free (tmp);
-	return str;
-}
-
-static gboolean
-nmc_property_tun_set_mode (NMSetting *setting, const char *prop,
-                           const char *val, GError **error)
-{
-	NMSettingTunMode mode;
-	gboolean ret;
-	long int t;
-
-	if (nmc_string_to_int_base (val, 0, TRUE, 0, NM_SETTING_TUN_MODE_TAP, &t))
-		mode = (NMSettingTunMode) t;
-	else {
-		ret = nm_utils_enum_from_str (nm_setting_tun_mode_get_type (), val,
-		                              (int *) &mode, NULL);
-
-		if (!ret) {
-			g_set_error (error, 1, 0, _("invalid option '%s', use '%s' or '%s'"),
-			             val, "tun", "tap");
-			return FALSE;
-		}
-	}
-
-	g_object_set (setting, prop, (guint) mode, NULL);
-	return TRUE;
-}
-
-static const char *tun_valid_modes[] = { "tun", "tap", "unknown", NULL };
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_tun_allowed_mode, tun_valid_modes)
-
-
-/* --- NM_SETTING_VLAN_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_vlan_get_parent, NM_SETTING_VLAN_PARENT)
-DEFINE_GETTER (nmc_property_vlan_get_id, NM_SETTING_VLAN_ID)
-
-static char *
-nmc_property_vlan_get_flags (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingVlan *s_vlan = NM_SETTING_VLAN (setting);
-	return vlan_flags_to_string (nm_setting_vlan_get_flags (s_vlan), get_type);
-}
-
-static char *
-nmc_property_vlan_get_ingress_priority_map (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingVlan *s_vlan = NM_SETTING_VLAN (setting);
-	return vlan_priorities_to_string (s_vlan, NM_VLAN_INGRESS_MAP);
-}
-
-static char *
-nmc_property_vlan_get_egress_priority_map (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingVlan *s_vlan = NM_SETTING_VLAN (setting);
-	return vlan_priorities_to_string (s_vlan, NM_VLAN_EGRESS_MAP);
-}
-
-static gboolean
-nmc_property_vlan_set_prio_map (NMSetting *setting,
-                                const char *prop,
-                                const char *val,
-                                NMVlanPriorityMap map_type,
-                                GError **error)
-{
-	char **prio_map, **p;
-
-	prio_map = nmc_vlan_parse_priority_maps (val, 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
-nmc_property_vlan_remove_prio_map (NMSetting *setting,
-                                   const char *prop,
-                                   guint32 idx,
-                                   NMVlanPriorityMap map_type,
-                                   GError **error)
-{
-	guint32 num;
-
-	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
-nmc_property_vlan_set_ingress_priority_map (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return nmc_property_vlan_set_prio_map (setting, prop, val, NM_VLAN_INGRESS_MAP, error);
-}
-
-static gboolean
-nmc_property_vlan_set_egress_priority_map (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return nmc_property_vlan_set_prio_map (setting, prop, val, NM_VLAN_EGRESS_MAP, error);
-}
-
-static gboolean
-nmc_property_vlan_remove_priority_map (NMSetting *setting,
-                                       const char *prop,
-                                       const char *value,
-                                       guint32 idx,
-                                       NMVlanPriorityMap map,
-                                       GError **error)
-{
-	/* If value != NULL, remove by value */
-	if (value) {
-		gboolean ret;
-		char **prio_map;
-		char *val = g_strdup (value);
-
-		prio_map = nmc_vlan_parse_priority_maps (val, map, error);
-		if (!prio_map)
-			return FALSE;
-		if (prio_map[1])
-			g_print (_("Warning: only one mapping at a time is supported; taking the first one (%s)\n"),
-			         prio_map[0]);
-		ret = nm_setting_vlan_remove_priority_str_by_value (NM_SETTING_VLAN (setting),
-		                                                    map,
-		                                                    prio_map[0]);
-
-		if (!ret)
-			g_set_error (error, 1, 0, _("the property doesn't contain mapping '%s'"), prio_map[0]);
-		g_free (val);
-		g_strfreev (prio_map);
-		return ret;
-	}
-
-	/* Else remove by index */
-	return nmc_property_vlan_remove_prio_map (setting, prop, idx, map, error);
-}
-
-static gboolean
-nmc_property_vlan_remove_ingress_priority_map (NMSetting *setting,
-                                               const char *prop,
-                                               const char *value,
-                                               guint32 idx,
-                                               GError **error)
-{
-	return nmc_property_vlan_remove_priority_map (setting,
-                                                      prop,
-                                                      value,
-                                                      idx,
-                                                      NM_VLAN_INGRESS_MAP,
-                                                      error);
-}
-
-static gboolean
-nmc_property_vlan_remove_egress_priority_map (NMSetting *setting,
-                                              const char *prop,
-                                              const char *value,
-                                              guint32 idx,
-                                              GError **error)
-{
-	return nmc_property_vlan_remove_priority_map (setting,
-                                                      prop,
-                                                      value,
-                                                      idx,
-                                                      NM_VLAN_EGRESS_MAP,
-                                                      error);
-}
-
-
-/* --- NM_SETTING_VPN_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_vpn_get_service_type, NM_SETTING_VPN_SERVICE_TYPE)
-DEFINE_GETTER (nmc_property_vpn_get_user_name, NM_SETTING_VPN_USER_NAME)
-
-static char *
-nmc_property_vpn_get_data (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingVpn *s_vpn = NM_SETTING_VPN (setting);
-	GString *data_item_str;
-
-	data_item_str = g_string_new (NULL);
-	nm_setting_vpn_foreach_data_item (s_vpn, &vpn_data_item, data_item_str);
-
-	return g_string_free (data_item_str, FALSE);
-}
-
-static char *
-nmc_property_vpn_get_secrets (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingVpn *s_vpn = NM_SETTING_VPN (setting);
-	GString *secret_str;
-
-	secret_str = g_string_new (NULL);
-	nm_setting_vpn_foreach_secret (s_vpn, &vpn_data_item, secret_str);
-
-	return g_string_free (secret_str, FALSE);
-}
-
-DEFINE_GETTER (nmc_property_vpn_get_persistent, NM_SETTING_VPN_PERSISTENT)
-DEFINE_GETTER (nmc_property_vpn_get_timeout, NM_SETTING_VPN_TIMEOUT)
-
-/* Validate value of vpn 'data' and 'secret' options */
-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;
-}
-
-/* 'data' */
-DEFINE_SETTER_OPTIONS (nmc_property_vpn_set_data,
-                       NM_SETTING_VPN,
-                       NMSettingVpn,
-                       nm_setting_vpn_add_data_item,
-                       NULL,
-                       _validate_vpn_hash_value)
-DEFINE_REMOVER_OPTION (nmc_property_vpn_remove_option_data,
-                       NM_SETTING_VPN,
-                       nm_setting_vpn_remove_data_item)
-
-/* 'secrets' */
-DEFINE_SETTER_OPTIONS (nmc_property_vpn_set_secrets,
-                       NM_SETTING_VPN,
-                       NMSettingVpn,
-                       nm_setting_vpn_add_secret,
-                       NULL,
-                       _validate_vpn_hash_value)
-DEFINE_REMOVER_OPTION (nmc_property_vpn_remove_option_secret,
-                       NM_SETTING_VPN,
-                       nm_setting_vpn_remove_secret)
-
-
-/* --- NM_SETTING_VXLAN_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_vxlan_get_parent, NM_SETTING_VXLAN_PARENT)
-DEFINE_GETTER (nmc_property_vxlan_get_id, NM_SETTING_VXLAN_ID)
-DEFINE_GETTER (nmc_property_vxlan_get_local, NM_SETTING_VXLAN_LOCAL)
-DEFINE_GETTER (nmc_property_vxlan_get_remote, NM_SETTING_VXLAN_REMOTE)
-DEFINE_GETTER (nmc_property_vxlan_get_source_port_min, NM_SETTING_VXLAN_SOURCE_PORT_MIN)
-DEFINE_GETTER (nmc_property_vxlan_get_source_port_max, NM_SETTING_VXLAN_SOURCE_PORT_MAX)
-DEFINE_GETTER (nmc_property_vxlan_get_destination_port, NM_SETTING_VXLAN_DESTINATION_PORT)
-DEFINE_GETTER (nmc_property_vxlan_get_tos, NM_SETTING_VXLAN_TOS)
-DEFINE_GETTER (nmc_property_vxlan_get_ttl, NM_SETTING_VXLAN_TTL)
-DEFINE_GETTER (nmc_property_vxlan_get_ageing, NM_SETTING_VXLAN_AGEING)
-DEFINE_GETTER (nmc_property_vxlan_get_limit, NM_SETTING_VXLAN_LIMIT)
-DEFINE_GETTER (nmc_property_vxlan_get_learning, NM_SETTING_VXLAN_LEARNING)
-DEFINE_GETTER (nmc_property_vxlan_get_proxy, NM_SETTING_VXLAN_PROXY)
-DEFINE_GETTER (nmc_property_vxlan_get_rsc, NM_SETTING_VXLAN_RSC)
-DEFINE_GETTER (nmc_property_vxlan_get_l2_miss, NM_SETTING_VXLAN_L2_MISS)
-DEFINE_GETTER (nmc_property_vxlan_get_l3_miss, NM_SETTING_VXLAN_L3_MISS)
-
-
-/* --- NM_SETTING_WIMAX_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_wimax_get_network_name, NM_SETTING_WIMAX_NETWORK_NAME)
-DEFINE_GETTER (nmc_property_wimax_get_mac_address, NM_SETTING_WIMAX_MAC_ADDRESS)
-
-
-/* --- NM_SETTING_WIRED_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_wired_get_port, NM_SETTING_WIRED_PORT)
-DEFINE_GETTER (nmc_property_wired_get_auto_negotiate, NM_SETTING_WIRED_AUTO_NEGOTIATE)
-DEFINE_GETTER (nmc_property_wired_get_mac_address, NM_SETTING_WIRED_MAC_ADDRESS)
-DEFINE_GETTER (nmc_property_wired_get_cloned_mac_address, NM_SETTING_WIRED_CLONED_MAC_ADDRESS)
-DEFINE_GETTER (nmc_property_wired_get_generate_mac_address_mask, NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK)
-DEFINE_GETTER (nmc_property_wired_get_mac_address_blacklist, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST)
-DEFINE_GETTER (nmc_property_wired_get_s390_subchannels, NM_SETTING_WIRED_S390_SUBCHANNELS)
-DEFINE_GETTER (nmc_property_wired_get_s390_nettype, NM_SETTING_WIRED_S390_NETTYPE)
-DEFINE_GETTER (nmc_property_wired_get_s390_options, NM_SETTING_WIRED_S390_OPTIONS)
-DEFINE_GETTER (nmc_property_wired_get_wake_on_lan_password, NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD)
-
-static char *
-nmc_property_wired_get_speed (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWired *s_wired = NM_SETTING_WIRED (setting);
-	guint32 speed;
-
-	speed = nm_setting_wired_get_speed (s_wired);
-	return g_strdup_printf ("%d", speed);
-}
-
-static char *
-nmc_property_wired_get_duplex (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWired *s_wired = NM_SETTING_WIRED (setting);
-	const char *str;
-
-	str = nm_setting_wired_get_duplex (s_wired);
-	if (!str)
-		return NULL;
-	else
-		return g_strdup (str);
-
-}
-
-static char *
-nmc_property_wired_get_mtu (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWired *s_wired = NM_SETTING_WIRED (setting);
-	int mtu;
-
-	mtu = nm_setting_wired_get_mtu (s_wired);
-	if (mtu == 0)
-		return g_strdup (_("auto"));
-	else
-		return g_strdup_printf ("%d", mtu);
-}
-
-static char *
-nmc_property_wired_get_wake_on_lan (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWired *s_wired = NM_SETTING_WIRED (setting);
-	NMSettingWiredWakeOnLan wol;
-	char *tmp, *str;
-
-	wol = nm_setting_wired_get_wake_on_lan (s_wired);
-	tmp = nm_utils_enum_to_str (nm_setting_wired_wake_on_lan_get_type (), wol);
-	if (get_type == NMC_PROPERTY_GET_PARSABLE)
-		str = g_strdup_printf ("%s", tmp && *tmp ? tmp : "none");
-	else
-		str = g_strdup_printf ("%d (%s)", wol, tmp && *tmp ? tmp : "none");
-	g_free (tmp);
-	return str;
-}
-
-static gboolean
-nmc_property_wired_set_wake_on_lan (NMSetting *setting, const char *prop,
-                                    const char *val, GError **error)
-{
-	NMSettingWiredWakeOnLan wol;
-	gs_free char *err_token = NULL;
-	gboolean ret;
-	long int t;
-
-	if (nmc_string_to_int_base (val, 0, TRUE, 0,
-	                            NM_SETTING_WIRED_WAKE_ON_LAN_ALL
-	                            | NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS,
-	                            &t))
-		wol = (NMSettingWiredWakeOnLan) t;
-	else {
-		ret = nm_utils_enum_from_str (nm_setting_wired_wake_on_lan_get_type (), val,
-		                              (int *) &wol, &err_token);
-
-		if (!ret) {
-			if (   g_ascii_strcasecmp (err_token, "none") == 0
-			    || g_ascii_strcasecmp (err_token, "disable") == 0
-			    || g_ascii_strcasecmp (err_token, "disabled") == 0)
-				wol = NM_SETTING_WIRED_WAKE_ON_LAN_NONE;
-			else {
-				g_set_error (error, 1, 0, _("invalid option '%s', use a combination of [%s] or 'ignore', 'default' or 'none'"),
-				             err_token,
-				             nm_utils_enum_to_str (nm_setting_wired_wake_on_lan_get_type (),
-				                                   NM_SETTING_WIRED_WAKE_ON_LAN_ALL));
-				return FALSE;
-			}
-		}
-	}
-
-	if (   NM_FLAGS_ANY (wol, NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS)
-	    && !nm_utils_is_power_of_two (wol)) {
-		g_set_error_literal (error, 1, 0, _("'default' and 'ignore' are incompatible with other flags"));
-		return FALSE;
-	}
-
-	g_object_set (setting, prop, (guint) wol, NULL);
-	return TRUE;
-}
-
-#if 0
--/*
-- * 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.
-- */
-/* 'port' */
-static const char *wired_valid_ports[] = { "tp", "aui", "bnc", "mii", NULL };
-
-static gboolean
-nmc_property_wired_set_port (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, wired_valid_ports, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wired_allowed_port, wired_valid_ports)
-#endif
-
-/* 'duplex' */
-static const char *wired_valid_duplexes[] = { "half", "full", NULL };
-
-static gboolean
-nmc_property_wired_set_duplex (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, wired_valid_duplexes, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wired_allowed_duplex, wired_valid_duplexes)
-
-
-/* 'mac-address-blacklist' */
-DEFINE_SETTER_MAC_BLACKLIST (nmc_property_wired_set_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 (nmc_property_wired_remove_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)
-
-/* 's390-subchannels' */
-static gboolean
-nmc_property_wired_set_s390_subchannels (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	char **strv = NULL;
-	int len;
-
-	strv = nmc_strsplit_set (val, " ,\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"),
-		             val);
-		g_strfreev (strv);
-		return FALSE;
-	}
-
-	g_object_set (setting, prop, strv, NULL);
-	g_strfreev (strv);
-	return TRUE;
-}
-
-static const char *
-nmc_property_wired_describe_s390_subchannels (NMSetting *setting, const char *prop)
-{
-	return _("Enter a list of subchannels (comma or space separated).\n\n"
-	         "Example: 0.0.0e20 0.0.0e21 0.0.0e22\n");
-}
-
-/* 's390-nettype' */
-static const char *wired_valid_s390_nettypes[] = { "qeth", "lcs", "ctc", NULL };
-
-static gboolean
-nmc_property_wired_set_s390_nettype (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, wired_valid_s390_nettypes, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wired_allowed_s390_nettype, wired_valid_s390_nettypes)
-
-/* 's390-options' */
-/* Validate value of 's390-options' */
-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 (nmc_property_wired_set_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 (nmc_property_wired_remove_option_s390_options,
-                       NM_SETTING_WIRED,
-                       nm_setting_wired_remove_s390_option)
-
-static const char **
-nmc_property_wired_allowed_s390_options (NMSetting *setting, const char *prop)
-{
-	return nm_setting_wired_get_valid_s390_options (NM_SETTING_WIRED (setting));
-}
-
-static const char *
-nmc_property_wired_describe_s390_options (NMSetting *setting, const char *prop)
-{
-	static char *desc = NULL;
-	const char **valid_options;
-	char *options_str;
-
-	if (G_UNLIKELY (desc == NULL)) {
-		valid_options = nm_setting_wired_get_valid_s390_options (NM_SETTING_WIRED (setting));
-		options_str = g_strjoinv (", ", (char **) valid_options);
-
-		desc = 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);
-		g_free (options_str);
-	}
-	return desc;
-}
-
-
-/* --- NM_SETTING_WIRELESS_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_wireless_get_mode, NM_SETTING_WIRELESS_MODE)
-DEFINE_GETTER (nmc_property_wireless_get_band, NM_SETTING_WIRELESS_BAND)
-DEFINE_GETTER (nmc_property_wireless_get_channel, NM_SETTING_WIRELESS_CHANNEL)
-DEFINE_GETTER (nmc_property_wireless_get_bssid, NM_SETTING_WIRELESS_BSSID)
-DEFINE_GETTER (nmc_property_wireless_get_rate, NM_SETTING_WIRELESS_RATE)
-DEFINE_GETTER (nmc_property_wireless_get_tx_power, NM_SETTING_WIRELESS_TX_POWER)
-DEFINE_GETTER (nmc_property_wireless_get_mac_address, NM_SETTING_WIRELESS_MAC_ADDRESS)
-DEFINE_GETTER (nmc_property_wireless_get_cloned_mac_address, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)
-DEFINE_GETTER (nmc_property_wireless_get_generate_mac_address_mask, NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK)
-DEFINE_GETTER (nmc_property_wireless_get_mac_address_blacklist, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST)
-DEFINE_GETTER (nmc_property_wireless_get_seen_bssids, NM_SETTING_WIRELESS_SEEN_BSSIDS)
-DEFINE_GETTER (nmc_property_wireless_get_hidden, NM_SETTING_WIRELESS_HIDDEN)
-
-static char *
-nmc_property_wireless_get_ssid (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWireless *s_wireless = NM_SETTING_WIRELESS (setting);
-	GBytes *ssid;
-	char *ssid_str = NULL;
-
-	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 ssid_str;
-}
-
-static char *
-nmc_property_wireless_get_mtu (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWireless *s_wireless = NM_SETTING_WIRELESS (setting);
-	int mtu;
-
-	mtu = nm_setting_wireless_get_mtu (s_wireless);
-	if (mtu == 0)
-		return g_strdup (_("auto"));
-	else
-		return g_strdup_printf ("%d", mtu);
-}
-
-static char *
-nmc_property_wireless_get_powersave (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWireless *s_wireless = NM_SETTING_WIRELESS (setting);
-	NMSettingWirelessPowersave powersave;
-	gs_free char *str = NULL;
-	char *ret;
-
-	powersave = nm_setting_wireless_get_powersave (s_wireless);
-	str = nm_utils_enum_to_str (nm_setting_wireless_powersave_get_type (), powersave);
-
-	if (get_type == NMC_PROPERTY_GET_PARSABLE) {
-		ret = str;
-		str = NULL;
-		return ret;
-	} else
-		return g_strdup_printf ("%s (%u)", str, powersave);
-}
-
-static char *
-nmc_property_wireless_get_mac_address_randomization (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWireless *s_wifi = NM_SETTING_WIRELESS (setting);
-	NMSettingMacRandomization randomization = nm_setting_wireless_get_mac_address_randomization (s_wifi);
-
-	if (randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT)
-		return g_strdup (_("default"));
-	else if (randomization == NM_SETTING_MAC_RANDOMIZATION_NEVER)
-		return g_strdup (_("never"));
-	else if (randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS)
-		return g_strdup_printf (_("always"));
-	else
-		return g_strdup_printf (_("unknown"));
-}
-
-/* 'mode' */
-static const char *wifi_valid_modes[] = {
-	NM_SETTING_WIRELESS_MODE_INFRA,
-	NM_SETTING_WIRELESS_MODE_ADHOC,
-	NM_SETTING_WIRELESS_MODE_AP,
-	NULL
-};
-
-static gboolean
-nmc_property_wifi_set_mode (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, wifi_valid_modes, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wifi_allowed_mode, wifi_valid_modes)
-
-/* 'band' */
-static const char *wifi_valid_bands[] = { "a", "bg", NULL };
-
-static gboolean
-nmc_property_wifi_set_band (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, wifi_valid_bands, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wifi_allowed_band, wifi_valid_bands)
-
-/* 'channel' */
-static gboolean
-nmc_property_wifi_set_channel (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	unsigned long chan_int;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_uint (val, FALSE, 0, 0, &chan_int)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid channel"), val);
-		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, prop, chan_int, NULL);
-	return TRUE;
-}
-
-/* 'mac-address-blacklist' */
-DEFINE_SETTER_MAC_BLACKLIST (nmc_property_wireless_set_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 (nmc_property_wireless_remove_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)
-
-/* 'powersave' */
-static gboolean
-nmc_property_wireless_set_powersave (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	NMSettingWirelessPowersave powersave;
-	gs_free const char **options = NULL;
-	gs_free char *options_str = NULL;
-	long int t;
-	gboolean ret;
-
-	if (nmc_string_to_int_base (val, 0, TRUE,
-	                            NM_SETTING_WIRELESS_POWERSAVE_DEFAULT,
-	                            NM_SETTING_WIRELESS_POWERSAVE_LAST,
-	                            &t))
-		powersave = (NMSettingWirelessPowersave) t;
-	else {
-		ret = nm_utils_enum_from_str (nm_setting_wireless_powersave_get_type (),
-		                              val,
-		                              (int *) &powersave,
-		                              NULL);
-		if (!ret) {
-			options = nm_utils_enum_get_values (nm_setting_wireless_powersave_get_type (),
-			                                    NM_SETTING_WIRELESS_POWERSAVE_DEFAULT,
-			                                    NM_SETTING_WIRELESS_POWERSAVE_LAST);
-			options_str = g_strjoinv (",", (char **) options);
-			g_set_error (error, 1, 0, _("invalid option '%s', use one of [%s]"), val, options_str);
-			return FALSE;
-		}
-	}
-
-	g_object_set (setting, prop, (guint) powersave, NULL);
-	return TRUE;
-}
-
-static gboolean
-nmc_property_wireless_set_mac_address_randomization (NMSetting *setting,
-                                                     const char *prop,
-                                                     const char *val,
-                                                     GError **error)
-{
-	NMSettingMacRandomization randomization;
-	gs_free char *err_token = NULL;
-	gboolean ret;
-	long int t;
-
-	if (nmc_string_to_int_base (val, 0, TRUE,
-	                            NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
-	                            NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
-	                            &t))
-		randomization = (NMSettingMacRandomization) t;
-	else {
-		ret = nm_utils_enum_from_str (nm_setting_mac_randomization_get_type (),
-		                              val,
-		                              (int *) &randomization,
-		                              &err_token);
-
-		if (!ret) {
-			g_set_error (error, 1, 0, _("invalid option '%s', use 'default', 'never' or 'always'"),
-			             err_token);
-			return FALSE;
-		}
-	}
-
-	g_object_set (setting, prop, (guint) randomization, NULL);
-	return TRUE;
-}
-
-
-/* --- NM_SETTING_WIRELESS_SECURITY_SETTING_NAME property functions --- */
-DEFINE_GETTER (nmc_property_wifi_sec_get_key_mgmt, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT)
-DEFINE_GETTER (nmc_property_wifi_sec_get_wep_tx_keyidx, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX)
-DEFINE_GETTER (nmc_property_wifi_sec_get_auth_alg, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG)
-DEFINE_GETTER (nmc_property_wifi_sec_get_proto, NM_SETTING_WIRELESS_SECURITY_PROTO)
-DEFINE_GETTER (nmc_property_wifi_sec_get_pairwise, NM_SETTING_WIRELESS_SECURITY_PAIRWISE)
-DEFINE_GETTER (nmc_property_wifi_sec_get_group, NM_SETTING_WIRELESS_SECURITY_GROUP)
-DEFINE_GETTER (nmc_property_wifi_sec_get_leap_username, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_wifi_sec_get_wep_key_flags, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS)
-DEFINE_GETTER (nmc_property_wifi_sec_get_psk, NM_SETTING_WIRELESS_SECURITY_PSK)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_wifi_sec_get_psk_flags, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)
-DEFINE_GETTER (nmc_property_wifi_sec_get_leap_password, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD)
-DEFINE_SECRET_FLAGS_GETTER (nmc_property_wifi_sec_get_leap_password_flags, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS)
-
-static char *
-nmc_property_wifi_sec_get_wep_key0 (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting);
-	return g_strdup (nm_setting_wireless_security_get_wep_key (s_wireless_sec, 0));
-}
-
-static char *
-nmc_property_wifi_sec_get_wep_key1 (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting);
-	return g_strdup (nm_setting_wireless_security_get_wep_key (s_wireless_sec, 1));
-}
-
-static char *
-nmc_property_wifi_sec_get_wep_key2 (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting);
-	return g_strdup (nm_setting_wireless_security_get_wep_key (s_wireless_sec, 2));
-}
-
-static char *
-nmc_property_wifi_sec_get_wep_key3 (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting);
-	return g_strdup (nm_setting_wireless_security_get_wep_key (s_wireless_sec, 3));
-}
-
-static char *
-nmc_property_wifi_sec_get_wep_key_type (NMSetting *setting, NmcPropertyGetType get_type)
-{
-	NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting);
-	return wep_key_type_to_string (nm_setting_wireless_security_get_wep_key_type (s_wireless_sec));
-}
-
-/* 'key-mgmt' */
-static const char *wifi_sec_valid_key_mgmts[] = { "none", "ieee8021x", "wpa-none", "wpa-psk", "wpa-eap", NULL };
-
-static gboolean
-nmc_property_wifi_sec_set_key_mgmt (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, wifi_sec_valid_key_mgmts, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wifi_sec_allowed_key_mgmt, wifi_sec_valid_key_mgmts)
-
-/* 'auth-alg' */
-static const char *wifi_sec_valid_auth_algs[] = { "open", "shared", "leap", NULL };
-
-static gboolean
-nmc_property_wifi_sec_set_auth_alg (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_set_string (setting, prop, val, wifi_sec_valid_auth_algs, error);
-}
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wifi_sec_allowed_auth_alg, wifi_sec_valid_auth_algs)
-
-/* 'proto' */
-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
-nmc_property_wifi_sec_set_proto (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_add_wifi_sec_proto (setting, prop, val, 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 (nmc_property_wifi_sec_remove_proto,
-                               NM_SETTING_WIRELESS_SECURITY,
-                               nm_setting_wireless_security_get_num_protos,
-                               nm_setting_wireless_security_remove_proto,
-                               _validate_and_remove_wifi_sec_proto)
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wifi_sec_allowed_proto, wifi_sec_valid_protos)
-
-/* 'pairwise' */
-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
-nmc_property_wifi_sec_set_pairwise (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_add_wifi_sec_pairwise (setting, prop, val, 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 (nmc_property_wifi_sec_remove_pairwise,
-                               NM_SETTING_WIRELESS_SECURITY,
-                               nm_setting_wireless_security_get_num_pairwise,
-                               nm_setting_wireless_security_remove_pairwise,
-                               _validate_and_remove_wifi_sec_pairwise)
-
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wifi_sec_allowed_pairwise, wifi_sec_valid_pairwises)
-
-/* 'group' */
-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
-nmc_property_wifi_sec_set_group (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	return check_and_add_wifi_sec_group (setting, prop, val, 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 (nmc_property_wifi_sec_remove_group,
-                               NM_SETTING_WIRELESS_SECURITY,
-                               nm_setting_wireless_security_get_num_groups,
-                               nm_setting_wireless_security_remove_group,
-                               _validate_and_remove_wifi_sec_group)
-DEFINE_ALLOWED_VAL_FUNC (nmc_property_wifi_sec_allowed_group, wifi_sec_valid_groups)
-
-/* 'wep-key' */
-static gboolean
-nmc_property_wifi_set_wep_key (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	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 (val, NM_WEP_KEY_TYPE_KEY))
-		guessed_type = NM_WEP_KEY_TYPE_KEY;
-	else if (nm_utils_wep_key_valid (val, 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"), val);
-		return FALSE;
-	}
-
-	if (type != NM_WEP_KEY_TYPE_UNKNOWN && type != guessed_type) {
-		if (nm_utils_wep_key_valid (val, 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."),
-			             val, 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 = prop[strlen (prop) - 1] - '0';
-	g_print (_("WEP key is guessed to be of '%s'\n"), wep_key_type_to_string (guessed_type));
-	if (idx != prev_idx)
-		g_print (_("WEP key index set to '%d'\n"), idx);
-
-	g_object_set (setting, prop, val, 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;
-}
-
-/* 'wep-key-type' */
-static gboolean
-nmc_property_wifi_set_wep_key_type (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	unsigned long  type_int;
-	const char *valid_wep_types[] = { "unknown", "key", "passphrase", NULL };
-	const char *type_str = NULL;
-	const char *key0, *key1,* key2, *key3;
-	NMWepKeyType type = NM_WEP_KEY_TYPE_UNKNOWN;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nmc_string_to_uint (val, TRUE, 0, 2, &type_int)) {
-		if (!(type_str = nmc_string_is_valid (val, valid_wep_types, NULL))) {
-			g_set_error (error, 1, 0, _("'%s' not among [0 (unknown), 1 (key), 2 (passphrase)]"), val);
-			return FALSE;
-		}
-		if (type_str == valid_wep_types[1])
-			type = NM_WEP_KEY_TYPE_KEY;
-		else if (type_str == valid_wep_types[2])
-			type = NM_WEP_KEY_TYPE_PASSPHRASE;
-	} else
-		type = (NMWepKeyType) type_int;
-
-	/* Check type compatibility with set keys */
-	key0 = nm_setting_wireless_security_get_wep_key (NM_SETTING_WIRELESS_SECURITY (setting), 0);
-	key1 = nm_setting_wireless_security_get_wep_key (NM_SETTING_WIRELESS_SECURITY (setting), 1);
-	key2 = nm_setting_wireless_security_get_wep_key (NM_SETTING_WIRELESS_SECURITY (setting), 2);
-	key3 = nm_setting_wireless_security_get_wep_key (NM_SETTING_WIRELESS_SECURITY (setting), 3);
-	if (key0 && !nm_utils_wep_key_valid (key0, type))
-		g_print (_("Warning: '%s' is not compatible with '%s' type, please change or delete the key.\n"),
-		         NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, wep_key_type_to_string (type));
-	if (key1 && !nm_utils_wep_key_valid (key1, type))
-		g_print (_("Warning: '%s' is not compatible with '%s' type, please change or delete the key.\n"),
-		         NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, wep_key_type_to_string (type));
-	if (key2 && !nm_utils_wep_key_valid (key2, type))
-		g_print (_("Warning: '%s' is not compatible with '%s' type, please change or delete the key.\n"),
-		         NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, wep_key_type_to_string (type));
-	if (key3 && !nm_utils_wep_key_valid (key3, type))
-		g_print (_("Warning: '%s' is not compatible with '%s' type, please change or delete the key.\n"),
-		         NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, wep_key_type_to_string (type));
-
-	g_object_set (setting, prop, type, NULL);
-	return TRUE;
-}
-
-static const char *
-nmc_property_wifi_describe_wep_key_type (NMSetting *setting, const char *prop)
-{
-	static char *desc = NULL;
-
-	if (G_UNLIKELY (desc == NULL)) {
-		desc = g_strdup_printf (_("Enter the type of WEP keys. The accepted values are: "
-		                          "0 or unknown, 1 or key, and 2 or passphrase.\n"));
-	}
-	return desc;
-}
-
-/* 'psk' */
-static gboolean
-nmc_property_wifi_set_psk (NMSetting *setting, const char *prop, const char *val, GError **error)
-{
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (!nm_utils_wpa_psk_valid (val)) {
-		g_set_error (error, 1, 0, _("'%s' is not a valid PSK"), val);
-		return FALSE;
-	}
-	g_object_set (setting, prop, val, NULL);
-	return TRUE;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void
-nmc_value_transform_bool_string (const GValue *src_value,
-                                 GValue       *dest_value)
-{
-	dest_value->data[0].v_pointer = g_strdup (src_value->data[0].v_int ? "yes" : "no");
-}
-
-static void
-nmc_value_transform_char_string (const GValue *src_value,
-                                 GValue       *dest_value)
-{
-	dest_value->data[0].v_pointer = g_strdup_printf ("%c", src_value->data[0].v_uint);
-}
-
-static void __attribute__((constructor))
-register_nmcli_value_transforms (void)
-{
-	g_value_register_transform_func (G_TYPE_BOOLEAN, G_TYPE_STRING, nmc_value_transform_bool_string);
-	g_value_register_transform_func (G_TYPE_CHAR, G_TYPE_STRING, nmc_value_transform_char_string);
-}
-
-/*----------------------------------------------------------------------------*/
-
-/* Main hash table storing function pointer for manipulating properties */
-static GHashTable *nmc_properties = NULL;
-typedef	char *        (*NmcPropertyGetFunc)      (NMSetting *, NmcPropertyGetType);
-typedef	gboolean      (*NmcPropertySetFunc)      (NMSetting *, const char *, const char *, GError **);
-typedef	gboolean      (*NmcPropertyRemoveFunc)   (NMSetting *, const char *, const char *, guint32, GError **);
-typedef	const char *  (*NmcPropertyDescribeFunc) (NMSetting *, const char *);
-typedef	const char ** (*NmcPropertyValuesFunc)   (NMSetting *, const char *);
+#include "nm-client-utils.h"
+#include "nm-vpn-helpers.h"
+#include "nm-meta-setting-access.h"
 
-typedef struct {
-	/* The order of the fields is important as they correspond
-	 * to the order as _nmc_add_prop_funcs() passes the arguments. */
-#define NmcPropertyFuncsFields \
-	NmcPropertyGetFunc get_func;           /* func getting property values */ \
-	NmcPropertySetFunc set_func;           /* func adding/setting property values */ \
-	NmcPropertyRemoveFunc remove_func;     /* func removing items from container options */ \
-	NmcPropertyDescribeFunc describe_func; /* func returning property description */ \
-	NmcPropertyValuesFunc values_func;     /* func returning allowed property values */ \
-	;
-	NmcPropertyFuncsFields
-} NmcPropertyFuncs;
+#include "utils.h"
+#include "common.h"
 
-NMSetting *
-nmc_setting_new_for_name (const char *name)
-{
-	GType stype;
-	NMSetting *setting = NULL;
-
-	if (name) {
-		stype = nm_setting_lookup_type (name);
-		if (stype != G_TYPE_INVALID) {
-			setting = g_object_new (stype, NULL);
-			g_warn_if_fail (NM_IS_SETTING (setting));
-		}
-	}
-	return setting;
-}
+/*****************************************************************************/
 
 static gboolean
 get_answer (const char *prop, const char *value)
@@ -6082,2326 +304,175 @@ nmc_setting_connection_connect_handlers (NMSettingConnection *setting, NMConnect
 	                  G_CALLBACK (connection_master_changed_cb), connection);
 }
 
-/*
- * Customize some properties of the setting so that the setting has sensible
- * values.
- */
-void
-nmc_setting_custom_init (NMSetting *setting)
-{
-	g_return_if_fail (NM_IS_SETTING (setting));
+/*****************************************************************************/
 
-	if (NM_IS_SETTING_VLAN (setting)) {
-		/* Set sensible initial VLAN values */
-		g_object_set (NM_SETTING_VLAN (setting),
-		              NM_SETTING_VLAN_ID, 1,
-		              NULL);
-	} else if (NM_IS_SETTING_INFINIBAND (setting)) {
-		/* Initialize 'transport-mode' so that 'infiniband' is valid */
-		g_object_set (NM_SETTING_INFINIBAND (setting),
-		              NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
-		              NULL);
-	} else if (NM_IS_SETTING_CDMA (setting)) {
-		/* Initialize 'number' so that 'cdma' is valid */
-		g_object_set (NM_SETTING_CDMA (setting),
-		              NM_SETTING_CDMA_NUMBER, "#777",
-		              NULL);
-	} else if (NM_IS_SETTING_GSM (setting)) {
-		/* Initialize 'number' so that 'gsm' is valid */
-		g_object_set (NM_SETTING_GSM (setting),
-		              NM_SETTING_GSM_NUMBER, "*99#",
-		              NULL);
-	} else if (NM_IS_SETTING_OLPC_MESH (setting)) {
-		g_object_set (NM_SETTING_OLPC_MESH (setting),
-		              NM_SETTING_OLPC_MESH_CHANNEL, 1,
-		              NULL);
-	} else if (NM_IS_SETTING_WIRELESS (setting)) {
-		/* 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);
-	} else if (NM_IS_SETTING_ADSL (setting)) {
-		/* Initialize a protocol */
-		g_object_set (NM_SETTING_ADSL (setting),
-		              NM_SETTING_ADSL_PROTOCOL, NM_SETTING_ADSL_PROTOCOL_PPPOE,
-		              NULL);
-	} else if (NM_IS_SETTING_IP4_CONFIG (setting)) {
-		g_object_set (NM_SETTING_IP_CONFIG (setting),
-		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
-		              NULL);
-	} else if (NM_IS_SETTING_IP6_CONFIG (setting)) {
-		g_object_set (NM_SETTING_IP_CONFIG (setting),
-		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
-		              NULL);
-	} else if (NM_IS_SETTING_PROXY (setting)) {
-		g_object_set (NM_SETTING_PROXY (setting),
-		              NM_SETTING_PROXY_METHOD, (int) NM_SETTING_PROXY_METHOD_NONE,
-		              NULL);
-	} else if (NM_IS_SETTING_TUN (setting)) {
-		g_object_set (NM_SETTING_TUN (setting),
-		              NM_SETTING_TUN_MODE, NM_SETTING_TUN_MODE_TUN,
-		              NULL);
-	} else if (NM_IS_SETTING_BLUETOOTH (setting)) {
-		g_object_set (NM_SETTING_BLUETOOTH (setting),
-		              NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
-		              NULL);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-static inline void
-_nmc_add_prop_funcs (const char *key,
-                     const NmcPropertyFuncs *item_init)
-{
-	NmcPropertyFuncs *item;
-
-	item = g_malloc (sizeof (NmcPropertyFuncs));
-	*item = *item_init;
-	g_hash_table_insert (nmc_properties, (gpointer) key, item);
-}
-
-#define nmc_add_prop_funcs(key, ...) \
-	G_STMT_START { \
-		struct { \
-			NmcPropertyFuncsFields; \
-			/* The _dummy field is here so that the last argument can be always
-			 * NULL. That means every call to nmc_add_prop_funcs() below ends
-			 * with a separate line "NULL);". */ \
-			gpointer _dummy; \
-		} _item_init = { \
-			__VA_ARGS__ \
-		};\
-		\
-		nm_assert (_item_init._dummy == NULL); \
-		_nmc_add_prop_funcs ("" key, (NmcPropertyFuncs *) &_item_init); \
-	} G_STMT_END
-
-/* concatenate setting name and property name */
-#define GLUE(A,B) "" NM_SETTING_##A##_SETTING_NAME "" NM_SETTING_##A##_##B ""
-#define GLUE_IP(A,B) "" NM_SETTING_IP##A##_CONFIG_SETTING_NAME "" NM_SETTING_IP_CONFIG_##B ""
-
-void
-nmc_properties_init (void)
+static gboolean
+_set_fcn_precheck_connection_secondaries (const char *value,
+                                          char **value_coerced,
+                                          GError **error)
 {
-	if (G_LIKELY (nmc_properties))
-		return;
-
-	/* create properties hash table */
-	nmc_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
-
-	/* Add editable properties for NM_SETTING_802_1X_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (802_1X, EAP),
-	                    nmc_property_802_1X_get_eap,
-	                    nmc_property_802_1X_set_eap,
-	                    nmc_property_802_1X_remove_eap,
-	                    NULL,
-	                    nmc_property_802_1X_allowed_eap,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, IDENTITY),
-	                    nmc_property_802_1X_get_identity,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, ANONYMOUS_IDENTITY),
-	                    nmc_property_802_1X_get_anonymous_identity,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PAC_FILE),
-	                    nmc_property_802_1X_get_pac_file,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, CA_CERT),
-	                    nmc_property_802_1X_get_ca_cert,
-	                    nmc_property_802_1X_set_ca_cert,
-	                    NULL,
-	                    nmc_property_802_1X_describe_ca_cert,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, CA_CERT_PASSWORD),
-	                    nmc_property_802_1X_get_ca_cert_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, CA_CERT_PASSWORD_FLAGS),
-	                    nmc_property_802_1X_get_ca_cert_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, CA_PATH),
-	                    nmc_property_802_1X_get_ca_path,
-                            nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, SUBJECT_MATCH),
-	                    nmc_property_802_1X_get_subject_match,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, ALTSUBJECT_MATCHES),
-	                    nmc_property_802_1X_get_altsubject_matches,
-	                    nmc_property_802_1X_set_altsubject_matches,
-	                    nmc_property_802_1X_remove_altsubject_matches,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, DOMAIN_SUFFIX_MATCH),
-	                    nmc_property_802_1X_get_domain_suffix_match,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, CLIENT_CERT),
-	                    nmc_property_802_1X_get_client_cert_full,
-	                    nmc_property_802_1X_set_client_cert,
-	                    NULL,
-	                    nmc_property_802_1X_describe_client_cert,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, CLIENT_CERT_PASSWORD),
-	                    nmc_property_802_1X_get_client_cert_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, CLIENT_CERT_PASSWORD_FLAGS),
-	                    nmc_property_802_1X_get_client_cert_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE1_PEAPVER),
-	                    nmc_property_802_1X_get_phase1_peapver,
-	                    nmc_property_802_1X_set_phase1_peapver,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_802_1X_allowed_phase1_peapver,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE1_PEAPLABEL),
-	                    nmc_property_802_1X_get_phase1_peaplabel,
-	                    nmc_property_802_1X_set_phase1_peaplabel,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_802_1X_allowed_phase1_peaplabel,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE1_FAST_PROVISIONING),
-	                    nmc_property_802_1X_get_phase1_fast_provisioning,
-	                    nmc_property_802_1X_set_phase1_fast_provisioning,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_802_1X_allowed_phase1_fast_provisioning,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE1_AUTH_FLAGS),
-	                    nmc_property_802_1X_get_phase1_auth_flags,
-	                    nmc_property_802_1X_set_phase1_auth_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_AUTH),
-	                    nmc_property_802_1X_get_phase2_auth,
-	                    nmc_property_802_1X_set_phase2_auth,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_802_1X_allowed_phase2_auth,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_AUTHEAP),
-	                    nmc_property_802_1X_get_phase2_autheap,
-	                    nmc_property_802_1X_set_phase2_autheap,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_802_1X_allowed_phase2_autheap,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_CA_CERT),
-	                    nmc_property_802_1X_get_phase2_ca_cert,
-	                    nmc_property_802_1X_set_phase2_ca_cert,
-	                    NULL,
-	                    nmc_property_802_1X_describe_phase2_ca_cert,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_CA_CERT_PASSWORD),
-	                    nmc_property_802_1X_get_phase2_ca_cert_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_CA_CERT_PASSWORD_FLAGS),
-	                    nmc_property_802_1X_get_phase2_ca_cert_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_CA_PATH),
-	                    nmc_property_802_1X_get_phase2_ca_path,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_SUBJECT_MATCH),
-	                    nmc_property_802_1X_get_phase2_subject_match,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_ALTSUBJECT_MATCHES),
-	                    nmc_property_802_1X_get_phase2_altsubject_matches,
-	                    nmc_property_802_1X_set_phase2_altsubject_matches,
-	                    nmc_property_802_1X_remove_phase2_altsubject_matches,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_DOMAIN_SUFFIX_MATCH),
-	                    nmc_property_802_1X_get_phase2_domain_suffix_match,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_CLIENT_CERT),
-	                    nmc_property_802_1X_get_phase2_client_cert_full,
-	                    nmc_property_802_1X_set_phase2_client_cert,
-	                    NULL,
-	                    nmc_property_802_1X_describe_phase2_client_cert,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_CLIENT_CERT_PASSWORD),
-	                    nmc_property_802_1X_get_phase2_client_cert_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_CLIENT_CERT_PASSWORD_FLAGS),
-	                    nmc_property_802_1X_get_phase2_client_cert_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PASSWORD),
-	                    nmc_property_802_1X_get_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PASSWORD_FLAGS),
-	                    nmc_property_802_1X_get_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PASSWORD_RAW),
-	                    nmc_property_802_1X_get_password_raw,
-	                    nmc_property_802_1X_set_password_raw,
-	                    NULL,
-	                    nmc_property_802_1X_describe_password_raw,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PASSWORD_RAW_FLAGS),
-	                    nmc_property_802_1X_get_password_raw_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PRIVATE_KEY),
-	                    nmc_property_802_1X_get_private_key_full,
-	                    nmc_property_802_1X_set_private_key,
-	                    NULL,
-	                    nmc_property_802_1X_describe_private_key,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PRIVATE_KEY_PASSWORD),
-	                    nmc_property_802_1X_get_private_key_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PRIVATE_KEY_PASSWORD_FLAGS),
-	                    nmc_property_802_1X_get_private_key_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_PRIVATE_KEY),
-	                    nmc_property_802_1X_get_phase2_private_key_full,
-	                    nmc_property_802_1X_set_phase2_private_key,
-	                    NULL,
-	                    nmc_property_802_1X_describe_private_key,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_PRIVATE_KEY_PASSWORD),
-	                    nmc_property_802_1X_get_phase2_private_key_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_PRIVATE_KEY_PASSWORD_FLAGS),
-	                    nmc_property_802_1X_get_phase2_private_key_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PIN),
-	                    nmc_property_802_1X_get_pin,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, PIN_FLAGS),
-	                    nmc_property_802_1X_get_pin_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, SYSTEM_CA_CERTS),
-	                    nmc_property_802_1X_get_system_ca_certs,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (802_1X, AUTH_TIMEOUT),
-	                    nmc_property_802_1X_get_auth_timeout,
-	                    nmc_property_set_int,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_ADSL_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (ADSL, USERNAME),
-	                    nmc_property_adsl_get_username,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (ADSL, PASSWORD),
-	                    nmc_property_adsl_get_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (ADSL, PASSWORD_FLAGS),
-	                    nmc_property_adsl_get_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (ADSL, PROTOCOL),
-	                    nmc_property_adsl_get_protocol,
-	                    nmc_property_adsl_set_protocol,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_adsl_allowed_protocol,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (ADSL, ENCAPSULATION),
-	                    nmc_property_adsl_get_encapsulation,
-	                    nmc_property_adsl_set_encapsulation,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_adsl_allowed_encapsulation,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (ADSL, VPI),
-	                    nmc_property_adsl_get_vpi,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (ADSL, VCI),
-	                    nmc_property_adsl_get_vci,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_BLUETOOTH_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (BLUETOOTH, BDADDR),
-	                    nmc_property_bluetooth_get_bdaddr,
-	                    nmc_property_set_mac,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (BLUETOOTH, TYPE),
-	                    nmc_property_bluetooth_get_type,
-	                    nmc_property_bluetooth_set_type,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_BOND_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (BOND, OPTIONS),
-	                    nmc_property_bond_get_options,
-	                    nmc_property_bond_set_options,
-	                    nmc_property_bond_remove_option_options,
-	                    nmc_property_bond_describe_options,
-	                    nmc_property_bond_allowed_options,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_BRIDGE_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (BRIDGE, MAC_ADDRESS),
-	                    nmc_property_bridge_get_mac_address,
-	                    nmc_property_set_mac,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (BRIDGE, STP),
-	                    nmc_property_bridge_get_stp,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (BRIDGE, PRIORITY),
-	                    nmc_property_bridge_get_priority,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (BRIDGE, FORWARD_DELAY),
-	                    nmc_property_bridge_get_forward_delay,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (BRIDGE, HELLO_TIME),
-	                    nmc_property_bridge_get_hello_time,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (BRIDGE, MAX_AGE),
-	                    nmc_property_bridge_get_max_age,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (BRIDGE, AGEING_TIME),
-	                    nmc_property_bridge_get_ageing_time,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	nmc_add_prop_funcs (GLUE (BRIDGE, MULTICAST_SNOOPING),
-	                    nmc_property_bridge_get_multicast_snooping,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_BRIDGE_PORT_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (BRIDGE_PORT, PRIORITY),
-	                    nmc_property_bridge_port_get_priority,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (BRIDGE_PORT, PATH_COST),
-	                    nmc_property_bridge_port_get_path_cost,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (BRIDGE_PORT, HAIRPIN_MODE),
-	                    nmc_property_bridge_port_get_hairpin_mode,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_CDMA_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (CDMA, NUMBER),
-	                    nmc_property_cdma_get_number,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CDMA, USERNAME),
-	                    nmc_property_cdma_get_username,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CDMA, PASSWORD),
-	                    nmc_property_cdma_get_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CDMA, PASSWORD_FLAGS),
-	                    nmc_property_cdma_get_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CDMA, MTU),
-	                    nmc_property_cdma_get_mtu,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_CONNECTION_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (CONNECTION, ID),
-	                    nmc_property_connection_get_id,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, UUID),
-	                    nmc_property_connection_get_uuid,
-	                    NULL, /* forbid setting/removing UUID */
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, STABLE_ID),
-	                    nmc_property_connection_get_stable_id,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, INTERFACE_NAME),
-	                    nmc_property_connection_get_interface_name,
-	                    nmc_property_set_ifname,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, TYPE),
-	                    nmc_property_connection_get_type,
-	                    nmc_property_connection_set_type,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, AUTOCONNECT),
-	                    nmc_property_connection_get_autoconnect,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, AUTOCONNECT_PRIORITY),
-	                    nmc_property_connection_get_autoconnect_priority,
-	                    nmc_property_set_int,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, AUTOCONNECT_RETRIES),
-	                    nmc_property_connection_get_autoconnect_retries,
-	                    nmc_property_set_int,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, TIMESTAMP),
-	                    nmc_property_connection_get_timestamp,
-	                    NULL, /* read-only */
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, READ_ONLY),
-	                    nmc_property_connection_get_read_only,
-	                    NULL, /* 'read-only' is read-only :-) */
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, PERMISSIONS),
-	                    nmc_property_connection_get_permissions,
-	                    nmc_property_connection_set_permissions,
-	                    nmc_property_connection_remove_permissions,
-	                    nmc_property_connection_describe_permissions,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, ZONE),
-	                    nmc_property_connection_get_zone,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, MASTER),
-	                    nmc_property_connection_get_master,
-	                    nmc_property_con_set_master,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, SLAVE_TYPE),
-	                    nmc_property_connection_get_slave_type,
-	                    nmc_property_con_set_slave_type,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_con_allowed_slave_type,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, AUTOCONNECT_SLAVES),
-	                    nmc_property_connection_get_autoconnect_slaves,
-	                    nmc_property_set_trilean,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, SECONDARIES),
-	                    nmc_property_connection_get_secondaries,
-	                    nmc_property_connection_set_secondaries,
-	                    nmc_property_connection_remove_secondaries,
-	                    nmc_property_connection_describe_secondaries,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, GATEWAY_PING_TIMEOUT),
-	                    nmc_property_connection_get_gateway_ping_timeout,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, METERED),
-	                    nmc_property_connection_get_metered,
-	                    nmc_property_connection_set_metered,
-	                    NULL,
-	                    nmc_property_connection_describe_metered,
-	                    nmc_property_connection_allowed_metered,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (CONNECTION, LLDP),
-	                    nmc_property_connection_get_lldp,
-	                    nmc_property_connection_set_lldp,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_connection_allowed_lldp,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_DCB_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (DCB, APP_FCOE_FLAGS),
-	                    nmc_property_dcb_get_app_fcoe_flags,
-	                    nmc_property_dcb_set_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, APP_FCOE_MODE),
-	                    nmc_property_dcb_get_app_fcoe_mode,
-	                    nmc_property_dcb_set_app_fcoe_mode,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_dcb_allowed_app_fcoe_modes,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, APP_FCOE_PRIORITY),
-	                    nmc_property_dcb_get_app_fcoe_priority,
-	                    nmc_property_dcb_set_priority,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, APP_ISCSI_FLAGS),
-	                    nmc_property_dcb_get_app_iscsi_flags,
-	                    nmc_property_dcb_set_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, APP_ISCSI_PRIORITY),
-	                    nmc_property_dcb_get_app_iscsi_priority,
-	                    nmc_property_dcb_set_priority,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, APP_FIP_FLAGS),
-	                    nmc_property_dcb_get_app_fip_flags,
-	                    nmc_property_dcb_set_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, APP_FIP_PRIORITY),
-	                    nmc_property_dcb_get_app_fip_priority,
-	                    nmc_property_dcb_set_priority,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, PRIORITY_FLOW_CONTROL_FLAGS),
-	                    nmc_property_dcb_get_pfc_flags,
-	                    nmc_property_dcb_set_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, PRIORITY_FLOW_CONTROL),
-	                    nmc_property_dcb_get_pfc,
-	                    nmc_property_dcb_set_pfc,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, PRIORITY_GROUP_FLAGS),
-	                    nmc_property_dcb_get_pg_flags,
-	                    nmc_property_dcb_set_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, PRIORITY_GROUP_ID),
-	                    nmc_property_dcb_get_pg_group_id,
-	                    nmc_property_dcb_set_pg_group_id,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, PRIORITY_GROUP_BANDWIDTH),
-	                    nmc_property_dcb_get_pg_group_bandwidth,
-	                    nmc_property_dcb_set_pg_group_bandwidth,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, PRIORITY_BANDWIDTH),
-	                    nmc_property_dcb_get_pg_bandwidth,
-	                    nmc_property_dcb_set_pg_bandwidth,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, PRIORITY_STRICT_BANDWIDTH),
-	                    nmc_property_dcb_get_pg_strict,
-	                    nmc_property_dcb_set_pg_strict,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (DCB, PRIORITY_TRAFFIC_CLASS),
-	                    nmc_property_dcb_get_pg_traffic_class,
-	                    nmc_property_dcb_set_pg_traffic_class,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_GSM_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (GSM, NUMBER),
-	                    nmc_property_gsm_get_number,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, USERNAME),
-	                    nmc_property_gsm_get_username,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, PASSWORD),
-	                    nmc_property_gsm_get_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, PASSWORD_FLAGS),
-	                    nmc_property_gsm_get_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, APN),
-	                    nmc_property_gsm_get_apn,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, NETWORK_ID),
-	                    nmc_property_gsm_get_network_id,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, PIN),
-	                    nmc_property_gsm_get_pin,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, PIN_FLAGS),
-	                    nmc_property_gsm_get_pin_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, HOME_ONLY),
-	                    nmc_property_gsm_get_home_only,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, DEVICE_ID),
-	                    nmc_property_gsm_get_device_id,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, SIM_ID),
-	                    nmc_property_gsm_get_sim_id,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, SIM_OPERATOR_ID),
-	                    nmc_property_gsm_get_sim_operator_id,
-	                    nmc_property_gsm_set_sim_operator_id,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (GSM, MTU),
-	                    nmc_property_gsm_get_mtu,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_INFINIBAND_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (INFINIBAND, MAC_ADDRESS),
-	                    nmc_property_ib_get_mac_address,
-	                    nmc_property_ib_set_mac,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (INFINIBAND, MTU),
-	                    nmc_property_ib_get_mtu,
-	                    nmc_property_set_mtu,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (INFINIBAND, TRANSPORT_MODE),
-	                    nmc_property_ib_get_transport_mode,
-	                    nmc_property_ib_set_transport_mode,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_ib_allowed_transport_mode,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (INFINIBAND, P_KEY),
-	                    nmc_property_ib_get_p_key,
-	                    nmc_property_ib_set_p_key,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (INFINIBAND, PARENT),
-	                    nmc_property_ib_get_parent,
-	                    nmc_property_set_ifname,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-
-	/* Add editable properties for NM_SETTING_IP4_CONFIG_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE_IP (4, METHOD),
-	                    nmc_property_ipv4_get_method,
-	                    nmc_property_ipv4_set_method,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_ipv4_allowed_method,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, DNS),
-	                    nmc_property_ipv4_get_dns,
-	                    nmc_property_ipv4_set_dns,
-	                    nmc_property_ipv4_remove_dns,
-	                    nmc_property_ipv4_describe_dns,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, DNS_SEARCH),
-	                    nmc_property_ipv4_get_dns_search,
-	                    nmc_property_ipv4_set_dns_search,
-	                    nmc_property_ipv4_remove_dns_search,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, DNS_OPTIONS),
-	                    nmc_property_ipv4_get_dns_options,
-	                    nmc_property_ipv4_set_dns_options,
-	                    nmc_property_ipv4_remove_dns_option,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, DNS_PRIORITY),
-	                    nmc_property_ipv4_get_dns_priority,
-	                    nmc_property_set_int,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, ADDRESSES),
-	                    nmc_property_ip_get_addresses,
-	                    nmc_property_ipv4_set_addresses,
-	                    nmc_property_ipv4_remove_addresses,
-	                    nmc_property_ipv4_describe_addresses,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, GATEWAY),
-	                    nmc_property_ipv4_get_gateway,
-	                    nmc_property_ipv4_set_gateway,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, ROUTES),
-	                    nmc_property_ipv4_get_routes,
-	                    nmc_property_ipv4_set_routes,
-	                    nmc_property_ipv4_remove_routes,
-	                    nmc_property_ipv4_describe_routes,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, ROUTE_METRIC),
-	                    nmc_property_ipv4_get_route_metric,
-	                    nmc_property_set_int64,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, IGNORE_AUTO_ROUTES),
-	                    nmc_property_ipv4_get_ignore_auto_routes,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, IGNORE_AUTO_DNS),
-	                    nmc_property_ipv4_get_ignore_auto_dns,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP4_CONFIG, DHCP_CLIENT_ID),
-	                    nmc_property_ipv4_get_dhcp_client_id,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, DHCP_TIMEOUT),
-	                    nmc_property_ipv4_get_dhcp_timeout,
-	                    nmc_property_set_int,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, DHCP_SEND_HOSTNAME),
-	                    nmc_property_ipv4_get_dhcp_send_hostname,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, DHCP_HOSTNAME),
-	                    nmc_property_ipv4_get_dhcp_hostname,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP4_CONFIG, DHCP_FQDN),
-	                    nmc_property_ipv4_get_dhcp_fqdn,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, NEVER_DEFAULT),
-	                    nmc_property_ipv4_get_never_default,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, MAY_FAIL),
-	                    nmc_property_ipv4_get_may_fail,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (4, DAD_TIMEOUT),
-	                    nmc_property_ipv4_get_dad_timeout,
-	                    nmc_property_set_int,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	const GPtrArray *connections;
+	NMConnection *con;
+	gs_strfreev char **strv = NULL;
+	char **iter;
+	gboolean modified;
 
-	/* Add editable properties for NM_SETTING_IP6_CONFIG_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE_IP (6, METHOD),
-	                    nmc_property_ipv6_get_method,
-	                    nmc_property_ipv6_set_method,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_ipv6_allowed_method,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, DNS),
-	                    nmc_property_ipv6_get_dns,
-	                    nmc_property_ipv6_set_dns,
-	                    nmc_property_ipv6_remove_dns,
-	                    nmc_property_ipv6_describe_dns,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, DNS_SEARCH),
-	                    nmc_property_ipv6_get_dns_search,
-	                    nmc_property_ipv6_set_dns_search,
-	                    nmc_property_ipv6_remove_dns_search,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, DNS_OPTIONS),
-	                    nmc_property_ipv6_get_dns_options,
-	                    nmc_property_ipv6_set_dns_options,
-	                    nmc_property_ipv6_remove_dns_option,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, DNS_PRIORITY),
-	                    nmc_property_ipv6_get_dns_priority,
-	                    nmc_property_set_int,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, ADDRESSES),
-	                    nmc_property_ip_get_addresses,
-	                    nmc_property_ipv6_set_addresses,
-	                    nmc_property_ipv6_remove_addresses,
-	                    nmc_property_ipv6_describe_addresses,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, GATEWAY),
-	                    nmc_property_ipv6_get_gateway,
-	                    nmc_property_ipv6_set_gateway,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, ROUTES),
-	                    nmc_property_ipv6_get_routes,
-	                    nmc_property_ipv6_set_routes,
-	                    nmc_property_ipv6_remove_routes,
-	                    nmc_property_ipv6_describe_routes,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, ROUTE_METRIC),
-	                    nmc_property_ipv6_get_route_metric,
-	                    nmc_property_set_int64,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, IGNORE_AUTO_ROUTES),
-	                    nmc_property_ipv6_get_ignore_auto_routes,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, IGNORE_AUTO_DNS),
-	                    nmc_property_ipv6_get_ignore_auto_dns,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, NEVER_DEFAULT),
-	                    nmc_property_ipv6_get_never_default,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, MAY_FAIL),
-	                    nmc_property_ipv6_get_may_fail,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP6_CONFIG, IP6_PRIVACY),
-	                    nmc_property_ipv6_get_ip6_privacy,
-	                    nmc_property_ipv6_set_ip6_privacy,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP6_CONFIG, ADDR_GEN_MODE),
-	                    nmc_property_ipv6_get_addr_gen_mode,
-	                    nmc_property_ipv6_set_addr_gen_mode,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_ipv6_allowed_addr_gen_mode,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, DHCP_SEND_HOSTNAME),
-	                    nmc_property_ipv6_get_dhcp_send_hostname,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE_IP (6, DHCP_HOSTNAME),
-	                    nmc_property_ipv6_get_dhcp_hostname,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP6_CONFIG, TOKEN),
-	                    nmc_property_ipv6_get_token,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	strv = nmc_strsplit_set (value, " \t,", 0);
+	if (!strv)
+		return TRUE;
 
-	/* Add editable properties for NM_SETTING_OLPC_MESH_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (OLPC_MESH, SSID),
-	                    nmc_property_olpc_get_ssid,
-	                    nmc_property_set_ssid,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (OLPC_MESH, CHANNEL),
-	                    nmc_property_olpc_get_channel,
-	                    nmc_property_olpc_set_channel,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (OLPC_MESH, DHCP_ANYCAST_ADDRESS),
-	                    nmc_property_olpc_get_anycast_address,
-	                    nmc_property_set_mac,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	connections = nm_client_get_connections (nm_cli.client);
 
-	/* Add editable properties for NM_SETTING_PPP_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (PPP, NOAUTH),
-	                    nmc_property_ppp_get_noauth,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, REFUSE_EAP),
-	                    nmc_property_ppp_get_refuse_eap,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, REFUSE_PAP),
-	                    nmc_property_ppp_get_refuse_pap,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, REFUSE_CHAP),
-	                    nmc_property_ppp_get_refuse_chap,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, REFUSE_MSCHAP),
-	                    nmc_property_ppp_get_refuse_mschap,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, REFUSE_MSCHAPV2),
-	                    nmc_property_ppp_get_refuse_mschapv2,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, NOBSDCOMP),
-	                    nmc_property_ppp_get_nobsdcomp,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, NODEFLATE),
-	                    nmc_property_ppp_get_nodeflate,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, NO_VJ_COMP),
-	                    nmc_property_ppp_get_no_vj_comp,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, REQUIRE_MPPE),
-	                    nmc_property_ppp_get_require_mppe,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, REQUIRE_MPPE_128),
-	                    nmc_property_ppp_get_require_mppe_128,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, MPPE_STATEFUL),
-	                    nmc_property_ppp_get_mppe_stateful,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, CRTSCTS),
-	                    nmc_property_ppp_get_crtscts,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, BAUD),
-	                    nmc_property_ppp_get_baud,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, MRU),
-	                    nmc_property_ppp_get_mru,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, MTU),
-	                    nmc_property_ppp_get_mtu,
-	                    nmc_property_set_mtu,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, LCP_ECHO_FAILURE),
-	                    nmc_property_ppp_get_lcp_echo_failure,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPP, LCP_ECHO_INTERVAL),
-	                    nmc_property_ppp_get_lcp_echo_interval,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	for (iter = strv; *iter; iter++) {
+		if (nm_utils_is_uuid (*iter)) {
+			con = nmc_find_connection (connections, "uuid", *iter, NULL, FALSE);
+			if (!con){
+				g_print (_("Warning: %s is not an UUID of any existing connection profile\n"),
+				         *iter);
+			} else {
+				/* Currenly NM only supports VPN connections as secondaries */
+				if (!nm_connection_is_type (con, NM_SETTING_VPN_SETTING_NAME)) {
+					g_set_error (error, 1, 0, _("'%s' is not a VPN connection profile"), *iter);
+					return FALSE;
+				}
+			}
+		} else {
+			con = nmc_find_connection (connections, "id", *iter, NULL, FALSE);
+			if (!con) {
+				g_set_error (error, 1, 0, _("'%s' is not a name of any exiting profile"), *iter);
+				return FALSE;
+			}
 
-	/* Add editable properties for NM_SETTING_PPPOE_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (PPPOE, SERVICE),
-	                    nmc_property_pppoe_get_service,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPPOE, USERNAME),
-	                    nmc_property_pppoe_get_username,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPPOE, PASSWORD),
-	                    nmc_property_pppoe_get_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PPPOE, PASSWORD_FLAGS),
-	                    nmc_property_pppoe_get_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+			/* Currenly NM only supports VPN connections as secondaries */
+			if (!nm_connection_is_type (con, NM_SETTING_VPN_SETTING_NAME)) {
+				g_set_error (error, 1, 0, _("'%s' is not a VPN connection profile"), *iter);
+				return FALSE;
+			}
 
-	/* Add editable properties for NM_SETTING_SERIAL_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (SERIAL, BAUD),
-	                    nmc_property_serial_get_baud,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (SERIAL, BITS),
-	                    nmc_property_serial_get_bits,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (SERIAL, PARITY),
-	                    nmc_property_serial_get_parity,
-	                    nmc_property_serial_set_parity,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (SERIAL, STOPBITS),
-	                    nmc_property_serial_get_stopbits,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (SERIAL, SEND_DELAY),
-	                    nmc_property_serial_get_send_delay,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+			/* translate id to uuid */
+			g_free (*iter);
+			*iter = g_strdup (nm_connection_get_uuid (con));
+			modified = TRUE;
+		}
+	}
 
-	/* Add editable properties for NM_SETTING_TEAM_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (TEAM, CONFIG),
-	                    nmc_property_team_get_config,
-	                    nmc_property_team_set_config,
-	                    NULL,
-	                    nmc_property_team_describe_config,
-	                    NULL,
-	                    NULL);
+	if (modified)
+		*value_coerced = g_strjoinv (" ", strv);
 
-	/* Add editable properties for NM_SETTING_TEAM_PORT_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (TEAM_PORT, CONFIG),
-	                    nmc_property_team_port_get_config,
-	                    nmc_property_team_set_config,
-	                    NULL,
-	                    nmc_property_team_describe_config,
-	                    NULL,
-	                    NULL);
+	return TRUE;
+}
 
-	/* Add editable properties for NM_SETTING_VLAN_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (VLAN, PARENT),
-	                    nmc_property_vlan_get_parent,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VLAN, ID),
-	                    nmc_property_vlan_get_id,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VLAN, FLAGS),
-	                    nmc_property_vlan_get_flags,
-	                    nmc_property_set_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VLAN, INGRESS_PRIORITY_MAP),
-	                    nmc_property_vlan_get_ingress_priority_map,
-	                    nmc_property_vlan_set_ingress_priority_map,
-	                    nmc_property_vlan_remove_ingress_priority_map,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VLAN, EGRESS_PRIORITY_MAP),
-	                    nmc_property_vlan_get_egress_priority_map,
-	                    nmc_property_vlan_set_egress_priority_map,
-	                    nmc_property_vlan_remove_egress_priority_map,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+/*****************************************************************************/
 
-	/* Add editable properties for NM_SETTING_VPN_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (VPN, SERVICE_TYPE),
-	                    nmc_property_vpn_get_service_type,
-	                    nmc_property_set_vpn_service,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VPN, USER_NAME),
-	                    nmc_property_vpn_get_user_name,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VPN, DATA),
-	                    nmc_property_vpn_get_data,
-	                    nmc_property_vpn_set_data,
-	                    nmc_property_vpn_remove_option_data,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VPN, SECRETS),
-	                    nmc_property_vpn_get_secrets,
-	                    nmc_property_vpn_set_secrets,
-	                    nmc_property_vpn_remove_option_secret,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VPN, PERSISTENT),
-	                    nmc_property_vpn_get_persistent,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+static void
+_env_warn_fcn_handle (const NMMetaEnvironment *environment,
+                      gpointer environment_user_data,
+                      NMMetaEnvWarnLevel warn_level,
+                      const char *fmt_l10n, /* the untranslated format string, but it is marked for translation using N_(). */
+                      va_list ap)
+{
+	gs_free char *m = NULL;
 
-	nmc_add_prop_funcs (GLUE (VPN, TIMEOUT),
-	                    nmc_property_vpn_get_timeout,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	NM_PRAGMA_WARNING_DISABLE("-Wformat-nonliteral")
+	m = g_strdup_vprintf (_(fmt_l10n), ap);
+	NM_PRAGMA_WARNING_REENABLE
 
-	/* Add editable properties for NM_SETTING_WIMAX_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (WIMAX, NETWORK_NAME),
-	                    nmc_property_wimax_get_network_name,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIMAX, MAC_ADDRESS),
-	                    nmc_property_wimax_get_mac_address,
-	                    nmc_property_set_mac,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	switch (warn_level) {
+	case NM_META_ENV_WARN_LEVEL_WARN:
+		g_print (_("Warning: %s\n"), m);
+		return;
+	case NM_META_ENV_WARN_LEVEL_INFO:
+		g_print (_("Info: %s\n"), m);
+		return;
+	}
+	g_print (_("Error: %s\n"), m);
+}
 
-	/* Add editable properties for NM_SETTING_WIRED_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (WIRED, PORT),
-	                    nmc_property_wired_get_port,
-	                    NULL, /* nmc_property_wired_set_port, */
-	                    NULL,
-	                    NULL,
-	                    NULL, /* nmc_property_wired_allowed_port, */
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, SPEED),
-	                    nmc_property_wired_get_speed,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, DUPLEX),
-	                    nmc_property_wired_get_duplex,
-	                    nmc_property_wired_set_duplex,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_wired_allowed_duplex,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, AUTO_NEGOTIATE),
-	                    nmc_property_wired_get_auto_negotiate,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, MAC_ADDRESS),
-	                    nmc_property_wired_get_mac_address,
-	                    nmc_property_set_mac,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, CLONED_MAC_ADDRESS),
-	                    nmc_property_wired_get_cloned_mac_address,
-	                    nmc_property_set_mac_cloned,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, GENERATE_MAC_ADDRESS_MASK),
-	                    nmc_property_wired_get_generate_mac_address_mask,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, MAC_ADDRESS_BLACKLIST),
-	                    nmc_property_wired_get_mac_address_blacklist,
-	                    nmc_property_wired_set_mac_address_blacklist,
-	                    nmc_property_wired_remove_mac_address_blacklist,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, MTU),
-	                    nmc_property_wired_get_mtu,
-	                    nmc_property_set_mtu,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, S390_SUBCHANNELS),
-	                    nmc_property_wired_get_s390_subchannels,
-	                    nmc_property_wired_set_s390_subchannels,
-	                    NULL,
-	                    nmc_property_wired_describe_s390_subchannels,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, S390_NETTYPE),
-	                    nmc_property_wired_get_s390_nettype,
-	                    nmc_property_wired_set_s390_nettype,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_wired_allowed_s390_nettype,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, S390_OPTIONS),
-	                    nmc_property_wired_get_s390_options,
-	                    nmc_property_wired_set_s390_options,
-	                    nmc_property_wired_remove_option_s390_options,
-	                    nmc_property_wired_describe_s390_options,
-	                    nmc_property_wired_allowed_s390_options,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, WAKE_ON_LAN),
-	                    nmc_property_wired_get_wake_on_lan,
-	                    nmc_property_wired_set_wake_on_lan,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRED, WAKE_ON_LAN_PASSWORD),
-	                    nmc_property_wired_get_wake_on_lan_password,
-	                    nmc_property_set_mac,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+static NMDevice *const*
+_env_get_nm_devices (const NMMetaEnvironment *environment,
+                     gpointer environment_user_data,
+                     guint *out_len)
+{
+	NmCli *nmc = environment_user_data;
+	const GPtrArray *devices;
 
-	/* Add editable properties for NM_SETTING_WIRELESS_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (WIRELESS, SSID),
-	                    nmc_property_wireless_get_ssid,
-	                    nmc_property_set_ssid,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, MODE),
-	                    nmc_property_wireless_get_mode,
-	                    nmc_property_wifi_set_mode,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_wifi_allowed_mode,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, BAND),
-	                    nmc_property_wireless_get_band,
-	                    nmc_property_wifi_set_band,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_wifi_allowed_band,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, CHANNEL),
-	                    nmc_property_wireless_get_channel,
-	                    nmc_property_wifi_set_channel,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, BSSID),
-	                    nmc_property_wireless_get_bssid,
-	                    nmc_property_set_mac,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	/*
-	 * Do not allow setting 'rate' and 'tx-power'. They are not implemented in
-	 * NM core, nor in ifcfg-rh plugin (thus not preserved over re-reading).
-	 */
-	nmc_add_prop_funcs (GLUE (WIRELESS, RATE),
-	                    nmc_property_wireless_get_rate,
-	                    NULL, /* editing rate disabled */
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, TX_POWER),
-	                    nmc_property_wireless_get_tx_power,
-	                    NULL, /* editing tx-power disabled */
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, MAC_ADDRESS),
-	                    nmc_property_wireless_get_mac_address,
-	                    nmc_property_set_mac,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, CLONED_MAC_ADDRESS),
-	                    nmc_property_wireless_get_cloned_mac_address,
-	                    nmc_property_set_mac_cloned,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, GENERATE_MAC_ADDRESS_MASK),
-	                    nmc_property_wireless_get_generate_mac_address_mask,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, MAC_ADDRESS_BLACKLIST),
-	                    nmc_property_wireless_get_mac_address_blacklist,
-	                    nmc_property_wireless_set_mac_address_blacklist,
-	                    nmc_property_wireless_remove_mac_address_blacklist,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, SEEN_BSSIDS),
-	                    nmc_property_wireless_get_seen_bssids,
-	                    NULL, /* read-only */
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, MTU),
-	                    nmc_property_wireless_get_mtu,
-	                    nmc_property_set_mtu,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, HIDDEN),
-	                    nmc_property_wireless_get_hidden,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, POWERSAVE),
-	                    nmc_property_wireless_get_powersave,
-	                    nmc_property_wireless_set_powersave,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS, MAC_ADDRESS_RANDOMIZATION),
-	                    nmc_property_wireless_get_mac_address_randomization,
-	                    nmc_property_wireless_set_mac_address_randomization,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	nm_assert (nmc);
 
-	/* Add editable properties for NM_SETTING_WIRELESS_SECURITY_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, KEY_MGMT),
-	                    nmc_property_wifi_sec_get_key_mgmt,
-	                    nmc_property_wifi_sec_set_key_mgmt,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_wifi_sec_allowed_key_mgmt,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, WEP_TX_KEYIDX),
-	                    nmc_property_wifi_sec_get_wep_tx_keyidx,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, AUTH_ALG),
-	                    nmc_property_wifi_sec_get_auth_alg,
-	                    nmc_property_wifi_sec_set_auth_alg,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_wifi_sec_allowed_auth_alg,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, PROTO),
-	                    nmc_property_wifi_sec_get_proto,
-	                    nmc_property_wifi_sec_set_proto,
-	                    nmc_property_wifi_sec_remove_proto,
-	                    NULL,
-	                    nmc_property_wifi_sec_allowed_proto,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, PAIRWISE),
-	                    nmc_property_wifi_sec_get_pairwise,
-	                    nmc_property_wifi_sec_set_pairwise,
-	                    nmc_property_wifi_sec_remove_pairwise,
-	                    NULL,
-	                    nmc_property_wifi_sec_allowed_pairwise,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, GROUP),
-	                    nmc_property_wifi_sec_get_group,
-	                    nmc_property_wifi_sec_set_group,
-	                    nmc_property_wifi_sec_remove_group,
-	                    NULL,
-	                    nmc_property_wifi_sec_allowed_group,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, LEAP_USERNAME),
-	                    nmc_property_wifi_sec_get_leap_username,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, WEP_KEY0),
-	                    nmc_property_wifi_sec_get_wep_key0,
-	                    nmc_property_wifi_set_wep_key,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, WEP_KEY1),
-	                    nmc_property_wifi_sec_get_wep_key1,
-	                    nmc_property_wifi_set_wep_key,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, WEP_KEY2),
-	                    nmc_property_wifi_sec_get_wep_key2,
-	                    nmc_property_wifi_set_wep_key,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, WEP_KEY3),
-	                    nmc_property_wifi_sec_get_wep_key3,
-	                    nmc_property_wifi_set_wep_key,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, WEP_KEY_FLAGS),
-	                    nmc_property_wifi_sec_get_wep_key_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, WEP_KEY_TYPE),
-	                    nmc_property_wifi_sec_get_wep_key_type,
-	                    nmc_property_wifi_set_wep_key_type,
-	                    NULL,
-	                    nmc_property_wifi_describe_wep_key_type,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, PSK),
-	                    nmc_property_wifi_sec_get_psk,
-	                    nmc_property_wifi_set_psk,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, PSK_FLAGS),
-	                    nmc_property_wifi_sec_get_psk_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, LEAP_PASSWORD),
-	                    nmc_property_wifi_sec_get_leap_password,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, LEAP_PASSWORD_FLAGS),
-	                    nmc_property_wifi_sec_get_leap_password_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	/* the returned list is *not* NULL terminated. Need to
+	 * provide and honor the out_len argument. */
+	nm_assert (out_len);
 
-	/* Add editable properties for NM_SETTING_TUN_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (TUN, MODE),
-	                    nmc_property_tun_get_mode,
-	                    nmc_property_tun_set_mode,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_tun_allowed_mode,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (TUN, OWNER),
-	                    nmc_property_tun_get_owner,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (TUN, GROUP),
-	                    nmc_property_tun_get_group,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (TUN, PI),
-	                    nmc_property_tun_get_pi,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (TUN, VNET_HDR),
-	                    nmc_property_tun_get_vnet_hdr,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (TUN, MULTI_QUEUE),
-	                    nmc_property_tun_get_multi_queue,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	devices = nm_client_get_devices (nmc->client);
+	if (!devices) {
+		*out_len = 0;
+		return NULL;
+	}
 
-	/* Add editable properties for NM_SETTING_IP_TUNNEL_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, MODE),
-	                    nmc_property_ip_tunnel_get_mode,
-	                    nmc_property_ip_tunnel_set_mode,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_ip_tunnel_allowed_mode,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, PARENT),
-	                    nmc_property_ip_tunnel_get_parent,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, LOCAL),
-	                    nmc_property_ip_tunnel_get_local,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, REMOTE),
-	                    nmc_property_ip_tunnel_get_remote,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, TTL),
-	                    nmc_property_ip_tunnel_get_ttl,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, TOS),
-	                    nmc_property_ip_tunnel_get_tos,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, PATH_MTU_DISCOVERY),
-	                    nmc_property_ip_tunnel_get_path_mtu_discovery,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, INPUT_KEY),
-	                    nmc_property_ip_tunnel_get_input_key,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, OUTPUT_KEY),
-	                    nmc_property_ip_tunnel_get_output_key,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, ENCAPSULATION_LIMIT),
-	                    nmc_property_ip_tunnel_get_encapsulation_limit,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, FLOW_LABEL),
-	                    nmc_property_ip_tunnel_get_flow_label,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (IP_TUNNEL, MTU),
-	                    nmc_property_ip_tunnel_get_mtu,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	*out_len = devices->len;
+	return (NMDevice *const*) devices->pdata;
+}
 
-	/* Add editable properties for NM_SETTING_MACSEC_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (MACSEC, PARENT),
-	                    nmc_property_macsec_get_parent,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACSEC, MODE),
-	                    nmc_property_macsec_get_mode,
-	                    nmc_property_macsec_set_mode,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_macsec_allowed_mode,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACSEC, ENCRYPT),
-	                    nmc_property_macsec_get_encrypt,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACSEC, MKA_CAK),
-	                    nmc_property_macsec_get_mka_cak,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACSEC, MKA_CAK_FLAGS),
-	                    nmc_property_macsec_get_mka_cak_flags,
-	                    nmc_property_set_secret_flags,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACSEC, MKA_CKN),
-	                    nmc_property_macsec_get_mka_ckn,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACSEC, PORT),
-	                    nmc_property_macsec_get_port,
-	                    nmc_property_set_int,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACSEC, VALIDATION),
-	                    nmc_property_macsec_get_validation,
-	                    nmc_property_macsec_set_validation,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_macsec_allowed_validation,
-	                    NULL);
+static NMRemoteConnection *const*
+_env_get_nm_connections (const NMMetaEnvironment *environment,
+                         gpointer environment_user_data,
+                         guint *out_len)
+{
+	NmCli *nmc = environment_user_data;
+	const GPtrArray *values;
 
-	/* Add editable properties for NM_SETTING_MACVLAN_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (MACVLAN, PARENT),
-	                    nmc_property_macvlan_get_parent,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACVLAN, MODE),
-	                    nmc_property_macvlan_get_mode,
-	                    nmc_property_macvlan_set_mode,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_macvlan_allowed_mode,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACVLAN, PROMISCUOUS),
-	                    nmc_property_macvlan_get_promiscuous,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (MACVLAN, TAP),
-	                    nmc_property_macvlan_get_tap,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	nm_assert (nmc);
 
-	/* Add editable properties for NM_SETTING_VXLAN_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (VXLAN, PARENT),
-	                    nmc_property_vxlan_get_parent,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, ID),
-	                    nmc_property_vxlan_get_id,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, LOCAL),
-	                    nmc_property_vxlan_get_local,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, REMOTE),
-	                    nmc_property_vxlan_get_remote,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, SOURCE_PORT_MIN),
-	                    nmc_property_vxlan_get_source_port_min,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, SOURCE_PORT_MAX),
-	                    nmc_property_vxlan_get_source_port_max,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, DESTINATION_PORT),
-	                    nmc_property_vxlan_get_destination_port,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, TOS),
-	                    nmc_property_vxlan_get_tos,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, TTL),
-	                    nmc_property_vxlan_get_ttl,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, AGEING),
-	                    nmc_property_vxlan_get_ageing,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, LIMIT),
-	                    nmc_property_vxlan_get_limit,
-	                    nmc_property_set_uint,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, LEARNING),
-	                    nmc_property_vxlan_get_learning,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, PROXY),
-	                    nmc_property_vxlan_get_proxy,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, RSC),
-	                    nmc_property_vxlan_get_rsc,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, L2_MISS),
-	                    nmc_property_vxlan_get_l2_miss,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (VXLAN, L3_MISS),
-	                    nmc_property_vxlan_get_l3_miss,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
+	/* the returned list is *not* NULL terminated. Need to
+	 * provide and honor the out_len argument. */
+	nm_assert (out_len);
 
-	/* Add editable properties for NM_SETTING_PROXY_SETTING_NAME */
-	nmc_add_prop_funcs (GLUE (PROXY, METHOD),
-	                    nmc_property_proxy_get_method,
-	                    nmc_property_proxy_set_method,
-	                    NULL,
-	                    NULL,
-	                    nmc_property_proxy_allowed_method,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PROXY, BROWSER_ONLY),
-	                    nmc_property_proxy_get_browser_only,
-	                    nmc_property_set_bool,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PROXY, PAC_URL),
-	                    nmc_property_proxy_get_pac_url,
-	                    nmc_property_set_string,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-	nmc_add_prop_funcs (GLUE (PROXY, PAC_SCRIPT),
-	                    nmc_property_proxy_get_pac_script,
-	                    nmc_property_proxy_set_pac_script,
-	                    NULL,
-	                    NULL,
-	                    NULL,
-	                    NULL);
-}
+	values = nm_client_get_connections (nmc->client);
+	if (!values) {
+		*out_len = 0;
+		return NULL;
+	}
 
-void
-nmc_properties_cleanup ()
-{
-	if (nmc_properties)
-		g_hash_table_destroy (nmc_properties);
+	*out_len = values->len;
+	return (NMRemoteConnection *const*) values->pdata;
 }
 
-static const NmcPropertyFuncs *
-nmc_properties_find (const char *s_name, const char *p_name)
-{
-	char *key;
-	gsize p_l, s_l;
+/*****************************************************************************/
 
-	nmc_properties_init ();
+const NMMetaEnvironment *const nmc_meta_environment = &((NMMetaEnvironment) {
+	.warn_fcn = _env_warn_fcn_handle,
+	.get_nm_devices = _env_get_nm_devices,
+	.get_nm_connections = _env_get_nm_connections,
+});
 
-	s_l = strlen (s_name);
-	p_l = strlen (p_name);
-	key = g_alloca (s_l + p_l + 1);
-	memcpy (&key[  0], s_name, s_l);
-	memcpy (&key[s_l], p_name, p_l + 1);
-	return (NmcPropertyFuncs *) g_hash_table_lookup (nmc_properties, key);
-}
+NmCli *const nmc_meta_environment_arg = &nm_cli;
 
 static char *
-get_property_val (NMSetting *setting, const char *prop, NmcPropertyGetType get_type, GError **error)
+get_property_val (NMSetting *setting, const char *prop, NMMetaAccessorGetType get_type, gboolean show_secrets, GError **error)
 {
-	const NmcPropertyFuncs *item;
+	const NMMetaPropertyInfo *property_info;
 
-	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
+	g_return_val_if_fail (!error || !*error, NULL);
+	g_return_val_if_fail (NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_PARSABLE, NM_META_ACCESSOR_GET_TYPE_PRETTY), NULL);
 
-	item = nmc_properties_find (nm_setting_get_name (setting), prop);
-	if (item && item->get_func)
-		return item->get_func (setting, get_type);
+	if ((property_info = nm_meta_property_info_find_by_setting (setting, prop))) {
+		if (property_info->property_type->get_fcn) {
+			NMMetaAccessorGetOutFlags out_flags = NM_META_ACCESSOR_GET_OUT_FLAGS_NONE;
+			char *to_free = NULL;
+			const char *value;
+
+			value = property_info->property_type->get_fcn (property_info,
+			                                               nmc_meta_environment,
+			                                               nmc_meta_environment_arg,
+			                                               setting,
+			                                               get_type,
+			                                               show_secrets ? NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS : 0,
+			                                               &out_flags,
+			                                               (gpointer *) &to_free);
+			nm_assert (!out_flags);
+			return to_free ?: g_strdup (value);
+		}
+	}
 
 	g_set_error_literal (error, 1, 0, _("don't know how to get the property value"));
 	return NULL;
@@ -8417,7 +488,7 @@ get_property_val (NMSetting *setting, const char *prop, NmcPropertyGetType get_t
 char *
 nmc_setting_get_property (NMSetting *setting, const char *prop, GError **error)
 {
-	return get_property_val (setting, prop, NMC_PROPERTY_GET_PRETTY, error);
+	return get_property_val (setting, prop, NM_META_ACCESSOR_GET_TYPE_PRETTY, TRUE, error);
 }
 
 /*
@@ -8427,33 +498,70 @@ nmc_setting_get_property (NMSetting *setting, const char *prop, GError **error)
 char *
 nmc_setting_get_property_parsable (NMSetting *setting, const char *prop, GError **error)
 {
-	return get_property_val (setting, prop, NMC_PROPERTY_GET_PARSABLE, error);
+	return get_property_val (setting, prop, NM_META_ACCESSOR_GET_TYPE_PARSABLE, TRUE, error);
+}
+
+static gboolean
+_set_fcn_call (const NMMetaPropertyInfo *property_info,
+               NMSetting *setting,
+               const char *value,
+               GError **error)
+{
+	return property_info->property_type->set_fcn (property_info,
+	                                              nmc_meta_environment,
+	                                              nmc_meta_environment_arg,
+	                                              setting,
+	                                              value,
+	                                              error);
 }
 
 /*
  * Generic function for setting property value.
  *
- * Sets property=val in setting by calling specialized functions.
- * If val is NULL then default property value is set.
+ * Sets property=value in setting by calling specialized functions.
+ * If value is NULL then default property value is set.
  *
  * Returns: TRUE on success; FALSE on failure and sets error
  */
 gboolean
-nmc_setting_set_property (NMSetting *setting, const char *prop, const char *val, GError **error)
+nmc_setting_set_property (NMSetting *setting, const char *prop, const char *value, GError **error)
 {
-	const NmcPropertyFuncs *item;
+	const NMMetaPropertyInfo *property_info;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	item = nmc_properties_find (nm_setting_get_name (setting), prop);
-	if (item && item->set_func) {
-		if (!val) {
+	if ((property_info = nm_meta_property_info_find_by_setting (setting, prop))) {
+
+		if (!value) {
 			/* No value argument sets default value */
 			nmc_property_set_default_value (setting, prop);
 			return TRUE;
 		}
-		return item->set_func (setting, prop, val, error);
+
+		if (property_info->property_type->set_fcn) {
+			switch (property_info->setting_info->general->meta_type) {
+			case NM_META_SETTING_TYPE_CONNECTION:
+				if (nm_streq (property_info->property_name, NM_SETTING_CONNECTION_SECONDARIES)) {
+					gs_free char *value_coerced = NULL;
+
+					if (!_set_fcn_precheck_connection_secondaries (value, &value_coerced, error))
+						return FALSE;
+
+					return _set_fcn_call (property_info,
+					                      setting,
+					                      value_coerced ?: value,
+					                      error);
+				}
+				break;
+			default:
+				break;
+			}
+			return _set_fcn_call (property_info,
+			                      setting,
+			                      value,
+			                      error);
+		}
 	}
 
 	g_set_error_literal (error, 1, 0, _("the property can't be changed"));
@@ -8486,16 +594,18 @@ nmc_property_set_default_value (NMSetting *setting, const char *prop)
 gboolean
 nmc_setting_reset_property (NMSetting *setting, const char *prop, GError **error)
 {
-	const NmcPropertyFuncs *item;
+	const NMMetaPropertyInfo *property_info;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	item = nmc_properties_find (nm_setting_get_name (setting), prop);
-	if (item && item->set_func) {
-		nmc_property_set_default_value (setting, prop);
-		return TRUE;
+	if ((property_info = nm_meta_property_info_find_by_setting (setting, prop))) {
+		if (property_info->property_type->set_fcn) {
+			nmc_property_set_default_value (setting, prop);
+			return TRUE;
+		}
 	}
+
 	g_set_error_literal (error, 1, 0, _("the property can't be changed"));
 	return FALSE;
 }
@@ -8516,14 +626,22 @@ nmc_setting_remove_property_option (NMSetting *setting,
                                     guint32 idx,
                                     GError **error)
 {
-	const NmcPropertyFuncs *item;
+	const NMMetaPropertyInfo *property_info;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	item = nmc_properties_find (nm_setting_get_name (setting), prop);
-	if (item && item->remove_func)
-		return item->remove_func (setting, prop, option, idx, error);
+	if ((property_info = nm_meta_property_info_find_by_setting (setting, prop))) {
+		if (property_info->property_type->remove_fcn) {
+			return property_info->property_type->remove_fcn (property_info,
+			                                                 nmc_meta_environment,
+			                                                 nmc_meta_environment_arg,
+			                                                 setting,
+			                                                 option,
+			                                                 idx,
+			                                                 error);
+		}
+	}
 
 	return TRUE;
 }
@@ -8559,26 +677,27 @@ nmc_setting_get_valid_properties (NMSetting *setting)
 	return valid_props;
 }
 
-/*
- * Return allowed values for 'prop' as a string.
- */
-const char **
-nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop)
+const char *const*
+nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop, char ***out_to_free)
 {
-
-	const NmcPropertyFuncs *item;
+	const NMMetaPropertyInfo *property_info;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+	g_return_val_if_fail (out_to_free, FALSE);
+
+	*out_to_free = NULL;
 
-	item = nmc_properties_find (nm_setting_get_name (setting), prop);
-	if (item && item->values_func)
-		return item->values_func (setting, prop);
+	if ((property_info = nm_meta_property_info_find_by_setting (setting, prop))) {
+		if (property_info->property_type->values_fcn) {
+			return property_info->property_type->values_fcn (property_info,
+			                                                 out_to_free);
+		} else if (property_info->property_typ_data && property_info->property_typ_data->values_static)
+			return property_info->property_typ_data->values_static;
+	}
 
 	return NULL;
 }
 
-#include "settings-docs.c"
-
 /*
  * Create a description string for a property.
  *
@@ -8590,22 +709,33 @@ nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop)
 char *
 nmc_setting_get_property_desc (NMSetting *setting, const char *prop)
 {
-	const NmcPropertyFuncs *item;
+	gs_free char *desc_to_free = NULL;
 	const char *setting_desc = NULL;
 	const char *setting_desc_title = "";
 	const char *nmcli_desc = NULL;
 	const char *nmcli_desc_title = "";
 	const char *nmcli_nl = "";
+	const NMMetaPropertyInfo *property_info;
+	const char *desc = NULL;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
 
-	setting_desc = nmc_setting_get_property_doc (setting, prop);
-	if (setting_desc)
+	property_info = nm_meta_property_info_find_by_setting (setting, prop);
+	if (!property_info)
+		return NULL;
+
+	if (property_info->describe_doc) {
+		setting_desc = _(property_info->describe_doc);
 		setting_desc_title = _("[NM property description]");
+	}
+
+	if (property_info->property_type->describe_fcn) {
+		desc = property_info->property_type->describe_fcn (property_info, &desc_to_free);
+	} else
+		desc = _(property_info->describe_message);
 
-	item = nmc_properties_find (nm_setting_get_name (setting), prop);
-	if (item && item->describe_func) {
-		nmcli_desc = item->describe_func (setting, prop);
+	if (desc) {
+		nmcli_desc = desc;
 		nmcli_desc_title = _("[nmcli specific description]");
 		nmcli_nl = "\n";
 	}
@@ -8652,1271 +782,35 @@ nmc_property_set_gvalue (NMSetting *setting, const char *prop, GValue *value)
 	return FALSE;
 }
 
-/*----------------------------------------------------------------------------*/
-
-#define GET_SECRET(show, setting, func, type) \
-	(show ? func (setting, type) : g_strdup (_("<hidden>")))
-
-static gboolean
-setting_connection_details (NMSetting *setting, NmCli *nmc,
-                            const char *one_prop,
-                            gboolean secrets,
-                            NmcPropertyGetType type)
-{
-	NMSettingConnection *s_con = NM_SETTING_CONNECTION (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (s_con), FALSE);
-
-	tmpl = nmc_fields_setting_connection;
-	tmpl_len = sizeof (nmc_fields_setting_connection);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_CONNECTION_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_connection_get_id (setting, type));
-	set_val_str (arr, 2, nmc_property_connection_get_uuid (setting, type));
-	set_val_str (arr, 3, nmc_property_connection_get_stable_id (setting, type));
-	set_val_str (arr, 4, nmc_property_connection_get_interface_name (setting, type));
-	set_val_str (arr, 5, nmc_property_connection_get_type (setting, type));
-	set_val_str (arr, 6, nmc_property_connection_get_autoconnect (setting, type));
-	set_val_str (arr, 7, nmc_property_connection_get_autoconnect_priority (setting, type));
-	set_val_str (arr, 8, nmc_property_connection_get_autoconnect_retries (setting, type));
-	set_val_str (arr, 9, nmc_property_connection_get_timestamp (setting, type));
-	set_val_str (arr, 10, nmc_property_connection_get_read_only (setting, type));
-	set_val_str (arr, 11, nmc_property_connection_get_permissions (setting, type));
-	set_val_str (arr, 12, nmc_property_connection_get_zone (setting, type));
-	set_val_str (arr, 13, nmc_property_connection_get_master (setting, type));
-	set_val_str (arr, 14, nmc_property_connection_get_slave_type (setting, type));
-	set_val_str (arr, 15, nmc_property_connection_get_autoconnect_slaves (setting, type));
-	set_val_str (arr, 16, nmc_property_connection_get_secondaries (setting, type));
-	set_val_str (arr, 17, nmc_property_connection_get_gateway_ping_timeout (setting, type));
-	set_val_str (arr, 18, nmc_property_connection_get_metered (setting, type));
-	set_val_str (arr, 19, nmc_property_connection_get_lldp (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_wired_details (NMSetting *setting,
-                       NmCli *nmc,
-                       const char *one_prop,
-                       gboolean secrets,
-                       NmcPropertyGetType type)
-{
-	NMSettingWired *s_wired = NM_SETTING_WIRED (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_WIRED (s_wired), FALSE);
-
-	tmpl = nmc_fields_setting_wired;
-	tmpl_len = sizeof (nmc_fields_setting_wired);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_WIRED_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_wired_get_port (setting, type));
-	set_val_str (arr, 2, nmc_property_wired_get_speed (setting, type));
-	set_val_str (arr, 3, nmc_property_wired_get_duplex (setting, type));
-	set_val_str (arr, 4, nmc_property_wired_get_auto_negotiate (setting, type));
-	set_val_str (arr, 5, nmc_property_wired_get_mac_address (setting, type));
-	set_val_str (arr, 6, nmc_property_wired_get_cloned_mac_address (setting, type));
-	set_val_str (arr, 7, nmc_property_wired_get_generate_mac_address_mask (setting, type));
-	set_val_str (arr, 8, nmc_property_wired_get_mac_address_blacklist (setting, type));
-	set_val_str (arr, 9, nmc_property_wired_get_mtu (setting, type));
-	set_val_str (arr, 10, nmc_property_wired_get_s390_subchannels (setting, type));
-	set_val_str (arr, 11, nmc_property_wired_get_s390_nettype (setting, type));
-	set_val_str (arr, 12, nmc_property_wired_get_s390_options (setting, type));
-	set_val_str (arr, 13, nmc_property_wired_get_wake_on_lan (setting, type));
-	set_val_str (arr, 14, nmc_property_wired_get_wake_on_lan_password (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_802_1X_details (NMSetting *setting,
-                        NmCli *nmc,
-                        const char *one_prop,
-                        gboolean secrets,
-                        NmcPropertyGetType type)
-{
-	NMSetting8021x *s_8021x = NM_SETTING_802_1X (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_802_1X (s_8021x), FALSE);
-
-	tmpl = nmc_fields_setting_8021X;
-	tmpl_len = sizeof (nmc_fields_setting_8021X);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_802_1X_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_802_1X_get_eap (setting, type));
-	set_val_str (arr, 2, nmc_property_802_1X_get_identity (setting, type));
-	set_val_str (arr, 3, nmc_property_802_1X_get_anonymous_identity (setting, type));
-	set_val_str (arr, 4, nmc_property_802_1X_get_pac_file (setting, type));
-	set_val_str (arr, 5, nmc_property_802_1X_get_ca_cert (setting, type));
-	set_val_str (arr, 6, GET_SECRET (secrets, setting, nmc_property_802_1X_get_ca_cert_password, type));
-	set_val_str (arr, 7, nmc_property_802_1X_get_ca_cert_password_flags (setting, type));
-	set_val_str (arr, 8, nmc_property_802_1X_get_ca_path (setting, type));
-	set_val_str (arr, 9, nmc_property_802_1X_get_subject_match (setting, type));
-	set_val_str (arr, 10, nmc_property_802_1X_get_altsubject_matches (setting, type));
-	set_val_str (arr, 11, nmc_property_802_1X_get_domain_suffix_match (setting, type));
-	set_val_str (arr, 12, nmc_property_802_1X_get_client_cert (setting, type, secrets));
-	set_val_str (arr, 13, GET_SECRET (secrets, setting, nmc_property_802_1X_get_client_cert_password, type));
-	set_val_str (arr, 14, nmc_property_802_1X_get_client_cert_password_flags (setting, type));
-	set_val_str (arr, 15, nmc_property_802_1X_get_phase1_peapver (setting, type));
-	set_val_str (arr, 16, nmc_property_802_1X_get_phase1_peaplabel (setting, type));
-	set_val_str (arr, 17, nmc_property_802_1X_get_phase1_fast_provisioning (setting, type));
-	set_val_str (arr, 18, nmc_property_802_1X_get_phase1_auth_flags (setting, type));
-	set_val_str (arr, 19, nmc_property_802_1X_get_phase2_auth (setting, type));
-	set_val_str (arr, 20, nmc_property_802_1X_get_phase2_autheap (setting, type));
-	set_val_str (arr, 21, nmc_property_802_1X_get_phase2_ca_cert (setting, type));
-	set_val_str (arr, 22, GET_SECRET (secrets, setting, nmc_property_802_1X_get_phase2_ca_cert_password, type));
-	set_val_str (arr, 23, nmc_property_802_1X_get_phase2_ca_cert_password_flags (setting, type));
-	set_val_str (arr, 24, nmc_property_802_1X_get_phase2_ca_path (setting, type));
-	set_val_str (arr, 25, nmc_property_802_1X_get_phase2_subject_match (setting, type));
-	set_val_str (arr, 26, nmc_property_802_1X_get_phase2_altsubject_matches (setting, type));
-	set_val_str (arr, 27, nmc_property_802_1X_get_phase2_domain_suffix_match (setting, type));
-	set_val_str (arr, 28, nmc_property_802_1X_get_phase2_client_cert (setting, type, secrets));
-	set_val_str (arr, 29, GET_SECRET (secrets, setting, nmc_property_802_1X_get_phase2_client_cert_password, type));
-	set_val_str (arr, 30, nmc_property_802_1X_get_phase2_client_cert_password_flags (setting, type));
-	set_val_str (arr, 31, GET_SECRET (secrets, setting, nmc_property_802_1X_get_password, type));
-	set_val_str (arr, 32, nmc_property_802_1X_get_password_flags (setting, type));
-	set_val_str (arr, 33, GET_SECRET (secrets, setting, nmc_property_802_1X_get_password_raw, type));
-	set_val_str (arr, 34, nmc_property_802_1X_get_password_raw_flags (setting, type));
-	set_val_str (arr, 35, nmc_property_802_1X_get_private_key (setting, type, secrets));
-	set_val_str (arr, 36, GET_SECRET (secrets, setting, nmc_property_802_1X_get_private_key_password, type));
-	set_val_str (arr, 37, nmc_property_802_1X_get_private_key_password_flags (setting, type));
-	set_val_str (arr, 38, nmc_property_802_1X_get_phase2_private_key (setting, type, secrets));
-	set_val_str (arr, 39, GET_SECRET (secrets, setting, nmc_property_802_1X_get_phase2_private_key_password, type));
-	set_val_str (arr, 40, nmc_property_802_1X_get_phase2_private_key_password_flags (setting, type));
-	set_val_str (arr, 41, GET_SECRET (secrets, setting, nmc_property_802_1X_get_pin, type));
-	set_val_str (arr, 42, nmc_property_802_1X_get_pin_flags (setting, type));
-	set_val_str (arr, 43, nmc_property_802_1X_get_system_ca_certs (setting, type));
-	set_val_str (arr, 44, nmc_property_802_1X_get_auth_timeout (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_wireless_details (NMSetting *setting,
-                          NmCli *nmc,
-                          const char *one_prop,
-                          gboolean secrets,
-                          NmcPropertyGetType type)
-{
-	NMSettingWireless *s_wireless = NM_SETTING_WIRELESS (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (s_wireless), FALSE);
-
-	tmpl = nmc_fields_setting_wireless;
-	tmpl_len = sizeof (nmc_fields_setting_wireless);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_WIRELESS_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_wireless_get_ssid (setting, type));
-	set_val_str (arr, 2, nmc_property_wireless_get_mode (setting, type));
-	set_val_str (arr, 3, nmc_property_wireless_get_band (setting, type));
-	set_val_str (arr, 4, nmc_property_wireless_get_channel (setting, type));
-	set_val_str (arr, 5, nmc_property_wireless_get_bssid (setting, type));
-	set_val_str (arr, 6, nmc_property_wireless_get_rate (setting, type));
-	set_val_str (arr, 7, nmc_property_wireless_get_tx_power (setting, type));
-	set_val_str (arr, 8, nmc_property_wireless_get_mac_address (setting, type));
-	set_val_str (arr, 9, nmc_property_wireless_get_cloned_mac_address (setting, type));
-	set_val_str (arr, 10, nmc_property_wireless_get_generate_mac_address_mask (setting, type));
-	set_val_str (arr, 11, nmc_property_wireless_get_mac_address_blacklist (setting, type));
-	set_val_str (arr, 12, nmc_property_wireless_get_mac_address_randomization (setting, type));
-	set_val_str (arr, 13, nmc_property_wireless_get_mtu (setting, type));
-	set_val_str (arr, 14, nmc_property_wireless_get_seen_bssids (setting, type));
-	set_val_str (arr, 15, nmc_property_wireless_get_hidden (setting, type));
-	set_val_str (arr, 16, nmc_property_wireless_get_powersave (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_wireless_security_details (NMSetting *setting,
-                                   NmCli *nmc,
-                                   const char *one_prop,
-                                   gboolean secrets,
-                                   NmcPropertyGetType type)
-{
-	NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (s_wireless_sec), FALSE);
-
-	tmpl = nmc_fields_setting_wireless_security;
-	tmpl_len = sizeof (nmc_fields_setting_wireless_security);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_WIRELESS_SECURITY_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_wifi_sec_get_key_mgmt (setting, type));
-	set_val_str (arr, 2, nmc_property_wifi_sec_get_wep_tx_keyidx (setting, type));
-	set_val_str (arr, 3, nmc_property_wifi_sec_get_auth_alg (setting, type));
-	set_val_str (arr, 4, nmc_property_wifi_sec_get_proto (setting, type));
-	set_val_str (arr, 5, nmc_property_wifi_sec_get_pairwise (setting, type));
-	set_val_str (arr, 6, nmc_property_wifi_sec_get_group (setting, type));
-	set_val_str (arr, 7, nmc_property_wifi_sec_get_leap_username (setting, type));
-	set_val_str (arr, 8, GET_SECRET (secrets, setting, nmc_property_wifi_sec_get_wep_key0, type));
-	set_val_str (arr, 9, GET_SECRET (secrets, setting, nmc_property_wifi_sec_get_wep_key1, type));
-	set_val_str (arr, 10, GET_SECRET (secrets, setting, nmc_property_wifi_sec_get_wep_key2, type));
-	set_val_str (arr, 11, GET_SECRET (secrets, setting, nmc_property_wifi_sec_get_wep_key3, type));
-	set_val_str (arr, 12, nmc_property_wifi_sec_get_wep_key_flags (setting, type));
-	set_val_str (arr, 13, nmc_property_wifi_sec_get_wep_key_type (setting, type));
-	set_val_str (arr, 14, GET_SECRET (secrets, setting, nmc_property_wifi_sec_get_psk, type));
-	set_val_str (arr, 15, nmc_property_wifi_sec_get_psk_flags (setting, type));
-	set_val_str (arr, 16, GET_SECRET (secrets, setting, nmc_property_wifi_sec_get_leap_password, type));
-	set_val_str (arr, 17, nmc_property_wifi_sec_get_leap_password_flags (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_ip4_config_details (NMSetting *setting,
-                            NmCli *nmc,
-                            const char *one_prop,
-                            gboolean secrets,
-                            NmcPropertyGetType type)
-{
-	NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (s_ip4), FALSE);
-
-	tmpl = nmc_fields_setting_ip4_config;
-	tmpl_len = sizeof (nmc_fields_setting_ip4_config);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_IP4_CONFIG_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_ipv4_get_method (setting, type));
-	set_val_str (arr, 2, nmc_property_ipv4_get_dns (setting, type));
-	set_val_str (arr, 3, nmc_property_ipv4_get_dns_search (setting, type));
-	set_val_str (arr, 4, nmc_property_ipv4_get_dns_options (setting, type));
-	set_val_str (arr, 5, nmc_property_ipv4_get_dns_priority (setting, type));
-	set_val_str (arr, 6, nmc_property_ip_get_addresses (setting, type));
-	set_val_str (arr, 7, nmc_property_ipv4_get_gateway (setting, type));
-	set_val_str (arr, 8, nmc_property_ipv4_get_routes (setting, type));
-	set_val_str (arr, 9, nmc_property_ipv4_get_route_metric (setting, type));
-	set_val_str (arr, 10, nmc_property_ipv4_get_ignore_auto_routes (setting, type));
-	set_val_str (arr, 11, nmc_property_ipv4_get_ignore_auto_dns (setting, type));
-	set_val_str (arr, 12, nmc_property_ipv4_get_dhcp_client_id (setting, type));
-	set_val_str (arr, 13, nmc_property_ipv4_get_dhcp_timeout (setting, type));
-	set_val_str (arr, 14, nmc_property_ipv4_get_dhcp_send_hostname (setting, type));
-	set_val_str (arr, 15, nmc_property_ipv4_get_dhcp_hostname (setting, type));
-	set_val_str (arr, 16, nmc_property_ipv4_get_dhcp_fqdn (setting, type));
-	set_val_str (arr, 17, nmc_property_ipv4_get_never_default (setting, type));
-	set_val_str (arr, 18, nmc_property_ipv4_get_may_fail (setting, type));
-	set_val_str (arr, 19, nmc_property_ipv4_get_dad_timeout (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_ip6_config_details (NMSetting *setting,
-                            NmCli *nmc,
-                            const char *one_prop,
-                            gboolean secrets,
-                            NmcPropertyGetType type)
-{
-	NMSettingIPConfig *s_ip6 = NM_SETTING_IP_CONFIG (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (s_ip6), FALSE);
-
-	tmpl = nmc_fields_setting_ip6_config;
-	tmpl_len = sizeof (nmc_fields_setting_ip6_config);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_IP6_CONFIG_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_ipv6_get_method (setting, type));
-	set_val_str (arr, 2, nmc_property_ipv6_get_dns (setting, type));
-	set_val_str (arr, 3, nmc_property_ipv6_get_dns_search (setting, type));
-	set_val_str (arr, 4, nmc_property_ipv6_get_dns_options (setting, type));
-	set_val_str (arr, 5, nmc_property_ipv6_get_dns_priority (setting, type));
-	set_val_str (arr, 6, nmc_property_ip_get_addresses (setting, type));
-	set_val_str (arr, 7, nmc_property_ipv6_get_gateway (setting, type));
-	set_val_str (arr, 8, nmc_property_ipv6_get_routes (setting, type));
-	set_val_str (arr, 9, nmc_property_ipv6_get_route_metric (setting, type));
-	set_val_str (arr, 10, nmc_property_ipv6_get_ignore_auto_routes (setting, type));
-	set_val_str (arr, 11, nmc_property_ipv6_get_ignore_auto_dns (setting, type));
-	set_val_str (arr, 12, nmc_property_ipv6_get_never_default (setting, type));
-	set_val_str (arr, 13, nmc_property_ipv6_get_may_fail (setting, type));
-	set_val_str (arr, 14, nmc_property_ipv6_get_ip6_privacy (setting, type));
-	set_val_str (arr, 15, nmc_property_ipv6_get_addr_gen_mode (setting, type));
-	set_val_str (arr, 16, nmc_property_ipv6_get_dhcp_send_hostname (setting, type));
-	set_val_str (arr, 17, nmc_property_ipv6_get_dhcp_hostname (setting, type));
-	set_val_str (arr, 18, nmc_property_ipv6_get_token (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_serial_details (NMSetting *setting,
-                        NmCli *nmc,
-                        const char *one_prop,
-                        gboolean secrets,
-                        NmcPropertyGetType type)
-{
-	NMSettingSerial *s_serial = NM_SETTING_SERIAL (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_SERIAL (s_serial), FALSE);
-
-	tmpl = nmc_fields_setting_serial;
-	tmpl_len = sizeof (nmc_fields_setting_serial);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_SERIAL_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_serial_get_baud (setting, type));
-	set_val_str (arr, 2, nmc_property_serial_get_bits (setting, type));
-	set_val_str (arr, 3, nmc_property_serial_get_parity (setting, type));
-	set_val_str (arr, 4, nmc_property_serial_get_stopbits (setting, type));
-	set_val_str (arr, 5, nmc_property_serial_get_send_delay (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_ppp_details (NMSetting *setting, NmCli *nmc,
-                     const char *one_prop,
-                     gboolean secrets,
-                     NmcPropertyGetType type)
-{
-	NMSettingPpp *s_ppp = NM_SETTING_PPP (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_PPP (s_ppp), FALSE);
-
-	tmpl = nmc_fields_setting_ppp;
-	tmpl_len = sizeof (nmc_fields_setting_ppp);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_PPP_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_ppp_get_noauth (setting, type));
-	set_val_str (arr, 2, nmc_property_ppp_get_refuse_eap (setting, type));
-	set_val_str (arr, 3, nmc_property_ppp_get_refuse_pap (setting, type));
-	set_val_str (arr, 4, nmc_property_ppp_get_refuse_chap (setting, type));
-	set_val_str (arr, 5, nmc_property_ppp_get_refuse_mschap (setting, type));
-	set_val_str (arr, 6, nmc_property_ppp_get_refuse_mschapv2 (setting, type));
-	set_val_str (arr, 7, nmc_property_ppp_get_nobsdcomp (setting, type));
-	set_val_str (arr, 8, nmc_property_ppp_get_nodeflate (setting, type));
-	set_val_str (arr, 9, nmc_property_ppp_get_no_vj_comp (setting, type));
-	set_val_str (arr, 10, nmc_property_ppp_get_require_mppe (setting, type));
-	set_val_str (arr, 11, nmc_property_ppp_get_require_mppe_128 (setting, type));
-	set_val_str (arr, 12, nmc_property_ppp_get_mppe_stateful (setting, type));
-	set_val_str (arr, 13, nmc_property_ppp_get_crtscts (setting, type));
-	set_val_str (arr, 14, nmc_property_ppp_get_baud (setting, type));
-	set_val_str (arr, 15, nmc_property_ppp_get_mru (setting, type));
-	set_val_str (arr, 16, nmc_property_ppp_get_mtu (setting, type));
-	set_val_str (arr, 17, nmc_property_ppp_get_lcp_echo_failure (setting, type));
-	set_val_str (arr, 18, nmc_property_ppp_get_lcp_echo_interval (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_pppoe_details (NMSetting *setting,
-                       NmCli *nmc,
-                       const char *one_prop,
-                       gboolean secrets,
-                       NmcPropertyGetType type)
-{
-	NMSettingPppoe *s_pppoe = NM_SETTING_PPPOE (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_PPPOE (s_pppoe), FALSE);
-
-	tmpl = nmc_fields_setting_pppoe;
-	tmpl_len = sizeof (nmc_fields_setting_pppoe);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_PPPOE_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_pppoe_get_service (setting, type));
-	set_val_str (arr, 2, nmc_property_pppoe_get_username (setting, type));
-	set_val_str (arr, 3, GET_SECRET (secrets, setting, nmc_property_pppoe_get_password, type));
-	set_val_str (arr, 4, nmc_property_pppoe_get_password_flags (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_gsm_details (NMSetting *setting,
-                     NmCli *nmc,
-                     const char *one_prop,
-                     gboolean secrets,
-                     NmcPropertyGetType type)
-{
-	NMSettingGsm *s_gsm = NM_SETTING_GSM (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_GSM (s_gsm), FALSE);
-
-	tmpl = nmc_fields_setting_gsm;
-	tmpl_len = sizeof (nmc_fields_setting_gsm);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_GSM_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_gsm_get_number (setting, type));
-	set_val_str (arr, 2, nmc_property_gsm_get_username (setting, type));
-	set_val_str (arr, 3, GET_SECRET (secrets, setting, nmc_property_gsm_get_password, type));
-	set_val_str (arr, 4, nmc_property_gsm_get_password_flags (setting, type));
-	set_val_str (arr, 5, nmc_property_gsm_get_apn (setting, type));
-	set_val_str (arr, 6, nmc_property_gsm_get_network_id (setting, type));
-	set_val_str (arr, 7, GET_SECRET (secrets, setting, nmc_property_gsm_get_pin, type));
-	set_val_str (arr, 8, nmc_property_gsm_get_pin_flags (setting, type));
-	set_val_str (arr, 9, nmc_property_gsm_get_home_only (setting, type));
-	set_val_str (arr, 10, nmc_property_gsm_get_device_id (setting, type));
-	set_val_str (arr, 11, nmc_property_gsm_get_sim_id (setting, type));
-	set_val_str (arr, 12, nmc_property_gsm_get_sim_operator_id (setting, type));
-	set_val_str (arr, 13, nmc_property_gsm_get_mtu (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_cdma_details (NMSetting *setting,
-                      NmCli *nmc,
-                      const char *one_prop,
-                      gboolean secrets,
-                      NmcPropertyGetType type)
-{
-	NMSettingCdma *s_cdma = NM_SETTING_CDMA (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_CDMA (s_cdma), FALSE);
-
-	tmpl = nmc_fields_setting_cdma;
-	tmpl_len = sizeof (nmc_fields_setting_cdma);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_CDMA_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_cdma_get_number (setting, type));
-	set_val_str (arr, 2, nmc_property_cdma_get_username (setting, type));
-	set_val_str (arr, 3, GET_SECRET (secrets, setting, nmc_property_cdma_get_password, type));
-	set_val_str (arr, 4, nmc_property_cdma_get_password_flags (setting, type));
-	set_val_str (arr, 5, nmc_property_cdma_get_mtu (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_bluetooth_details (NMSetting *setting,
-                           NmCli *nmc,
-                           const char *one_prop,
-                           gboolean secrets,
-                           NmcPropertyGetType type)
-{
-	NMSettingBluetooth *s_bluetooth = NM_SETTING_BLUETOOTH (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_BLUETOOTH (s_bluetooth), FALSE);
-
-	tmpl = nmc_fields_setting_bluetooth;
-	tmpl_len = sizeof (nmc_fields_setting_bluetooth);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_BLUETOOTH_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_bluetooth_get_bdaddr (setting, type));
-	set_val_str (arr, 2, nmc_property_bluetooth_get_type (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_olpc_mesh_details (NMSetting *setting,
-                           NmCli *nmc,
-                           const char *one_prop,
-                           gboolean secrets,
-                           NmcPropertyGetType type)
-{
-	NMSettingOlpcMesh *s_olpc_mesh = NM_SETTING_OLPC_MESH (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (s_olpc_mesh), FALSE);
-
-	tmpl = nmc_fields_setting_olpc_mesh;
-	tmpl_len = sizeof (nmc_fields_setting_olpc_mesh);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_OLPC_MESH_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_olpc_get_ssid (setting, type));
-	set_val_str (arr, 2, nmc_property_olpc_get_channel (setting, type));
-	set_val_str (arr, 3, nmc_property_olpc_get_anycast_address (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_vpn_details (NMSetting *setting,
-                     NmCli *nmc,
-                     const char *one_prop,
-                     gboolean secrets,
-                     NmcPropertyGetType type)
-{
-	NMSettingVpn *s_vpn = NM_SETTING_VPN (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_VPN (s_vpn), FALSE);
-
-	tmpl = nmc_fields_setting_vpn;
-	tmpl_len = sizeof (nmc_fields_setting_vpn);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_VPN_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_vpn_get_service_type (setting, type));
-	set_val_str (arr, 2, nmc_property_vpn_get_user_name (setting, type));
-	set_val_str (arr, 3, nmc_property_vpn_get_data (setting, type));
-	set_val_str (arr, 4, GET_SECRET (secrets, setting, nmc_property_vpn_get_secrets, type));
-	set_val_str (arr, 5, nmc_property_vpn_get_persistent (setting, type));
-	set_val_str (arr, 6, nmc_property_vpn_get_timeout (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_wimax_details (NMSetting *setting,
-                       NmCli *nmc,
-                       const char *one_prop,
-                       gboolean secrets,
-                       NmcPropertyGetType type)
-{
-	NMSettingWimax *s_wimax = NM_SETTING_WIMAX (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_WIMAX (s_wimax), FALSE);
-
-	tmpl = nmc_fields_setting_wimax;
-	tmpl_len = sizeof (nmc_fields_setting_wimax);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_WIMAX_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_wimax_get_mac_address (setting, type));
-	set_val_str (arr, 2, nmc_property_wimax_get_network_name (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_infiniband_details (NMSetting *setting,
-                            NmCli *nmc,
-                            const char *one_prop,
-                            gboolean secrets,
-                            NmcPropertyGetType type)
-{
-	NMSettingInfiniband *s_infiniband = NM_SETTING_INFINIBAND (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (s_infiniband), FALSE);
-
-	tmpl = nmc_fields_setting_infiniband;
-	tmpl_len = sizeof (nmc_fields_setting_infiniband);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_INFINIBAND_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_ib_get_mac_address (setting, type));
-	set_val_str (arr, 2, nmc_property_ib_get_mtu (setting, type));
-	set_val_str (arr, 3, nmc_property_ib_get_transport_mode (setting, type));
-	set_val_str (arr, 4, nmc_property_ib_get_p_key (setting, type));
-	set_val_str (arr, 5, nmc_property_ib_get_parent (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_bond_details (NMSetting *setting,
-                      NmCli *nmc,
-                      const char *one_prop,
-                      gboolean secrets,
-                      NmcPropertyGetType type)
-{
-	NMSettingBond *s_bond = NM_SETTING_BOND (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_BOND (s_bond), FALSE);
-
-	tmpl = nmc_fields_setting_bond;
-	tmpl_len = sizeof (nmc_fields_setting_bond);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_BOND_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_bond_get_options (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_vlan_details (NMSetting *setting,
-                      NmCli *nmc,
-                      const char *one_prop,
-                      gboolean secrets,
-                      NmcPropertyGetType type)
-{
-	NMSettingVlan *s_vlan = NM_SETTING_VLAN (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_VLAN (s_vlan), FALSE);
-
-	tmpl = nmc_fields_setting_vlan;
-	tmpl_len = sizeof (nmc_fields_setting_vlan);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_VLAN_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_vlan_get_parent (setting, type));
-	set_val_str (arr, 2, nmc_property_vlan_get_id (setting, type));
-	set_val_str (arr, 3, nmc_property_vlan_get_flags (setting, type));
-	set_val_str (arr, 4, nmc_property_vlan_get_ingress_priority_map (setting, type));
-	set_val_str (arr, 5, nmc_property_vlan_get_egress_priority_map (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_adsl_details (NMSetting *setting,
-                      NmCli *nmc,
-                      const char *one_prop,
-                      gboolean secrets,
-                      NmcPropertyGetType type)
-{
-	NMSettingAdsl *s_adsl = NM_SETTING_ADSL (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_ADSL (s_adsl), FALSE);
-
-	tmpl = nmc_fields_setting_adsl;
-	tmpl_len = sizeof (nmc_fields_setting_adsl);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_ADSL_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_adsl_get_username (setting, type));
-	set_val_str (arr, 2, GET_SECRET (secrets, setting, nmc_property_adsl_get_password, type));
-	set_val_str (arr, 3, nmc_property_adsl_get_password_flags (setting, type));
-	set_val_str (arr, 4, nmc_property_adsl_get_protocol (setting, type));
-	set_val_str (arr, 5, nmc_property_adsl_get_encapsulation (setting, type));
-	set_val_str (arr, 6, nmc_property_adsl_get_vpi (setting, type));
-	set_val_str (arr, 7, nmc_property_adsl_get_vci (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_bridge_details (NMSetting *setting,
-                        NmCli *nmc,
-                        const char *one_prop,
-                        gboolean secrets,
-                        NmcPropertyGetType type)
-{
-	NMSettingBridge *s_bridge = NM_SETTING_BRIDGE (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_BRIDGE (s_bridge), FALSE);
-
-	tmpl = nmc_fields_setting_bridge;
-	tmpl_len = sizeof (nmc_fields_setting_bridge);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_BRIDGE_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_bridge_get_mac_address (setting, type));
-	set_val_str (arr, 2, nmc_property_bridge_get_stp (setting, type));
-	set_val_str (arr, 3, nmc_property_bridge_get_priority (setting, type));
-	set_val_str (arr, 4, nmc_property_bridge_get_forward_delay (setting, type));
-	set_val_str (arr, 5, nmc_property_bridge_get_hello_time (setting, type));
-	set_val_str (arr, 6, nmc_property_bridge_get_max_age (setting, type));
-	set_val_str (arr, 7, nmc_property_bridge_get_ageing_time (setting, type));
-	set_val_str (arr, 8, nmc_property_bridge_get_multicast_snooping (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_bridge_port_details (NMSetting *setting,
-                             NmCli *nmc,
-                             const char *one_prop,
-                             gboolean secrets,
-                             NmcPropertyGetType type)
-{
-	NMSettingBridgePort *s_bridge_port = NM_SETTING_BRIDGE_PORT (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_BRIDGE_PORT (s_bridge_port), FALSE);
-
-	tmpl = nmc_fields_setting_bridge_port;
-	tmpl_len = sizeof (nmc_fields_setting_bridge_port);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_BRIDGE_PORT_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_bridge_port_get_priority (setting, type));
-	set_val_str (arr, 2, nmc_property_bridge_port_get_path_cost (setting, type));
-	set_val_str (arr, 3, nmc_property_bridge_port_get_hairpin_mode (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_team_details (NMSetting *setting,
-                      NmCli *nmc,
-                      const char *one_prop,
-                      gboolean secrets,
-                      NmcPropertyGetType type)
-{
-	NMSettingTeam *s_team = NM_SETTING_TEAM (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_TEAM (s_team), FALSE);
-
-	tmpl = nmc_fields_setting_team;
-	tmpl_len = sizeof (nmc_fields_setting_team);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_TEAM_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_team_get_config (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_team_port_details (NMSetting *setting,
-                           NmCli *nmc,
-                           const char *one_prop,
-                           gboolean secrets,
-                           NmcPropertyGetType type)
-{
-	NMSettingTeamPort *s_team_port = NM_SETTING_TEAM_PORT (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (s_team_port), FALSE);
-
-	tmpl = nmc_fields_setting_team_port;
-	tmpl_len = sizeof (nmc_fields_setting_team_port);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_TEAM_PORT_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_team_port_get_config (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_dcb_details (NMSetting *setting,
-                     NmCli *nmc,
-                     const char *one_prop,
-                     gboolean secrets,
-                     NmcPropertyGetType type)
-{
-	NMSettingDcb *s_dcb = NM_SETTING_DCB (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_DCB (s_dcb), FALSE);
-
-	tmpl = nmc_fields_setting_dcb;
-	tmpl_len = sizeof (nmc_fields_setting_dcb);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_DCB_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_dcb_get_app_fcoe_flags (setting, type));
-	set_val_str (arr, 2, nmc_property_dcb_get_app_fcoe_priority (setting, type));
-	set_val_str (arr, 3, nmc_property_dcb_get_app_fcoe_mode (setting, type));
-	set_val_str (arr, 4, nmc_property_dcb_get_app_iscsi_flags (setting, type));
-	set_val_str (arr, 5, nmc_property_dcb_get_app_iscsi_priority (setting, type));
-	set_val_str (arr, 6, nmc_property_dcb_get_app_fip_flags (setting, type));
-	set_val_str (arr, 7, nmc_property_dcb_get_app_fip_priority (setting, type));
-	set_val_str (arr, 8, nmc_property_dcb_get_pfc_flags (setting, type));
-	set_val_str (arr, 9, nmc_property_dcb_get_pfc (setting, type));
-	set_val_str (arr, 10, nmc_property_dcb_get_pg_flags (setting, type));
-	set_val_str (arr, 11, nmc_property_dcb_get_pg_group_id (setting, type));
-	set_val_str (arr, 12, nmc_property_dcb_get_pg_group_bandwidth (setting, type));
-	set_val_str (arr, 13, nmc_property_dcb_get_pg_bandwidth (setting, type));
-	set_val_str (arr, 14, nmc_property_dcb_get_pg_strict (setting, type));
-	set_val_str (arr, 15, nmc_property_dcb_get_pg_traffic_class (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_tun_details (NMSetting *setting,
-                     NmCli *nmc,
-                     const char *one_prop,
-                     gboolean secrets,
-                     NmcPropertyGetType type)
-{
-	NMSettingTun *s_tun = NM_SETTING_TUN (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_TUN (s_tun), FALSE);
-
-	tmpl = nmc_fields_setting_tun;
-	tmpl_len = sizeof (nmc_fields_setting_tun);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_TUN_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_tun_get_mode (setting, type));
-	set_val_str (arr, 2, nmc_property_tun_get_owner (setting, type));
-	set_val_str (arr, 3, nmc_property_tun_get_group (setting, type));
-	set_val_str (arr, 4, nmc_property_tun_get_pi (setting, type));
-	set_val_str (arr, 5, nmc_property_tun_get_vnet_hdr (setting, type));
-	set_val_str (arr, 6, nmc_property_tun_get_multi_queue (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_ip_tunnel_details (NMSetting *setting,
-                           NmCli *nmc,
-                           const char *one_prop,
-                           gboolean secrets,
-                           NmcPropertyGetType type)
-{
-	NMSettingIPTunnel *s_ip_tunnel = NM_SETTING_IP_TUNNEL (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (s_ip_tunnel), FALSE);
-
-	tmpl = nmc_fields_setting_ip_tunnel;
-	tmpl_len = sizeof (nmc_fields_setting_ip_tunnel);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_IP_TUNNEL_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_ip_tunnel_get_mode (setting, type));
-	set_val_str (arr, 2, nmc_property_ip_tunnel_get_parent (setting, type));
-	set_val_str (arr, 3, nmc_property_ip_tunnel_get_local (setting, type));
-	set_val_str (arr, 4, nmc_property_ip_tunnel_get_remote (setting, type));
-	set_val_str (arr, 5, nmc_property_ip_tunnel_get_ttl (setting, type));
-	set_val_str (arr, 6, nmc_property_ip_tunnel_get_tos (setting, type));
-	set_val_str (arr, 7, nmc_property_ip_tunnel_get_path_mtu_discovery (setting, type));
-	set_val_str (arr, 8, nmc_property_ip_tunnel_get_input_key (setting, type));
-	set_val_str (arr, 9, nmc_property_ip_tunnel_get_output_key (setting, type));
-	set_val_str (arr, 10, nmc_property_ip_tunnel_get_encapsulation_limit (setting, type));
-	set_val_str (arr, 11, nmc_property_ip_tunnel_get_flow_label (setting, type));
-	set_val_str (arr, 12, nmc_property_ip_tunnel_get_mtu (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_macsec_details (NMSetting *setting,
-                        NmCli *nmc,
-                        const char *one_prop,
-                        gboolean secrets,
-                        NmcPropertyGetType type)
-{
-	NMSettingMacsec *s_macsec = NM_SETTING_MACSEC (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_MACSEC (s_macsec), FALSE);
-
-	tmpl = nmc_fields_setting_macsec;
-	tmpl_len = sizeof (nmc_fields_setting_macsec);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_MACSEC_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_macsec_get_parent (setting, type));
-	set_val_str (arr, 2, nmc_property_macsec_get_mode (setting, type));
-	set_val_str (arr, 3, nmc_property_macsec_get_encrypt (setting, type));
-	set_val_str (arr, 4, GET_SECRET (secrets, setting, nmc_property_macsec_get_mka_cak, type));
-	set_val_str (arr, 5, nmc_property_macsec_get_mka_cak_flags (setting, type));
-	set_val_str (arr, 6, nmc_property_macsec_get_mka_ckn (setting, type));
-	set_val_str (arr, 7, nmc_property_macsec_get_port (setting, type));
-	set_val_str (arr, 8, nmc_property_macsec_get_validation (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_macvlan_details (NMSetting *setting,
-                         NmCli *nmc,
-                         const char *one_prop,
-                         gboolean secrets,
-                         NmcPropertyGetType type)
-{
-	NMSettingMacvlan *s_macvlan = NM_SETTING_MACVLAN (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_MACVLAN (s_macvlan), FALSE);
-
-	tmpl = nmc_fields_setting_macvlan;
-	tmpl_len = sizeof (nmc_fields_setting_macvlan);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_MACVLAN_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_macvlan_get_parent (setting, type));
-	set_val_str (arr, 2, nmc_property_macvlan_get_mode (setting, type));
-	set_val_str (arr, 3, nmc_property_macvlan_get_promiscuous (setting, type));
-	set_val_str (arr, 4, nmc_property_macvlan_get_tap (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_vxlan_details (NMSetting *setting,
-                       NmCli *nmc,
-                       const char *one_prop,
-                       gboolean secrets,
-                       NmcPropertyGetType type)
-{
-	NMSettingVxlan *s_vxlan = NM_SETTING_VXLAN (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_VXLAN (s_vxlan), FALSE);
-
-	tmpl = nmc_fields_setting_vxlan;
-	tmpl_len = sizeof (nmc_fields_setting_vxlan);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_VXLAN_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_vxlan_get_parent (setting, type));
-	set_val_str (arr, 2, nmc_property_vxlan_get_id (setting, type));
-	set_val_str (arr, 3, nmc_property_vxlan_get_local (setting, type));
-	set_val_str (arr, 4, nmc_property_vxlan_get_remote (setting, type));
-	set_val_str (arr, 5, nmc_property_vxlan_get_source_port_min (setting, type));
-	set_val_str (arr, 6, nmc_property_vxlan_get_source_port_max (setting, type));
-	set_val_str (arr, 7, nmc_property_vxlan_get_destination_port (setting, type));
-	set_val_str (arr, 8, nmc_property_vxlan_get_tos (setting, type));
-	set_val_str (arr, 9, nmc_property_vxlan_get_ttl (setting, type));
-	set_val_str (arr, 10, nmc_property_vxlan_get_ageing (setting, type));
-	set_val_str (arr, 11, nmc_property_vxlan_get_limit (setting, type));
-	set_val_str (arr, 12, nmc_property_vxlan_get_learning (setting, type));
-	set_val_str (arr, 13, nmc_property_vxlan_get_proxy (setting, type));
-	set_val_str (arr, 14, nmc_property_vxlan_get_rsc (setting, type));
-	set_val_str (arr, 15, nmc_property_vxlan_get_l2_miss (setting, type));
-	set_val_str (arr, 16, nmc_property_vxlan_get_l3_miss (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-static gboolean
-setting_proxy_details (NMSetting *setting,
-                       NmCli *nmc,
-                       const char *one_prop,
-                       gboolean secrets,
-                       NmcPropertyGetType type)
-{
-	NMSettingProxy *s_proxy = NM_SETTING_PROXY (setting);
-	NmcOutputField *tmpl, *arr;
-	size_t tmpl_len;
-
-	g_return_val_if_fail (NM_IS_SETTING_PROXY (s_proxy), FALSE);
-
-	tmpl = nmc_fields_setting_proxy;
-	tmpl_len = sizeof (nmc_fields_setting_proxy);
-	nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_PROXY_ALL,
-	                                                 tmpl, FALSE, NULL, NULL);
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (nmc->output_data, arr);
-
-	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
-	set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
-	set_val_str (arr, 1, nmc_property_proxy_get_method (setting, type));
-	set_val_str (arr, 2, nmc_property_proxy_get_browser_only (setting, type));
-	set_val_str (arr, 3, nmc_property_proxy_get_pac_url (setting, type));
-	set_val_str (arr, 4, nmc_property_proxy_get_pac_script (setting, type));
-	g_ptr_array_add (nmc->output_data, arr);
-
-	print_data (nmc);  /* Print all data */
-
-	return TRUE;
-}
-
-typedef struct {
-	const char *sname;
-	gboolean (*func) (NMSetting *setting,
-	                  NmCli *nmc,
-	                  const char *one_prop,
-	                  gboolean secrets,
-	                  NmcPropertyGetType type);
-} SettingDetails;
-
-static const SettingDetails detail_printers[] = {
-	{ NM_SETTING_CONNECTION_SETTING_NAME,        setting_connection_details },
-	{ NM_SETTING_WIRED_SETTING_NAME,             setting_wired_details },
-	{ NM_SETTING_802_1X_SETTING_NAME,            setting_802_1X_details },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,          setting_wireless_details },
-	{ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, setting_wireless_security_details },
-	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,        setting_ip4_config_details },
-	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,        setting_ip6_config_details },
-	{ NM_SETTING_SERIAL_SETTING_NAME,            setting_serial_details },
-	{ NM_SETTING_PPP_SETTING_NAME,               setting_ppp_details },
-	{ NM_SETTING_PPPOE_SETTING_NAME,             setting_pppoe_details },
-	{ NM_SETTING_GSM_SETTING_NAME,               setting_gsm_details },
-	{ NM_SETTING_CDMA_SETTING_NAME,              setting_cdma_details },
-	{ NM_SETTING_BLUETOOTH_SETTING_NAME,         setting_bluetooth_details },
-	{ NM_SETTING_OLPC_MESH_SETTING_NAME,         setting_olpc_mesh_details },
-	{ NM_SETTING_VPN_SETTING_NAME,               setting_vpn_details },
-	{ NM_SETTING_WIMAX_SETTING_NAME,             setting_wimax_details },
-	{ NM_SETTING_INFINIBAND_SETTING_NAME,        setting_infiniband_details },
-	{ NM_SETTING_BOND_SETTING_NAME,              setting_bond_details },
-	{ NM_SETTING_VLAN_SETTING_NAME,              setting_vlan_details },
-	{ NM_SETTING_ADSL_SETTING_NAME,              setting_adsl_details },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,            setting_bridge_details },
-	{ NM_SETTING_BRIDGE_PORT_SETTING_NAME,       setting_bridge_port_details },
-	{ NM_SETTING_TEAM_SETTING_NAME,              setting_team_details },
-	{ NM_SETTING_TEAM_PORT_SETTING_NAME,         setting_team_port_details },
-	{ NM_SETTING_DCB_SETTING_NAME,               setting_dcb_details },
-	{ NM_SETTING_TUN_SETTING_NAME,               setting_tun_details },
-	{ NM_SETTING_IP_TUNNEL_SETTING_NAME,         setting_ip_tunnel_details },
-	{ NM_SETTING_MACSEC_SETTING_NAME,            setting_macsec_details },
-	{ NM_SETTING_MACVLAN_SETTING_NAME,           setting_macvlan_details },
-	{ NM_SETTING_VXLAN_SETTING_NAME,             setting_vxlan_details },
-	{ NM_SETTING_PROXY_SETTING_NAME,             setting_proxy_details },
-	{ NULL },
-};
+/*****************************************************************************/
 
 gboolean
-setting_details (NMSetting *setting, NmCli *nmc,  const char *one_prop, gboolean secrets)
+setting_details (const NmcConfig *nmc_config, NMSetting *setting, const char *one_prop)
 {
-	const SettingDetails *iter = &detail_printers[0];
-	NmcPropertyGetType type = NMC_PROPERTY_GET_PRETTY;
+	const NMMetaSettingInfoEditor *setting_info;
+	gs_free_error GError *error = NULL;
+	gs_free char *fields_str = NULL;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
 
-	if (nmc->print_output == NMC_PRINT_TERSE)
-		type = NMC_PROPERTY_GET_PARSABLE;
+	setting_info = nm_meta_setting_info_editor_find_by_setting (setting);
+	if (!setting_info)
+		return FALSE;
 
-	while (iter->sname) {
-		if (nm_setting_lookup_type (iter->sname) == G_OBJECT_TYPE (setting))
-			return iter->func (setting, nmc, one_prop, secrets, type);
-		iter++;
+	if (one_prop) {
+		/* hack around setting-details being called for one setting. Must prefix the
+		 * property name with the setting name. Later we should remove setting_details()
+		 * and merge it into the caller. */
+		fields_str = g_strdup_printf ("%s.%s", nm_setting_get_name (setting), one_prop);
 	}
 
-	g_assert_not_reached ();
-	return FALSE;
-}
+	if (!nmc_print (nmc_config,
+	                (gpointer[]) { setting, NULL },
+	                NULL,
+	                (const NMMetaAbstractInfo *const[]) { (const NMMetaAbstractInfo *) setting_info, NULL },
+	                fields_str,
+	                &error))
+		return FALSE;
 
+	return TRUE;
+}
diff --git a/clients/cli/settings.h b/clients/cli/settings.h
index f663aa46..7dad622b 100644
--- a/clients/cli/settings.h
+++ b/clients/cli/settings.h
@@ -20,16 +20,13 @@
 #ifndef NMC_SETTINGS_H
 #define NMC_SETTINGS_H
 
-#include "nmcli.h"
-#include "utils.h"
+#include "nm-meta-setting.h"
+#include "nm-meta-setting-desc.h"
 
-/* --- Functions --- */
+#include "nmcli.h"
 
-void nmc_properties_init (void);
-void nmc_properties_cleanup (void);
+/*****************************************************************************/
 
-NMSetting *nmc_setting_new_for_name (const char *name);
-void nmc_setting_custom_init (NMSetting *setting);
 void nmc_setting_ip4_connect_handlers (NMSettingIPConfig *setting);
 void nmc_setting_ip6_connect_handlers (NMSettingIPConfig *setting);
 void nmc_setting_proxy_connect_handlers (NMSettingProxy *setting);
@@ -38,7 +35,7 @@ void nmc_setting_connection_connect_handlers (NMSettingConnection *setting, NMCo
 
 char      **nmc_setting_get_valid_properties (NMSetting *setting);
 char       *nmc_setting_get_property_desc (NMSetting *setting, const char *prop);
-const char **nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop);
+const char *const*nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop, char ***out_to_free);
 char       *nmc_setting_get_property (NMSetting *setting,
                                       const char *prop,
                                       GError **error);
@@ -62,39 +59,6 @@ void nmc_property_set_default_value (NMSetting *setting, const char *prop);
 gboolean nmc_property_get_gvalue (NMSetting *setting, const char *prop, GValue *value);
 gboolean nmc_property_set_gvalue (NMSetting *setting, const char *prop, GValue *value);
 
-gboolean setting_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gboolean secrets);
-
-extern NmcOutputField nmc_fields_setting_connection[];
-extern NmcOutputField nmc_fields_setting_wired[];
-extern NmcOutputField nmc_fields_setting_8021X[];
-extern NmcOutputField nmc_fields_setting_wireless[];
-extern NmcOutputField nmc_fields_setting_wireless_security[];
-extern NmcOutputField nmc_fields_setting_ip4_config[];
-extern NmcOutputField nmc_fields_setting_ip6_config[];
-extern NmcOutputField nmc_fields_setting_serial[];
-extern NmcOutputField nmc_fields_setting_ppp[];
-extern NmcOutputField nmc_fields_setting_pppoe[];
-extern NmcOutputField nmc_fields_setting_adsl[];
-extern NmcOutputField nmc_fields_setting_gsm[];
-extern NmcOutputField nmc_fields_setting_cdma[];
-extern NmcOutputField nmc_fields_setting_bluetooth[];
-extern NmcOutputField nmc_fields_setting_olpc_mesh[];
-extern NmcOutputField nmc_fields_setting_vpn[];
-extern NmcOutputField nmc_fields_setting_wimax[];
-extern NmcOutputField nmc_fields_setting_infiniband[];
-extern NmcOutputField nmc_fields_setting_bond[];
-extern NmcOutputField nmc_fields_setting_vlan[];
-extern NmcOutputField nmc_fields_setting_bridge[];
-extern NmcOutputField nmc_fields_setting_bridge_port[];
-extern NmcOutputField nmc_fields_setting_team[];
-extern NmcOutputField nmc_fields_setting_team_port[];
-extern NmcOutputField nmc_fields_setting_dcb[];
-extern NmcOutputField nmc_fields_setting_tun[];
-extern NmcOutputField nmc_fields_setting_ip_tunnel[];
-extern NmcOutputField nmc_fields_setting_macvlan[];
-extern NmcOutputField nmc_fields_setting_macsec[];
-extern NmcOutputField nmc_fields_setting_vxlan[];
-extern NmcOutputField nmc_fields_setting_proxy[];
-extern NmcOutputField nmc_fields_setting_dummy[];
+gboolean setting_details (const NmcConfig *nmc_config, NMSetting *setting, const char *one_prop);
 
 #endif /* NMC_SETTINGS_H */
diff --git a/clients/cli/utils.c b/clients/cli/utils.c
index 24686ec7..570bfb98 100644
--- a/clients/cli/utils.c
+++ b/clients/cli/utils.c
@@ -14,11 +14,14 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2010 - 2015 Red Hat, Inc.
+ * Copyright 2010 Lennart Poettering
+ * Copyright 2010 - 2017 Red Hat, Inc.
  */
 
 #include "nm-default.h"
 
+#include "utils.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -26,26 +29,140 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+
+#include "nm-client-utils.h"
+#include "nm-meta-setting-access.h"
 
-#include "utils.h"
 #include "common.h"
+#include "settings.h"
 
-gboolean
-matches (const char *cmd, const char *pattern)
+#define ML_HEADER_WIDTH 79
+#define ML_VALUE_INDENT 40
+
+/*****************************************************************************/
+
+static const char *
+_meta_type_nmc_generic_info_get_name (const NMMetaAbstractInfo *abstract_info, gboolean for_header)
 {
-	size_t len = strlen (cmd);
-	if (!len || len > strlen (pattern))
-		return FALSE;
-	return memcmp (pattern, cmd, len) == 0;
+	const NmcMetaGenericInfo *info = (const NmcMetaGenericInfo *) abstract_info;
+
+	if (for_header)
+		return info->name_header ?: info->name;
+	return info->name;
 }
 
+static const NMMetaAbstractInfo *const*
+_meta_type_nmc_generic_info_get_nested (const NMMetaAbstractInfo *abstract_info,
+                                        guint *out_len,
+                                        gpointer *out_to_free)
+{
+	const NmcMetaGenericInfo *info;
+
+	info = (const NmcMetaGenericInfo *) abstract_info;
+
+	*out_to_free = NULL;
+	NM_SET_OUT (out_len, NM_PTRARRAY_LEN (info->nested));
+	return (const NMMetaAbstractInfo *const*) info->nested;
+}
+
+static gconstpointer
+_meta_type_nmc_generic_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 NmcMetaGenericInfo *info = (const NmcMetaGenericInfo *) 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,
+	                NM_META_ACCESSOR_GET_TYPE_TERMFORMAT))
+		g_return_val_if_reached (NULL);
+
+	/* omitting the out_to_free value is only allowed for TERMFORMAT. */
+	nm_assert (out_to_free || NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_TERMFORMAT));
+
+	if (info->get_fcn) {
+		return info->get_fcn (environment, environment_user_data,
+		                      info, target,
+		                      get_type,
+		                      get_flags,
+		                      out_flags,
+		                      out_to_free);
+	}
+
+	if (info->nested) {
+		NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL);
+		return info->name;
+	}
+
+	g_return_val_if_reached (NULL);
+}
+
+const NMMetaType nmc_meta_type_generic_info = {
+	.type_name =         "nmc-generic-info",
+	.get_name =          _meta_type_nmc_generic_info_get_name,
+	.get_nested =        _meta_type_nmc_generic_info_get_nested,
+	.get_fcn =           _meta_type_nmc_generic_info_get_fcn,
+};
+
+/*****************************************************************************/
+
+static gboolean
+use_colors (NmcColorOption color_option)
+{
+	if (color_option == NMC_USE_COLOR_AUTO) {
+		static NmcColorOption cached = NMC_USE_COLOR_AUTO;
+
+		if (G_UNLIKELY (cached == NMC_USE_COLOR_AUTO)) {
+			if (   g_strcmp0 (g_getenv ("TERM"), "dumb") == 0
+				|| !isatty (STDOUT_FILENO))
+				cached = NMC_USE_COLOR_NO;
+			else
+				cached = NMC_USE_COLOR_YES;
+		}
+		return cached == NMC_USE_COLOR_YES;
+	}
+
+	return color_option == NMC_USE_COLOR_YES;
+}
+
+static const char *
+colorize_string (NmcColorOption color_option,
+                 NMMetaTermColor color,
+                 NMMetaTermFormat color_fmt,
+                 const char *str,
+                 char **out_to_free)
+{
+	const char *out = str;
+
+	if (   use_colors (color_option)
+	    && (color != NM_META_TERM_COLOR_NORMAL || color_fmt != NM_META_TERM_FORMAT_NORMAL)) {
+		*out_to_free = nmc_colorize (color_option, color, color_fmt, "%s", str);
+		out = *out_to_free;
+	}
+
+	return out;
+}
+
+/*****************************************************************************/
+
 static gboolean
 parse_global_arg (NmCli *nmc, const char *arg)
 {
 	if (nmc_arg_is_option (arg, "ask"))
 		nmc->ask = TRUE;
 	else if (nmc_arg_is_option (arg, "show-secrets"))
-		nmc->show_secrets = TRUE;
+		nmc->nmc_config_mutable.show_secrets = TRUE;
 	else
 		return FALSE;
 
@@ -279,31 +396,31 @@ nmc_terminal_show_progress (const char *str)
 }
 
 const char *
-nmc_term_color_sequence (NmcTermColor color)
+nmc_term_color_sequence (NMMetaTermColor color)
 {
 	switch (color) {
-        case NMC_TERM_COLOR_BLACK:
+        case NM_META_TERM_COLOR_BLACK:
 		return "\33[30m";
 		break;
-        case NMC_TERM_COLOR_RED:
+        case NM_META_TERM_COLOR_RED:
 		return "\33[31m";
 		break;
-        case NMC_TERM_COLOR_GREEN:
+        case NM_META_TERM_COLOR_GREEN:
 		return "\33[32m";
 		break;
-        case NMC_TERM_COLOR_YELLOW:
+        case NM_META_TERM_COLOR_YELLOW:
 		return "\33[33m";
 		break;
-        case NMC_TERM_COLOR_BLUE:
+        case NM_META_TERM_COLOR_BLUE:
 		return "\33[34m";
 		break;
-        case NMC_TERM_COLOR_MAGENTA:
+        case NM_META_TERM_COLOR_MAGENTA:
 		return "\33[35m";
 		break;
-        case NMC_TERM_COLOR_CYAN:
+        case NM_META_TERM_COLOR_CYAN:
 		return "\33[36m";
 		break;
-        case NMC_TERM_COLOR_WHITE:
+        case NM_META_TERM_COLOR_WHITE:
 		return "\33[37m";
 		break;
 	default:
@@ -313,7 +430,7 @@ nmc_term_color_sequence (NmcTermColor color)
 }
 
 /* Parses @str for color as string or number */
-NmcTermColor
+NMMetaTermColor
 nmc_term_color_parse_string (const char *str, GError **error)
 {
 	unsigned long color_int;
@@ -321,7 +438,7 @@ nmc_term_color_parse_string (const char *str, GError **error)
 	                                "blue", "magenta", "cyan", "white", NULL };
 
 	if (nmc_string_to_uint (str, TRUE, 0, 8, &color_int)) {
-		return (NmcTermColor) color_int;
+		return (NMMetaTermColor) color_int;
 	} else {
 		const char *color, **p;
 		int i;
@@ -329,32 +446,32 @@ nmc_term_color_parse_string (const char *str, GError **error)
 		color = nmc_string_is_valid (str, colors, error);
 		for (p = colors, i = 0; *p != NULL; p++, i++) {
 			if (*p == color)
-				return (NmcTermColor) i;
+				return (NMMetaTermColor) i;
 		}
 		return -1;
 	}
 }
 
 const char *
-nmc_term_format_sequence (NmcTermFormat format)
+nmc_term_format_sequence (NMMetaTermFormat format)
 {
 	switch (format) {
-        case NMC_TERM_FORMAT_BOLD:
+        case NM_META_TERM_FORMAT_BOLD:
 		return "\33[1m";
 		break;
-        case NMC_TERM_FORMAT_DIM:
+        case NM_META_TERM_FORMAT_DIM:
 		return "\33[2m";
 		break;
-        case NMC_TERM_FORMAT_UNDERLINE:
+        case NM_META_TERM_FORMAT_UNDERLINE:
 		return "\33[4m";
 		break;
-        case NMC_TERM_FORMAT_BLINK:
+        case NM_META_TERM_FORMAT_BLINK:
 		return "\33[5m";
 		break;
-        case NMC_TERM_FORMAT_REVERSE:
+        case NM_META_TERM_FORMAT_REVERSE:
 		return "\33[7m";
 		break;
-        case NMC_TERM_FORMAT_HIDDEN:
+        case NM_META_TERM_FORMAT_HIDDEN:
 		return "\33[8m";
 		break;
 	default:
@@ -363,25 +480,8 @@ nmc_term_format_sequence (NmcTermFormat format)
 	}
 }
 
-static gboolean
-use_colors (NmCli *nmc)
-{
-	if (nmc == NULL)
-		return FALSE;
-
-	if (nmc->use_colors == NMC_USE_COLOR_AUTO) {
-		if (   g_strcmp0 (g_getenv ("TERM"), "dumb") == 0
-		    || !isatty (fileno (stdout)))
-			nmc->use_colors = NMC_USE_COLOR_NO;
-		else
-			nmc->use_colors = NMC_USE_COLOR_YES;
-	}
-
-	return nmc->use_colors == NMC_USE_COLOR_YES;
-}
-
 char *
-nmc_colorize (NmCli *nmc, NmcTermColor color, NmcTermFormat format, const char *fmt, ...)
+nmc_colorize (NmcColorOption color_option, NMMetaTermColor color, NMMetaTermFormat format, const char *fmt, ...)
 {
 	va_list args;
 	char *str, *colored;
@@ -392,7 +492,7 @@ nmc_colorize (NmCli *nmc, NmcTermColor color, NmcTermFormat format, const char *
 	str = g_strdup_vprintf (fmt, args);
 	va_end (args);
 
-	if (!use_colors (nmc))
+	if (!use_colors (color_option))
 		return str;
 
 	ansi_color = nmc_term_color_sequence (color);
@@ -471,137 +571,6 @@ nmc_filter_out_colors (const char *str)
 }
 
 /*
- * Convert string to signed integer.
- * If required, the resulting number is checked to be in the <min,max> range.
- */
-gboolean
-nmc_string_to_int_base (const char *str,
-                        int base,
-                        gboolean range_check,
-                        long int min,
-                        long int max,
-                        long int *value)
-{
-	char *end;
-	long int tmp;
-
-	errno = 0;
-	tmp = strtol (str, &end, base);
-	if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) {
-		return FALSE;
-	}
-	*value = tmp;
-	return TRUE;
-}
-
-/*
- * Convert string to unsigned integer.
- * If required, the resulting number is checked to be in the <min,max> range.
- */
-gboolean
-nmc_string_to_uint_base (const char *str,
-                         int base,
-                         gboolean range_check,
-                         unsigned long int min,
-                         unsigned long int max,
-                         unsigned long int *value)
-{
-	char *end;
-	unsigned long int tmp;
-
-	errno = 0;
-	tmp = strtoul (str, &end, base);
-	if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) {
-		return FALSE;
-	}
-	*value = tmp;
-	return TRUE;
-}
-
-gboolean
-nmc_string_to_int (const char *str,
-                   gboolean range_check,
-                   long int min,
-                   long int max,
-                   long int *value)
-{
-	return nmc_string_to_int_base (str, 10, range_check, min, max, value);
-}
-
-gboolean
-nmc_string_to_uint (const char *str,
-                    gboolean range_check,
-                    unsigned long int min,
-                    unsigned long int max,
-                    unsigned long int *value)
-{
-	return nmc_string_to_uint_base (str, 10, range_check, min, max, value);
-}
-
-gboolean
-nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error)
-{
-	const char *s_true[] = { "true", "yes", "on", NULL };
-	const char *s_false[] = { "false", "no", "off", NULL };
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (g_strcmp0 (str, "o") == 0) {
-		g_set_error (error, 1, 0,
-		             /* Translators: the first %s is the partial value entered by
-		              * the user, the second %s a list of compatible values.
-		              */
-		             _("'%s' is ambiguous (%s)"), str, "on x off");
-		return FALSE;
-	}
-
-	if (nmc_string_is_valid (str, s_true, NULL))
-		*val_bool = TRUE;
-	else if (nmc_string_is_valid (str, s_false, NULL))
-		*val_bool = FALSE;
-	else {
-		g_set_error (error, 1, 0,
-		             _("'%s' is not valid; use [%s] or [%s]"),
-		             str, "true, yes, on", "false, no, off");
-		return FALSE;
-	}
-	return TRUE;
-}
-
-gboolean
-nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error)
-{
-	const char *s_true[] = { "true", "yes", "on", NULL };
-	const char *s_false[] = { "false", "no", "off", NULL };
-	const char *s_unknown[] = { "unknown", NULL };
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (g_strcmp0 (str, "o") == 0) {
-		g_set_error (error, 1, 0,
-		             /* Translators: the first %s is the partial value entered by
-		              * the user, the second %s a list of compatible values.
-		              */
-		             _("'%s' is ambiguous (%s)"), str, "on x off");
-		return FALSE;
-	}
-
-	if (nmc_string_is_valid (str, s_true, NULL))
-		*val = NMC_TRI_STATE_YES;
-	else if (nmc_string_is_valid (str, s_false, NULL))
-		*val = NMC_TRI_STATE_NO;
-	else if (nmc_string_is_valid (str, s_unknown, NULL))
-		*val = NMC_TRI_STATE_UNKNOWN;
-	else {
-		g_set_error (error, 1, 0,
-		             _("'%s' is not valid; use [%s], [%s] or [%s]"),
-		             str, "true, yes, on", "false, no, off", "unknown");
-		return FALSE;
-	}
-	return TRUE;
-}
-
-/*
  * Ask user for input and return the string.
  * The caller is responsible for freeing the returned string.
  */
@@ -664,64 +633,13 @@ nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote,
 }
 
 /*
- * Check whether 'input' is contained in 'allowed' array. It performs case
- * insensitive comparison and supports shortcut strings if they are unique.
- * Returns: a pointer to found string in allowed array on success or NULL.
- * On failure: error->code : 0 - string not found; 1 - string is ambiguous
- */
-const char *
-nmc_string_is_valid (const char *input, const char **allowed, GError **error)
-{
-	const char **p;
-	size_t input_ln, p_len;
-	gboolean prev_match = FALSE;
-	const char *ret = NULL;
-
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	if (!input || !*input)
-		goto finish;
-
-	input_ln = strlen (input);
-	for (p = allowed; p && *p; p++) {
-		p_len = strlen (*p);
-		if (g_ascii_strncasecmp (input, *p, input_ln) == 0) {
-			if (input_ln == p_len) {
-				ret = *p;
-				break;
-			}
-			if (!prev_match)
-				ret = *p;
-			else {
-				g_set_error (error, 1, 1, _("'%s' is ambiguous (%s x %s)"),
-				             input, ret, *p);
-				return NULL;
-			}
-			prev_match = TRUE;
-		}
-	}
-
-finish:
-	if (ret == NULL) {
-		char *valid_vals = g_strjoinv (", ", (char **) allowed);
-		if (!input || !*input)
-			g_set_error (error, 1, 0, _("missing name, try one of [%s]"), valid_vals);
-		else
-			g_set_error (error, 1, 0, _("'%s' not among [%s]"), input, valid_vals);
-
-		g_free (valid_vals);
-	}
-	return ret;
-}
-
-/*
  * Convert string array (char **) to description string in the form of:
  * "[string1, string2, ]"
  *
  * Returns: a newly allocated string. Caller must free it with g_free().
  */
 char *
-nmc_util_strv_for_display (const char **strv, gboolean brackets)
+nmc_util_strv_for_display (const char *const*strv, gboolean brackets)
 {
 	GString *result;
 	guint i = 0;
@@ -742,31 +660,6 @@ nmc_util_strv_for_display (const char **strv, gboolean brackets)
 }
 
 /*
- * Wrapper function for g_strsplit_set() that removes empty strings
- * from the vector as they are not useful in most cases.
- */
-char **
-nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens)
-{
-	char **result;
-	uint i;
-	uint j;
-
-	result = g_strsplit_set (str, delimiter, max_tokens);
-
-	/* remove empty strings */
-	for (i = 0; result && result[i]; i++) {
-		if (*(result[i]) == '\0') {
-			g_free (result[i]);
-			for (j = i; result[j]; j++)
-				result[j] = result[j + 1];
-			i--;
-		}
-	}
-	return result;
-}
-
-/*
  * Find out how many columns an UTF-8 string occupies on the screen.
  */
 int
@@ -820,21 +713,21 @@ set_val_arrc (NmcOutputField fields_array[], guint32 idx, const char **value)
 }
 
 void
-set_val_color_all (NmcOutputField fields_array[], NmcTermColor color)
+set_val_color_all (NmcOutputField fields_array[], NMMetaTermColor color)
 {
 	int i;
 
-	for (i = 0; fields_array[i].name; i++) {
+	for (i = 0; fields_array[i].info; i++) {
 		fields_array[i].color = color;
 	}
 }
 
 void
-set_val_color_fmt_all (NmcOutputField fields_array[], NmcTermFormat format)
+set_val_color_fmt_all (NmcOutputField fields_array[], NMMetaTermFormat format)
 {
 	int i;
 
-	for (i = 0; fields_array[i].name; i++) {
+	for (i = 0; fields_array[i].info; i++) {
 		fields_array[i].color_fmt = format;
 	}
 }
@@ -847,7 +740,7 @@ nmc_free_output_field_values (NmcOutputField fields_array[])
 {
 	NmcOutputField *iter = fields_array;
 
-	while (iter && iter->name) {
+	while (iter && iter->info) {
 		if (iter->free_value) {
 			if (iter->value_is_array)
 				g_strfreev ((char **) iter->value);
@@ -859,6 +752,157 @@ nmc_free_output_field_values (NmcOutputField fields_array[])
 	}
 }
 
+/*****************************************************************************/
+
+#define PRINT_DATA_COL_PARENT_NIL (G_MAXUINT)
+
+typedef struct {
+	const NMMetaSelectionItem *selection_item;
+	guint parent_idx;
+	guint self_idx;
+	bool is_leaf;
+} PrintDataCol;
+
+static gboolean
+_output_selection_append (GArray *cols,
+                          const char *fields_prefix,
+                          guint parent_idx,
+                          const NMMetaSelectionItem *selection_item,
+                          GPtrArray *gfree_keeper,
+                          GError **error)
+{
+	gs_free gpointer nested_to_free = NULL;
+	guint col_idx;
+	guint i;
+	const NMMetaAbstractInfo *const*nested;
+	NMMetaSelectionResultList *selection;
+	const NMMetaSelectionItem *si;
+
+	col_idx = cols->len;
+
+	{
+		PrintDataCol col = {
+			.selection_item = selection_item,
+			.parent_idx = parent_idx,
+			.self_idx = col_idx,
+			.is_leaf = TRUE,
+		};
+		g_array_append_val (cols, col);
+	}
+
+	nested = nm_meta_abstract_info_get_nested (selection_item->info, NULL, &nested_to_free);
+
+	if (selection_item->sub_selection) {
+		if (!nested) {
+			gs_free char *allowed_fields = NULL;
+
+			if (parent_idx != PRINT_DATA_COL_PARENT_NIL) {
+				si = g_array_index (cols, PrintDataCol, parent_idx).selection_item;
+				allowed_fields = nm_meta_abstract_info_get_nested_names_str (si->info, si->self_selection);
+			}
+			if (!allowed_fields) {
+				g_set_error (error, NMCLI_ERROR, 1, _("invalid field '%s%s%s'; no such field"),
+				             selection_item->self_selection ?: "", selection_item->self_selection ? "." : "",
+				             selection_item->sub_selection);
+			} else {
+				g_set_error (error, NMCLI_ERROR, 1, _("invalid field '%s%s%s'; allowed fields: [%s]"),
+				             selection_item->self_selection ?: "", selection_item->self_selection ? "." : "",
+				             selection_item->sub_selection,
+				             allowed_fields);
+			}
+			return FALSE;
+		}
+
+		selection = nm_meta_selection_create_parse_one (nested, selection_item->self_selection,
+		                                                selection_item->sub_selection, FALSE, error);
+		if (!selection)
+			return FALSE;
+		nm_assert (selection->num == 1);
+	} else if (nested) {
+		selection = nm_meta_selection_create_all (nested);
+		nm_assert (selection && selection->num > 0);
+	} else
+		selection = NULL;
+
+	if (selection) {
+		g_ptr_array_add (gfree_keeper, selection);
+
+		for (i = 0; i < selection->num; i++) {
+			si = &selection->items[i];
+			if (!_output_selection_append (cols, si->self_selection, col_idx,
+			                               si, gfree_keeper, error))
+				return FALSE;
+		}
+
+		if (!NM_IN_SET(selection_item->info->meta_type,
+		               &nm_meta_type_setting_info_editor,
+		               &nmc_meta_type_generic_info))
+			g_array_index (cols, PrintDataCol, col_idx).is_leaf = FALSE;
+	}
+
+	return TRUE;
+}
+
+/*****************************************************************************/
+
+/**
+ * _output_selection_parse:
+ * @fields: a %NULL terminated array of meta-data fields
+ * @fields_str: a comma separated selector for fields. Nested fields
+ *   can be specified using '.' notation.
+ * @out_cols: (transfer full): the result, parsed as an GArray of PrintDataCol items.
+ *   The order of the items is as specified by @fields_str. Meta data
+ *   items that contain nested elements are unpacked (note the is_leaf
+ *   and parent properties of PrintDataCol).
+ * @out_gfree_keeper: (transfer full): an output GPtrArray that owns
+ *   strings to which @out_cols points to. The lifetime of @out_cols
+ *   and @out_gfree_keeper should correspond.
+ * @error:
+ *
+ * Returns: %TRUE on success.
+ */
+static gboolean
+_output_selection_parse (const NMMetaAbstractInfo *const*fields,
+                         const char *fields_str,
+                         GArray **out_cols,
+                         GPtrArray **out_gfree_keeper,
+                         GError **error)
+{
+	NMMetaSelectionResultList *selection;
+	gs_unref_ptrarray GPtrArray *gfree_keeper = NULL;
+	gs_unref_array GArray *cols = NULL;
+	guint i;
+
+	selection = nm_meta_selection_create_parse_list (fields, NULL, fields_str, FALSE, error);
+	if (!selection)
+		return FALSE;
+
+	if (!selection->num) {
+		g_set_error (error, NMCLI_ERROR, 1, _("failure to select field"));
+		g_free (selection);
+		return FALSE;
+	}
+
+	gfree_keeper = g_ptr_array_new_with_free_func (g_free);
+	g_ptr_array_add (gfree_keeper, selection);
+
+	cols = g_array_new (FALSE, TRUE, sizeof (PrintDataCol));
+
+	for (i = 0; i < selection->num; i++) {
+		const NMMetaSelectionItem *si = &selection->items[i];
+
+		if (!_output_selection_append (cols, NULL, PRINT_DATA_COL_PARENT_NIL,
+		                               si, gfree_keeper, error))
+			return FALSE;
+	}
+
+	*out_cols = g_steal_pointer (&cols);
+	*out_gfree_keeper = g_steal_pointer (&gfree_keeper);
+	return TRUE;
+}
+
+/*****************************************************************************/
+
 /**
  * parse_output_fields:
  * @field_str: comma-separated field names to parse
@@ -881,212 +925,673 @@ nmc_free_output_field_values (NmcOutputField fields_array[])
  */
 GArray *
 parse_output_fields (const char *fields_str,
-                     const NmcOutputField fields_array[],
+                     const NMMetaAbstractInfo *const*fields_array,
                      gboolean parse_groups,
-                     GPtrArray **group_fields,
+                     GPtrArray **out_group_fields,
                      GError **error)
 {
-	char **fields, **iter;
+	gs_free NMMetaSelectionResultList *selection = NULL;
 	GArray *array;
-	int i, j;
+	GPtrArray *group_fields = NULL;
+	guint i;
 
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-	g_return_val_if_fail (group_fields == NULL || *group_fields == NULL, NULL);
-
-	array = g_array_new (FALSE, FALSE, sizeof (int));
-	if (parse_groups && group_fields)
-		*group_fields = g_ptr_array_new_full (20, (GDestroyNotify) g_free);
-
-	/* Split supplied fields string */
-	fields = g_strsplit_set (fields_str, ",", -1);
-	for (iter = fields; iter && *iter; iter++) {
-		int idx = -1;
-
-		g_strstrip (*iter);
-		if (parse_groups) {
-			/* e.g. "general.device,general.driver,ip4,ip6" */
-			gboolean found = FALSE;
-			char *left = *iter;
-			char *right = strchr (*iter, '.');
-
-			if (right)
-				*right++ = '\0';
-
-			for (i = 0; fields_array[i].name; i++) {
-				if (strcasecmp (left, fields_array[i].name) == 0) {
-					NmcOutputField *valid_names = fields_array[i].group;
-					idx = i;
-					if (!right && !valid_names) {
-						found = TRUE;
-						break;
-					}
-					for (j = 0; valid_names && valid_names[j].name; j++) {
-						if (!right || strcasecmp (right, valid_names[j].name) == 0) {
-							found = TRUE;
-							break;
-						}
+	g_return_val_if_fail (!error || !*error, NULL);
+	g_return_val_if_fail (!out_group_fields || !*out_group_fields, NULL);
+
+	selection = nm_meta_selection_create_parse_list (fields_array, NULL, fields_str, TRUE, error);
+	if (!selection)
+		return NULL;
+
+	array = g_array_sized_new (FALSE, FALSE, sizeof (int), selection->num);
+	if (parse_groups && out_group_fields)
+		group_fields = g_ptr_array_new_full (selection->num, g_free);
+
+	for (i = 0; i < selection->num; i++) {
+		int idx = selection->items[i].idx;
+
+		g_array_append_val (array, idx);
+		if (group_fields)
+			g_ptr_array_add (group_fields, g_strdup (selection->items[i].sub_selection));
+	}
+
+	if (group_fields)
+		*out_group_fields = group_fields;
+	return array;
+}
+
+NmcOutputField *
+nmc_dup_fields_array (const NMMetaAbstractInfo *const*fields, NmcOfFlags flags)
+{
+	NmcOutputField *row;
+	gsize l;
+
+	for (l = 0; fields[l]; l++) {
+	}
+
+	row = g_new0 (NmcOutputField, l + 1);
+	for (l = 0; fields[l]; l++)
+		row[l].info = fields[l];
+	row[0].flags = flags;
+	return row;
+}
+
+void
+nmc_empty_output_fields (NmcOutputData *output_data)
+{
+	guint i;
+
+	/* Free values in field structure */
+	for (i = 0; i < output_data->output_data->len; i++) {
+		NmcOutputField *fld_arr = g_ptr_array_index (output_data->output_data, i);
+		nmc_free_output_field_values (fld_arr);
+	}
+
+	/* Empty output_data array */
+	if (output_data->output_data->len > 0)
+		g_ptr_array_remove_range (output_data->output_data, 0, output_data->output_data->len);
+}
+
+/*****************************************************************************/
+
+typedef struct {
+	guint col_idx;
+	const PrintDataCol *col;
+	const char *title;
+	bool title_to_free:1;
+	int width;
+} PrintDataHeaderCell;
+
+typedef enum {
+	PRINT_DATA_CELL_FORMAT_TYPE_PLAIN = 0,
+	PRINT_DATA_CELL_FORMAT_TYPE_STRV,
+} PrintDataCellFormatType;
+
+typedef struct {
+	guint row_idx;
+	const PrintDataHeaderCell *header_cell;
+	NMMetaTermColor term_color;
+	NMMetaTermFormat term_format;
+	union {
+		const char *plain;
+		const char *const*strv;
+	} text;
+	PrintDataCellFormatType text_format:3;
+	bool text_to_free:1;
+} PrintDataCell;
+
+static void
+_print_data_header_cell_clear (gpointer cell_p)
+{
+	PrintDataHeaderCell *cell = cell_p;
+
+	if (cell->title_to_free) {
+		g_free ((char *) cell->title);
+		cell->title_to_free = FALSE;
+	}
+	cell->title = NULL;
+}
+
+static void
+_print_data_cell_clear_text (PrintDataCell *cell)
+{
+	if (cell->text_to_free) {
+		switch (cell->text_format) {
+		case PRINT_DATA_CELL_FORMAT_TYPE_PLAIN:
+			g_free ((char *) cell->text.plain);
+			break;
+		case PRINT_DATA_CELL_FORMAT_TYPE_STRV:
+			g_strfreev ((char **) cell->text.strv);
+			break;
+		};
+		cell->text_to_free = FALSE;
+	}
+	memset (&cell->text, 0, sizeof (cell->text));
+}
+
+static void
+_print_data_cell_clear (gpointer cell_p)
+{
+	PrintDataCell *cell = cell_p;
+
+	_print_data_cell_clear_text (cell);
+}
+
+static void
+_print_fill (const NmcConfig *nmc_config,
+             gpointer const *targets,
+             const PrintDataCol *cols,
+             guint cols_len,
+             GArray **out_header_row,
+             GArray **out_cells)
+{
+	GArray *cells;
+	GArray *header_row;
+	guint i_row, i_col;
+	guint targets_len;
+	gboolean pretty;
+	NMMetaAccessorGetType text_get_type;
+	NMMetaAccessorGetFlags text_get_flags;
+
+	pretty = (nmc_config->print_output != NMC_PRINT_TERSE);
+
+	header_row = g_array_sized_new (FALSE, TRUE, sizeof (PrintDataHeaderCell), cols_len);
+	g_array_set_clear_func (header_row, _print_data_header_cell_clear);
+
+	for (i_col = 0; i_col < cols_len; i_col++) {
+		const PrintDataCol *col;
+		PrintDataHeaderCell *header_cell;
+		guint col_idx;
+		const NMMetaAbstractInfo *info;
+
+		col = &cols[i_col];
+		if (!col->is_leaf)
+			continue;
+
+		info = col->selection_item->info;
+
+		col_idx = header_row->len;
+		g_array_set_size (header_row, col_idx + 1);
+
+		header_cell = &g_array_index (header_row, PrintDataHeaderCell, col_idx);
+
+		header_cell->col_idx = col_idx;
+		header_cell->col = col;
+
+		header_cell->title = nm_meta_abstract_info_get_name (info, TRUE);
+		if (   nmc_config->multiline_output
+		    && col->parent_idx != PRINT_DATA_COL_PARENT_NIL
+		    && NM_IN_SET (info->meta_type,
+		                  &nm_meta_type_property_info,
+		                  &nmc_meta_type_generic_info)) {
+			header_cell->title = g_strdup_printf ("%s.%s",
+			                                      nm_meta_abstract_info_get_name (cols[col->parent_idx].selection_item->info, FALSE),
+			                                      header_cell->title);
+			header_cell->title_to_free = TRUE;
+		}
+	}
+
+	targets_len = NM_PTRARRAY_LEN (targets);
+
+	cells = g_array_sized_new (FALSE, TRUE, sizeof (PrintDataCell), targets_len * header_row->len);
+	g_array_set_clear_func (cells, _print_data_cell_clear);
+	g_array_set_size (cells, targets_len * header_row->len);
+
+	text_get_type = pretty
+	                ? NM_META_ACCESSOR_GET_TYPE_PRETTY
+	                : NM_META_ACCESSOR_GET_TYPE_PARSABLE;
+	text_get_flags = NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV;
+	if (nmc_config->show_secrets)
+		text_get_flags |= NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS;
+
+	for (i_row = 0; i_row < targets_len; i_row++) {
+		gpointer target = targets[i_row];
+		PrintDataCell *cells_line = &g_array_index (cells, PrintDataCell, i_row * header_row->len);
+
+		for (i_col = 0; i_col < header_row->len; i_col++) {
+			char *to_free = NULL;
+			PrintDataCell *cell = &cells_line[i_col];
+			const PrintDataHeaderCell *header_cell;
+			const NMMetaAbstractInfo *info;
+			NMMetaAccessorGetOutFlags text_out_flags, color_out_flags;
+			gconstpointer value;
+
+			header_cell = &g_array_index (header_row, PrintDataHeaderCell, i_col);
+			info = header_cell->col->selection_item->info;
+
+			cell->row_idx = i_row;
+			cell->header_cell = header_cell;
+
+			value = nm_meta_abstract_info_get (info,
+			                                   nmc_meta_environment,
+			                                   nmc_meta_environment_arg,
+			                                   target,
+			                                   text_get_type,
+			                                   text_get_flags,
+			                                   &text_out_flags,
+			                                   (gpointer *) &to_free);
+			if (NM_FLAGS_HAS (text_out_flags, NM_META_ACCESSOR_GET_OUT_FLAGS_STRV)) {
+				if (value) {
+					if (nmc_config->multiline_output) {
+						cell->text_format = PRINT_DATA_CELL_FORMAT_TYPE_STRV;
+						cell->text.strv = value;
+						cell->text_to_free = !!to_free;
+					} else {
+						cell->text.plain = g_strjoinv (" | ", (char **) value);
+						cell->text_to_free = TRUE;
+						if (to_free)
+							g_strfreev ((char **) to_free);
 					}
-					if (found)
-						break;
 				}
+			} else {
+				cell->text.plain = value;
+				cell->text_to_free = !!to_free;
 			}
-			if (found) {
-				/* Add index to array, and field name (or NULL) to group_fields array */
-				g_array_append_val (array, idx);
-				if (group_fields && *group_fields)
-					g_ptr_array_add (*group_fields, g_strdup (right));
+
+			nm_meta_termformat_unpack (nm_meta_abstract_info_get (info,
+			                                                      nmc_meta_environment,
+			                                                      nmc_meta_environment_arg,
+			                                                      target,
+			                                                      NM_META_ACCESSOR_GET_TYPE_TERMFORMAT,
+			                                                      NM_META_ACCESSOR_GET_FLAGS_NONE,
+			                                                      &color_out_flags,
+			                                                      NULL),
+			                           &cell->term_color,
+			                           &cell->term_format);
+
+			if (cell->text_format == PRINT_DATA_CELL_FORMAT_TYPE_PLAIN) {
+				if (pretty && (!cell->text.plain|| !cell->text.plain[0])) {
+					_print_data_cell_clear_text (cell);
+					cell->text.plain = "--";
+				} else if (!cell->text.plain)
+					cell->text.plain = "";
 			}
-			if (right)
-				*(right-1) = '.';  /* Restore the original string */
-		} else {
-			/* e.g. "general,ip4,ip6" */
-			for (i = 0; fields_array[i].name; i++) {
-				if (strcasecmp (*iter, fields_array[i].name) == 0) {
-					g_array_append_val (array, i);
-					break;
+		}
+	}
+
+	for (i_col = 0; i_col < header_row->len; i_col++) {
+		PrintDataHeaderCell *header_cell = &g_array_index (header_row, PrintDataHeaderCell, i_col);
+
+		header_cell->width = nmc_string_screen_width (header_cell->title, NULL);
+
+		for (i_row = 0; i_row < targets_len; i_row++) {
+			const PrintDataCell *cell = &g_array_index (cells, PrintDataCell, i_row * cols_len + i_col);
+			const char *const*i_strv;
+
+			switch (cell->text_format) {
+			case PRINT_DATA_CELL_FORMAT_TYPE_PLAIN:
+				header_cell->width = NM_MAX (header_cell->width,
+				                             nmc_string_screen_width (cell->text.plain, NULL));
+				break;
+			case PRINT_DATA_CELL_FORMAT_TYPE_STRV:
+				i_strv = cell->text.strv;
+				if (i_strv) {
+					for (; *i_strv; i_strv++) {
+						header_cell->width = NM_MAX (header_cell->width,
+						                             nmc_string_screen_width (*i_strv, NULL));
+					}
 				}
+				break;
 			}
 		}
 
-		/* Field was not found - error case */
-		if (fields_array[i].name == NULL) {
-			/* Set GError */
-			if (!strcasecmp (*iter, "all") || !strcasecmp (*iter, "common"))
-				g_set_error (error, NMCLI_ERROR, 0, _("field '%s' has to be alone"), *iter);
-			else {
-				char *allowed_fields = nmc_get_allowed_fields (fields_array, idx);
-				g_set_error (error, NMCLI_ERROR, 1, _("invalid field '%s'; allowed fields: %s"),
-				             *iter, allowed_fields);
-				g_free (allowed_fields);
+		header_cell->width += 1;
+	}
+
+	*out_header_row = header_row;
+	*out_cells = cells;
+}
+
+static gboolean
+_print_skip_column (const NmcConfig *nmc_config,
+                    const PrintDataHeaderCell *header_cell)
+{
+	const NMMetaSelectionItem *selection_item;
+	const NMMetaAbstractInfo *info;
+
+	selection_item = header_cell->col->selection_item;
+	info = selection_item->info;
+
+	if (nmc_config->multiline_output) {
+		if (info->meta_type == &nm_meta_type_setting_info_editor) {
+			/* we skip the "name" entry for the setting in multiline output. */
+			return TRUE;
+		}
+		if (   info->meta_type == &nmc_meta_type_generic_info
+		    && ((const NmcMetaGenericInfo *) info)->nested) {
+			/* skip the "name" entry for parent generic-infos */
+			return TRUE;
+		}
+	} else {
+		if (   NM_IN_SET (info->meta_type,
+		                  &nm_meta_type_setting_info_editor,
+		                  &nmc_meta_type_generic_info)
+		    && selection_item->sub_selection) {
+			/* in tabular form, we skip the "name" entry for sections that have sub-selections.
+			 * That is, for "ipv4.may-fail", but not for "ipv4". */
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+static void
+_print_do (const NmcConfig *nmc_config,
+           const char *header_name_no_l10n,
+           guint col_len,
+           guint row_len,
+           const PrintDataHeaderCell *header_row,
+           const PrintDataCell *cells)
+{
+	int width1, width2;
+	int table_width = 0;
+	gboolean pretty = (nmc_config->print_output == NMC_PRINT_PRETTY);
+	gboolean terse = (nmc_config->print_output == NMC_PRINT_TERSE);
+	gboolean multiline = nmc_config->multiline_output;
+	guint i_row, i_col;
+	nm_auto_free_gstring GString *str = NULL;
+
+	g_assert (col_len && row_len);
+
+	/* Main header */
+	if (pretty && header_name_no_l10n) {
+		gs_free char *line = NULL;
+		int header_width;
+		const char *header_name = _(header_name_no_l10n);
+
+		header_width = nmc_string_screen_width (header_name, NULL) + 4;
+
+		if (multiline) {
+			table_width = NM_MAX (header_width, ML_HEADER_WIDTH);
+			line = g_strnfill (ML_HEADER_WIDTH, '=');
+		} else { /* tabular */
+			table_width = NM_MAX (table_width, header_width);
+			line = g_strnfill (table_width, '=');
+		}
+
+		width1 = strlen (header_name);
+		width2 = nmc_string_screen_width (header_name, NULL);
+		g_print ("%s\n", line);
+		g_print ("%*s\n", (table_width + width2)/2 + width1 - width2, header_name);
+		g_print ("%s\n", line);
+	}
+
+	str = !multiline
+	      ? g_string_sized_new (100)
+	      : NULL;
+
+	/* print the header for the tabular form */
+	if (!multiline && !terse) {
+		for (i_col = 0; i_col < col_len; i_col++) {
+			const PrintDataHeaderCell *header_cell = &header_row[i_col];
+			const char *title;
+
+			if (_print_skip_column (nmc_config, header_cell))
+				continue;
+
+			title = header_cell->title;
+
+			width1 = strlen (title);
+			width2 = nmc_string_screen_width (title, NULL);  /* Width of the string (in screen colums) */
+			g_string_append_printf (str, "%-*s", (int) (header_cell->width + width1 - width2), title);
+			g_string_append_c (str, ' ');  /* Column separator */
+			table_width += header_cell->width + width1 - width2 + 1;
+		}
+
+		if (str->len)
+			g_string_truncate (str, str->len-1);  /* Chop off last column separator */
+		g_print ("%s\n", str->str);
+		g_string_truncate (str, 0);
+
+		/* Print horizontal separator */
+		if (pretty) {
+			gs_free char *line = NULL;
+
+			g_print ("%s\n", (line = g_strnfill (table_width, '-')));
+		}
+	}
+
+	for (i_row = 0; i_row < row_len; i_row++) {
+		const PrintDataCell *current_line = &cells[i_row * col_len];
+
+		for (i_col = 0; i_col < col_len; i_col++) {
+			const PrintDataCell *cell = &current_line[i_col];
+			const char *const*lines = NULL;
+			guint i_lines, lines_len;
+
+			if (_print_skip_column (nmc_config, cell->header_cell))
+				continue;
+
+			lines_len = 0;
+			switch (cell->text_format) {
+			case PRINT_DATA_CELL_FORMAT_TYPE_PLAIN:
+				lines = &cell->text.plain;
+				lines_len = 1;
+				break;
+			case PRINT_DATA_CELL_FORMAT_TYPE_STRV:
+				nm_assert (multiline);
+				lines = cell->text.strv;
+				lines_len = NM_PTRARRAY_LEN (lines);
+				break;
 			}
 
-			/* Free arrays on error */
-			g_array_free (array, TRUE);
-			array = NULL;
-			if (group_fields && *group_fields) {
-				g_ptr_array_free (*group_fields, TRUE);
-				*group_fields = NULL;
+			for (i_lines = 0; i_lines < lines_len; i_lines++) {
+				gs_free char *text_to_free = NULL;
+				const char *text;
+
+				text = colorize_string (nmc_config->use_colors,
+				                        cell->term_color, cell->term_format,
+				                        lines[i_lines], &text_to_free);
+				if (multiline) {
+					gs_free char *prefix = NULL;
+
+					if (cell->text_format == PRINT_DATA_CELL_FORMAT_TYPE_STRV)
+						prefix = g_strdup_printf ("%s[%u]:", cell->header_cell->title, i_lines + 1);
+					else
+						prefix = g_strdup_printf ("%s:", cell->header_cell->title);
+					width1 = strlen (prefix);
+					width2 = nmc_string_screen_width (prefix, NULL);
+					g_print ("%-*s%s\n", (int) (terse ? 0 : ML_VALUE_INDENT+width1-width2), prefix, text);
+				} else {
+					nm_assert (str);
+					if (terse) {
+						if (nmc_config->escape_values) {
+							const char *p = text;
+							while (*p) {
+								if (*p == ':' || *p == '\\')
+									g_string_append_c (str, '\\');  /* Escaping by '\' */
+								g_string_append_c (str, *p);
+								p++;
+							}
+						}
+						else
+							g_string_append_printf (str, "%s", text);
+						g_string_append_c (str, ':');  /* Column separator */
+					} else {
+						const PrintDataHeaderCell *header_cell = &header_row[i_col];
+
+						width1 = strlen (text);
+						width2 = nmc_string_screen_width (text, NULL);  /* Width of the string (in screen colums) */
+						g_string_append_printf (str, "%-*s", (int) (header_cell->width + width1 - width2), text);
+						g_string_append_c (str, ' ');  /* Column separator */
+						table_width += header_cell->width + width1 - width2 + 1;
+					}
+				}
 			}
-			goto done;
+		}
+
+		if (!multiline) {
+			if (str->len)
+				g_string_truncate (str, str->len-1);  /* Chop off last column separator */
+			g_print ("%s\n", str->str);
+
+			g_string_truncate (str, 0);
+		}
+
+		if (   pretty
+		    && (   i_row < row_len - 1
+		        || multiline)) {
+			gs_free char *line = NULL;
+
+			g_print ("%s\n", (line = g_strnfill (ML_HEADER_WIDTH, '-')));
 		}
 	}
-done:
-	if (fields)
-		g_strfreev (fields);
-	return array;
 }
 
-/**
-* nmc_get_allowed_fields:
-* @fields_array: array of fields
-* @group_idx: index to the array (for second-level array in 'group' member),
-*   or -1
-*
-* Returns: string of allowed fields names.
-*   Caller is responsible for freeing the array.
-*/
-char *
-nmc_get_allowed_fields (const NmcOutputField fields_array[], int group_idx)
+gboolean
+nmc_print (const NmcConfig *nmc_config,
+           gpointer const *targets,
+           const char *header_name_no_l10n,
+           const NMMetaAbstractInfo *const*fields,
+           const char *fields_str,
+           GError **error)
 {
-	GString *allowed_fields = g_string_sized_new (256);
-	int i;
+	gs_unref_ptrarray GPtrArray *gfree_keeper = NULL;
+	gs_unref_array GArray *cols = NULL;
+	gs_unref_array GArray *header_row = NULL;
+	gs_unref_array GArray *cells = NULL;
+
+	if (!_output_selection_parse (fields, fields_str,
+	                              &cols, &gfree_keeper,
+	                              error))
+		return FALSE;
 
-	if (group_idx != -1 && fields_array[group_idx].group) {
-		NmcOutputField *second_level = fields_array[group_idx].group;
-		for (i = 0; second_level[i].name; i++)
-			g_string_append_printf (allowed_fields, "%s.%s,",
-			                        fields_array[group_idx].name, second_level[i].name);
-	} else {
-		for (i = 0; fields_array[i].name; i++)
-			g_string_append_printf (allowed_fields, "%s,", fields_array[i].name);
-	}
-	g_string_truncate (allowed_fields, allowed_fields->len - 1);
+	_print_fill (nmc_config,
+	             targets,
+	             &g_array_index (cols, PrintDataCol, 0),
+	             cols->len,
+	             &header_row,
+	             &cells);
+
+	_print_do (nmc_config,
+	           header_name_no_l10n,
+	           header_row->len,
+	           cells->len / header_row->len,
+	           &g_array_index (header_row, PrintDataHeaderCell, 0),
+	           &g_array_index (cells, PrintDataCell, 0));
 
-	return g_string_free (allowed_fields, FALSE);
+	return TRUE;
 }
 
-NmcOutputField *
-nmc_dup_fields_array (NmcOutputField fields[], size_t size, guint32 flags)
+/*****************************************************************************/
+
+static void
+pager_fallback (void)
 {
-	NmcOutputField *row;
+	char buf[64];
+	int rb;
 
-	row = g_malloc0 (size);
-	memcpy (row, fields, size);
-	row[0].flags = flags;
+	do {
+		rb = read (STDIN_FILENO, buf, sizeof (buf));
+		if (rb == -1) {
+			if (errno == EINTR) {
+				continue;
+			} else {
+				g_printerr (_("Error reading nmcli output: %s\n"), strerror (errno));
+				_exit(EXIT_FAILURE);
+			}
+		}
+		if (write (STDOUT_FILENO, buf, rb) == -1) {
+			g_printerr (_("Error writing nmcli output: %s\n"), strerror (errno));
+			_exit(EXIT_FAILURE);
+		}
+	} while (rb > 0);
 
-	return row;
+	_exit(EXIT_SUCCESS);
 }
 
 void
-nmc_empty_output_fields (NmCli *nmc)
+nmc_terminal_spawn_pager (const NmcConfig *nmc_config)
 {
-	guint i;
+	const char *pager = getenv ("PAGER");
+	pid_t parent_pid;
+	int fd[2];
+
+	if (   nm_cli.nmc_config.in_editor
+	    || nm_cli.pager_pid > 0
+	    || nmc_config->print_output == NMC_PRINT_TERSE
+	    || !use_colors (nmc_config->use_colors)
+	    || g_strcmp0 (pager, "") == 0
+	    || getauxval (AT_SECURE))
+		return;
 
-	/* Free values in field structure */
-	for (i = 0; i < nmc->output_data->len; i++) {
-		NmcOutputField *fld_arr = g_ptr_array_index (nmc->output_data, i);
-		nmc_free_output_field_values (fld_arr);
+	if (pipe (fd) == -1) {
+		g_printerr (_("Failed to create pager pipe: %s\n"), strerror (errno));
+		return;
 	}
 
-	/* Empty output_data array */
-	if (nmc->output_data->len > 0)
-		g_ptr_array_remove_range (nmc->output_data, 0, nmc->output_data->len);
+	parent_pid = getpid ();
 
-	if (nmc->print_fields.indices) {
-		g_array_free (nmc->print_fields.indices, TRUE);
-		nmc->print_fields.indices = NULL;
+	nm_cli.pager_pid = fork ();
+	if (nm_cli.pager_pid == -1) {
+		g_printerr (_("Failed to fork pager: %s\n"), strerror (errno));
+		close (fd[0]);
+		close (fd[1]);
+		return;
 	}
-}
 
-static const char *
-colorize_string (NmCli *nmc,
-                 NmcTermColor color,
-                 NmcTermFormat color_fmt,
-                 const char *str,
-                 char **out_to_free)
-{
-	const char *out = str;
+	/* In the child start the pager */
+	if (nm_cli.pager_pid == 0) {
+		dup2 (fd[0], STDIN_FILENO);
+		close (fd[0]);
+		close (fd[1]);
 
-	if (   use_colors (nmc)
-	    && (color != NMC_TERM_COLOR_NORMAL || color_fmt != NMC_TERM_FORMAT_NORMAL)) {
-		*out_to_free = nmc_colorize (nmc, color, color_fmt, "%s", str);
-		out = *out_to_free;
+		setenv ("LESS", "FRSXMK", 1);
+		setenv ("LESSCHARSET", "utf-8", 1);
+
+		/* Make sure the pager goes away when the parent dies */
+		if (prctl (PR_SET_PDEATHSIG, SIGTERM) < 0)
+			_exit (EXIT_FAILURE);
+
+		/* Check whether our parent died before we were able
+		 * to set the death signal */
+		if (getppid () != parent_pid)
+			_exit (EXIT_SUCCESS);
+
+		if (pager) {
+			execlp (pager, pager, NULL);
+			execl ("/bin/sh", "sh", "-c", pager, NULL);
+		}
+
+		/* Debian's alternatives command for pagers is
+		 * called 'pager'. Note that we do not call
+		 * sensible-pagers here, since that is just a
+		 * shell script that implements a logic that
+		 * is similar to this one anyway, but is
+		 * Debian-specific. */
+		execlp ("pager", "pager", NULL);
+
+		execlp ("less", "less", NULL);
+		execlp ("more", "more", NULL);
+
+		pager_fallback ();
+		/* not reached */
 	}
 
-	return out;
+	/* Return in the parent */
+	if (dup2 (fd[1], STDOUT_FILENO) < 0)
+		g_printerr (_("Failed to duplicate pager pipe: %s\n"), strerror (errno));
+	if (dup2 (fd[1], STDERR_FILENO) < 0)
+		g_printerr (_("Failed to duplicate pager pipe: %s\n"), strerror (errno));
+
+	close (fd[0]);
+	close (fd[1]);
 }
 
+/*****************************************************************************/
+
 static const char *
-get_value_to_print (NmCli *nmc,
-                    NmcOutputField *field,
+get_value_to_print (NmcColorOption color_option,
+                    const NmcOutputField *field,
                     gboolean field_name,
                     const char *not_set_str,
                     char **out_to_free)
 {
 	gboolean is_array = field->value_is_array;
-	char *value;
+	const char *value;
 	const char *out;
-	gboolean free_value;
+	gs_free char *free_value = NULL;
+
+	nm_assert (out_to_free && !*out_to_free);
 
 	if (field_name)
-		value = _(field->name_l10n);
-	else
+		value = nm_meta_abstract_info_get_name (field->info, FALSE);
+	else {
 		value = field->value
 		            ? (is_array
-		                  ? g_strjoinv (" | ", (char **) field->value)
-		                  : (*((char *) field->value)
-		                        ? (char *) field->value
-		                        : (char *) not_set_str))
-		            : (char *) not_set_str;
-	free_value = field->value && is_array && !field_name;
+		                  ? (free_value = g_strjoinv (" | ", (char **) field->value))
+		                  : (*((const char *) field->value))
+		                        ? field->value
+		                        : not_set_str)
+		            : not_set_str;
+	}
 
 	/* colorize the value */
-	out = colorize_string (nmc, field->color, field->color_fmt, value, out_to_free);
-	if (*out_to_free) {
-		if (free_value)
-			g_free (value);
-	} else if (free_value)
-		 *out_to_free = value;
+	out = colorize_string (color_option, field->color, field->color_fmt, value, out_to_free);
+
+	if (out && out == free_value) {
+		nm_assert (!*out_to_free);
+		*out_to_free = g_steal_pointer (&free_value);
+	}
 
 	return out;
 }
@@ -1094,70 +1599,68 @@ get_value_to_print (NmCli *nmc,
 /*
  * Print both headers or values of 'field_values' array.
  * Entries to print and their order are specified via indices in
- * 'nmc->print_fields.indices' array.
+ * 'nmc->indices' array.
  * Various flags influencing the output of fields are set up in the first item
  * of 'field_values' array.
  */
 void
-print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
+print_required_fields (const NmcConfig *nmc_config,
+                       NmcOfFlags of_flags,
+                       const GArray *indices,
+                       const char *header_name,
+                       int indent,
+                       const NmcOutputField *field_values)
 {
-	GString *str;
+	nm_auto_free_gstring GString *str = NULL;
 	int width1, width2;
 	int table_width = 0;
-	char *line = NULL;
-	char *indent_str;
-	const char *not_set_str = "--";
+	const char *not_set_str;
 	int i;
-	const NmcPrintFields fields = nmc->print_fields;
-	gboolean multiline = nmc->multiline_output;
-	gboolean terse = (nmc->print_output == NMC_PRINT_TERSE);
-	gboolean pretty = (nmc->print_output == NMC_PRINT_PRETTY);
-	gboolean escape = nmc->escape_values;
-	gboolean main_header_add = field_values[0].flags & NMC_OF_FLAG_MAIN_HEADER_ADD;
-	gboolean main_header_only = field_values[0].flags & NMC_OF_FLAG_MAIN_HEADER_ONLY;
-	gboolean field_names = field_values[0].flags & NMC_OF_FLAG_FIELD_NAMES;
-	gboolean section_prefix = field_values[0].flags & NMC_OF_FLAG_SECTION_PREFIX;
-	gboolean main_header = main_header_add || main_header_only;
-
-	enum { ML_HEADER_WIDTH = 79 };
-	enum { ML_VALUE_INDENT = 40 };
+	gboolean terse = (nmc_config->print_output == NMC_PRINT_TERSE);
+	gboolean pretty = (nmc_config->print_output == NMC_PRINT_PRETTY);
+	gboolean main_header_add = of_flags & NMC_OF_FLAG_MAIN_HEADER_ADD;
+	gboolean main_header_only = of_flags & NMC_OF_FLAG_MAIN_HEADER_ONLY;
+	gboolean field_names = of_flags & NMC_OF_FLAG_FIELD_NAMES;
+	gboolean section_prefix = of_flags & NMC_OF_FLAG_SECTION_PREFIX;
 
+	/* Optionally start paging the output. */
+	nmc_terminal_spawn_pager (nmc_config);
 
 	/* --- Main header --- */
-	if (main_header && pretty) {
-		int header_width = nmc_string_screen_width (fields.header_name, NULL) + 4;
+	if ((main_header_add || main_header_only) && pretty) {
+		gs_free char *line = NULL;
+		int header_width;
 
-		if (multiline) {
-			table_width = header_width < ML_HEADER_WIDTH ? ML_HEADER_WIDTH : header_width;
+		header_width = nmc_string_screen_width (header_name, NULL) + 4;
+
+		if (nmc_config->multiline_output) {
+			table_width = NM_MAX (header_width, ML_HEADER_WIDTH);
 			line = g_strnfill (ML_HEADER_WIDTH, '=');
 		} else { /* tabular */
-			table_width = table_width < header_width ? header_width : table_width;
+			table_width = NM_MAX (table_width, header_width);
 			line = g_strnfill (table_width, '=');
 		}
 
-		width1 = strlen (fields.header_name);
-		width2 = nmc_string_screen_width (fields.header_name, NULL);
+		width1 = strlen (header_name);
+		width2 = nmc_string_screen_width (header_name, NULL);
 		g_print ("%s\n", line);
-		g_print ("%*s\n", (table_width + width2)/2 + width1 - width2, fields.header_name);
+		g_print ("%*s\n", (table_width + width2)/2 + width1 - width2, header_name);
 		g_print ("%s\n", line);
-		g_free (line);
 	}
 
 	if (main_header_only)
 		return;
 
 	/* No field headers are printed in terse mode nor for multiline output */
-	if ((terse || multiline) && field_names)
+	if ((terse || nmc_config->multiline_output) && field_names)
 		return;
 
-	if (terse)
-		not_set_str = ""; /* Don't replace empty strings in terse mode */
-
+	/* Don't replace empty strings in terse mode */
+	not_set_str = terse ? "" : "--";
 
-	if (multiline) {
-		for (i = 0; i < fields.indices->len; i++) {
-			char *tmp;
-			int idx = g_array_index (fields.indices, int, i);
+	if (nmc_config->multiline_output) {
+		for (i = 0; i < indices->len; i++) {
+			int idx = g_array_index (indices, int, i);
 			gboolean is_array = field_values[idx].value_is_array;
 
 			/* section prefix can't be an array */
@@ -1167,49 +1670,52 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
 				continue;
 
 			if (is_array) {
-				/* value is a null-terminated string array */
-				const char **p, *val, *print_val;
 				gs_free char *val_to_free = NULL;
+				const char **p, *val, *print_val;
 				int j;
 
+				/* value is a null-terminated string array */
+
 				for (p = (const char **) field_values[idx].value, j = 1; p && *p; p++, j++) {
-					val = *p ? *p : not_set_str;
-					print_val = colorize_string (nmc, field_values[idx].color, field_values[idx].color_fmt,
+					gs_free char *tmp = NULL;
+
+					val = *p ?: not_set_str;
+					print_val = colorize_string (nmc_config->use_colors, field_values[idx].color, field_values[idx].color_fmt,
 					                             val, &val_to_free);
 					tmp = g_strdup_printf ("%s%s%s[%d]:",
 					                       section_prefix ? (const char*) field_values[0].value : "",
 					                       section_prefix ? "." : "",
-					                       _(field_values[idx].name_l10n),
+					                       nm_meta_abstract_info_get_name (field_values[idx].info, FALSE),
 					                       j);
 					width1 = strlen (tmp);
 					width2 = nmc_string_screen_width (tmp, NULL);
-					g_print ("%-*s%s\n", terse ? 0 : ML_VALUE_INDENT+width1-width2, tmp, print_val);
-					g_free (tmp);
+					g_print ("%-*s%s\n", (int) (terse ? 0 : ML_VALUE_INDENT+width1-width2), tmp, print_val);
 				}
 			} else {
-				/* value is a string */
+				gs_free char *val_to_free = NULL;
+				gs_free char *tmp = NULL;
 				const char *hdr_name = (const char*) field_values[0].value;
 				const char *val = (const char*) field_values[idx].value;
 				const char *print_val;
-				gs_free char *val_to_free = NULL;
+
+				/* value is a string */
 
 				val = val && *val ? val : not_set_str;
-				print_val = colorize_string (nmc, field_values[idx].color, field_values[idx].color_fmt,
+				print_val = colorize_string (nmc_config->use_colors, field_values[idx].color, field_values[idx].color_fmt,
 				                             val, &val_to_free);
 				tmp = g_strdup_printf ("%s%s%s:",
 				                       section_prefix ? hdr_name : "",
 				                       section_prefix ? "." : "",
-				                       _(field_values[idx].name_l10n));
+				                       nm_meta_abstract_info_get_name (field_values[idx].info, FALSE));
 				width1 = strlen (tmp);
 				width2 = nmc_string_screen_width (tmp, NULL);
-				g_print ("%-*s%s\n", terse ? 0 : ML_VALUE_INDENT+width1-width2, tmp, print_val);
-				g_free (tmp);
+				g_print ("%-*s%s\n", (int) (terse ? 0 : ML_VALUE_INDENT+width1-width2), tmp, print_val);
 			}
 		}
 		if (pretty) {
-			line = g_strnfill (ML_HEADER_WIDTH, '-');
-			g_print ("%s\n", line);
-			g_free (line);
+			gs_free char *line = NULL;
+
+			g_print ("%s\n", (line = g_strnfill (ML_HEADER_WIDTH, '-')));
 		}
 
 		return;
@@ -1219,14 +1725,18 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
 
 	str = g_string_new (NULL);
 
-	for (i = 0; i < fields.indices->len; i++) {
-		int idx = g_array_index (fields.indices, int, i);
+	for (i = 0; i < indices->len; i++) {
 		gs_free char *val_to_free = NULL;
-		const char *value = get_value_to_print (nmc, (NmcOutputField *) field_values+idx, field_names,
-		                                        not_set_str, &val_to_free);
+		int idx;
+		const char *value;
+
+		idx = g_array_index (indices, int, i);
+
+		value = get_value_to_print (nmc_config->use_colors, (NmcOutputField *) field_values+idx, field_names,
+		                            not_set_str, &val_to_free);
 
 		if (terse) {
-			if (escape) {
+			if (nmc_config->escape_values) {
 				const char *p = value;
 				while (*p) {
 					if (*p == ':' || *p == '\\')
@@ -1250,46 +1760,37 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
 	/* Print actual values */
 	if (str->len > 0) {
 		g_string_truncate (str, str->len-1);  /* Chop off last column separator */
-		if (fields.indent > 0) {
-			indent_str = g_strnfill (fields.indent, ' ');
-			g_string_prepend (str, indent_str);
-			g_free (indent_str);
+		if (indent > 0) {
+			gs_free char *indent_str = NULL;
+
+			g_string_prepend (str, (indent_str = g_strnfill (indent, ' ')));
 		}
+
 		g_print ("%s\n", str->str);
 
 		/* Print horizontal separator */
 		if (field_names && pretty) {
-			line = g_strnfill (table_width, '-');
-			g_print ("%s\n", line);
-			g_free (line);
+			gs_free char *line = NULL;
+
+			g_print ("%s\n", (line = g_strnfill (table_width, '-')));
 		}
 	}
-
-	g_string_free (str, TRUE);
 }
 
-/*
- * Print nmc->output_data
- *
- * It first finds out maximal string length in columns and fill the value to
- * 'width' member of NmcOutputField, so that columns in tabular output are
- * properly aligned. Then each object (row in tabular) is printed using
- * print_required_fields() function.
- */
 void
-print_data (NmCli *nmc)
+print_data_prepare_width (GPtrArray *output_data)
 {
 	int i, j;
 	size_t len;
 	NmcOutputField *row;
 	int num_fields = 0;
 
-	if (!nmc->output_data || nmc->output_data->len < 1)
+	if (!output_data || output_data->len < 1)
 		return;
 
 	/* How many fields? */
-	row = g_ptr_array_index (nmc->output_data, 0);
-	while (row->name) {
+	row = g_ptr_array_index (output_data, 0);
+	while (row->info) {
 		num_fields++;
 		row++;
 	}
@@ -1297,27 +1798,39 @@ print_data (NmCli *nmc)
 	/* Find out maximal string lengths */
 	for (i = 0; i < num_fields; i++) {
 		size_t max_width = 0;
-		for (j = 0; j < nmc->output_data->len; j++) {
+		for (j = 0; j < output_data->len; j++) {
 			gboolean field_names;
 			gs_free char * val_to_free = NULL;
 			const char *value;
 
-			row = g_ptr_array_index (nmc->output_data, j);
+			row = g_ptr_array_index (output_data, j);
 			field_names = row[0].flags & NMC_OF_FLAG_FIELD_NAMES;
-			value = get_value_to_print (NULL, row+i, field_names, "--", &val_to_free);
+			value = get_value_to_print (NMC_USE_COLOR_NO, row+i, field_names, "--", &val_to_free);
 			len = nmc_string_screen_width (value, NULL);
 			max_width = len > max_width ? len : max_width;
 		}
-		for (j = 0; j < nmc->output_data->len; j++) {
-			row = g_ptr_array_index (nmc->output_data, j);
+		for (j = 0; j < output_data->len; j++) {
+			row = g_ptr_array_index (output_data, j);
 			row[i].width = max_width + 1;
 		}
 	}
+}
+
+void
+print_data (const NmcConfig *nmc_config,
+            const GArray *indices,
+            const char *header_name,
+            int indent,
+            const NmcOutputData *out)
+{
+	guint i;
+
+	for (i = 0; i < out->output_data->len; i++) {
+		const NmcOutputField *field_values = g_ptr_array_index (out->output_data, i);
 
-	/* Now we can print the data. */
-	for (i = 0; i < nmc->output_data->len; i++) {
-		row = g_ptr_array_index (nmc->output_data, i);
-		print_required_fields (nmc, row);
+		print_required_fields (nmc_config, field_values[0].flags,
+		                       indices, header_name,
+		                       indent, field_values);
 	}
 }
 
diff --git a/clients/cli/utils.h b/clients/cli/utils.h
index a1c08764..ffc5b6f3 100644
--- a/clients/cli/utils.h
+++ b/clients/cli/utils.h
@@ -14,7 +14,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2010 - 2015 Red Hat, Inc.
+ * Copyright 2010 - 2017 Red Hat, Inc.
  */
 
 #ifndef NMC_UTILS_H
@@ -32,74 +32,147 @@ typedef struct {
 	gboolean found;
 } nmc_arg_t;
 
-typedef enum {
-	NMC_TRI_STATE_NO,
-	NMC_TRI_STATE_YES,
-	NMC_TRI_STATE_UNKNOWN,
-} NMCTriStateValue;
-
 /* === Functions === */
-gboolean matches (const char *cmd, const char *pattern);
 int next_arg (NmCli *nmc, int *argc, char ***argv, ...);
 gboolean nmc_arg_is_help (const char *arg);
 gboolean nmc_arg_is_option (const char *arg, const char *opt_name);
 gboolean nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GError **error);
 char *ssid_to_hex (const char *str, gsize len);
-gboolean nmc_string_to_int_base (const char *str,
-                                 int base,
-                                 gboolean range_check,
-                                 long int min,
-                                 long int max,
-                                 long int *value);
-gboolean nmc_string_to_uint_base (const char *str,
-                                  int base,
-                                  gboolean range_check,
-                                  unsigned long int min,
-                                  unsigned long int max,
-                                  unsigned long int *value);
-gboolean nmc_string_to_int (const char *str,
-                            gboolean range_check,
-                            long int min,
-                            long int max,
-                            long int *value);
-gboolean nmc_string_to_uint (const char *str,
-                             gboolean range_check,
-                             unsigned long int min,
-                             unsigned long int max,
-                             unsigned long int *value);
-gboolean nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error);
-gboolean nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error);
 void nmc_terminal_erase_line (void);
 void nmc_terminal_show_progress (const char *str);
-const char *nmc_term_color_sequence (NmcTermColor color);
-const char *nmc_term_format_sequence (NmcTermFormat format);
-NmcTermColor nmc_term_color_parse_string (const char *str, GError **error);
-char *nmc_colorize (NmCli *nmc, NmcTermColor color, NmcTermFormat format, const char * fmt, ...)  _nm_printf (4, 5);
+void nmc_terminal_spawn_pager (const NmcConfig *nmc_config);
+gboolean nmc_term_use_colors (NmcColorOption color_option);
+const char *nmc_term_color_sequence (NMMetaTermColor color);
+const char *nmc_term_format_sequence (NMMetaTermFormat format);
+NMMetaTermColor nmc_term_color_parse_string (const char *str, GError **error);
+char *nmc_colorize (NmcColorOption color_option, NMMetaTermColor color, NMMetaTermFormat format, const char * fmt, ...)  _nm_printf (4, 5);
 void nmc_filter_out_colors_inplace (char *str);
 char *nmc_filter_out_colors (const char *str);
 char *nmc_get_user_input (const char *ask_str);
 int nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote,
                              char ***argv, int *argc);
 const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
-char * nmc_util_strv_for_display (const char **strv, gboolean brackets);
+char * nmc_util_strv_for_display (const char *const*strv, gboolean brackets);
 char **nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens);
 int nmc_string_screen_width (const char *start, const char *end);
 void set_val_str  (NmcOutputField fields_array[], guint32 index, char *value);
 void set_val_strc (NmcOutputField fields_array[], guint32 index, const char *value);
 void set_val_arr  (NmcOutputField fields_array[], guint32 index, char **value);
 void set_val_arrc (NmcOutputField fields_array[], guint32 index, const char **value);
-void set_val_color_all (NmcOutputField fields_array[], NmcTermColor color);
-void set_val_color_fmt_all (NmcOutputField fields_array[], NmcTermFormat format);
+void set_val_color_all (NmcOutputField fields_array[], NMMetaTermColor color);
+void set_val_color_fmt_all (NmcOutputField fields_array[], NMMetaTermFormat format);
 void nmc_free_output_field_values (NmcOutputField fields_array[]);
+
 GArray *parse_output_fields (const char *fields_str,
-                             const NmcOutputField fields_array[],
+                             const NMMetaAbstractInfo *const* fields_array,
                              gboolean parse_groups,
                              GPtrArray **group_fields,
                              GError **error);
-char *nmc_get_allowed_fields (const NmcOutputField fields_array[], int group_idx);
-NmcOutputField *nmc_dup_fields_array (NmcOutputField fields[], size_t size, guint32 flags);
-void nmc_empty_output_fields (NmCli *nmc);
-void print_required_fields (NmCli *nmc, const NmcOutputField field_values[]);
-void print_data (NmCli *nmc);
+NmcOutputField *nmc_dup_fields_array (const NMMetaAbstractInfo *const*fields, NmcOfFlags flags);
+void nmc_empty_output_fields (NmcOutputData *output_data);
+void print_required_fields (const NmcConfig *nmc_config,
+                            NmcOfFlags of_flags,
+                            const GArray *indices,
+                            const char *header_name,
+                            int indent,
+                            const NmcOutputField *field_values);
+void print_data_prepare_width (GPtrArray *output_data);
+void print_data (const NmcConfig *nmc_config,
+                 const GArray *indices,
+                 const char *header_name,
+                 int indent,
+                 const NmcOutputData *out);
+
+/*****************************************************************************/
+
+extern const NMMetaEnvironment *const nmc_meta_environment;
+extern NmCli *const nmc_meta_environment_arg;
+
+typedef enum {
+
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_RUNNING = 0,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_VERSION,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STATE,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STARTUP,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_CONNECTIVITY,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NETWORKING,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI_HW,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN_HW,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX_HW,
+	NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX,
+	_NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NUM,
+
+	NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_PERMISSION = 0,
+	NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_VALUE,
+	_NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_NUM,
+
+	NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_LEVEL = 0,
+	NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_DOMAINS,
+	_NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_NUM,
+
+	NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ADDRESS = 0,
+	NMC_GENERIC_INFO_TYPE_IP4_CONFIG_GATEWAY,
+	NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ROUTE,
+	NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DNS,
+	NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DOMAIN,
+	NMC_GENERIC_INFO_TYPE_IP4_CONFIG_WINS,
+	_NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM,
+
+	NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ADDRESS = 0,
+	NMC_GENERIC_INFO_TYPE_IP6_CONFIG_GATEWAY,
+	NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ROUTE,
+	NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DNS,
+	NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN,
+	_NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM,
+
+} NmcGenericInfoType;
+
+#define NMC_HANDLE_TERMFORMAT(color) \
+	G_STMT_START { \
+		if (get_type == NM_META_ACCESSOR_GET_TYPE_TERMFORMAT) \
+			return nm_meta_termformat_pack ((color), NM_META_TERM_FORMAT_NORMAL); \
+	} G_STMT_END
+
+struct _NmcMetaGenericInfo {
+	union {
+		NMObjBaseInst parent;
+		const NMMetaType *meta_type;
+	};
+	NmcGenericInfoType info_type;
+	const char *name;
+	const char *name_header;
+	const NmcMetaGenericInfo *const*nested;
+	gconstpointer (*get_fcn) (const NMMetaEnvironment *environment,
+	                          gpointer environment_user_data,
+	                          const NmcMetaGenericInfo *info,
+	                          gpointer target,
+	                          NMMetaAccessorGetType get_type,
+	                          NMMetaAccessorGetFlags get_flags,
+	                          NMMetaAccessorGetOutFlags *out_flags,
+	                          gpointer *out_to_free);
+};
+
+#define NMC_META_GENERIC(n, ...) \
+	(&((NmcMetaGenericInfo) { \
+		.meta_type =                        &nmc_meta_type_generic_info, \
+		.name =                             n, \
+		__VA_ARGS__ \
+	}))
+
+#define NMC_META_GENERIC_WITH_NESTED(n, nest, ...) \
+	NMC_META_GENERIC (n, .nested = (nest), __VA_ARGS__)
+
+/*****************************************************************************/
+
+gboolean nmc_print (const NmcConfig *nmc_config,
+                    gpointer const *targets,
+                    const char *header_name_no_l10n,
+                    const NMMetaAbstractInfo *const*fields,
+                    const char *fields_str,
+                    GError **error);
+
+/*****************************************************************************/
 
 #endif /* NMC_UTILS_H */
diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c
new file mode 100644
index 00000000..bf4dcc77
--- /dev/null
+++ b/clients/common/nm-client-utils.c
@@ -0,0 +1,517 @@
+/* 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-client-utils.h"
+
+#include "nm-device-bond.h"
+#include "nm-device-bridge.h"
+#include "nm-device-team.h"
+
+/*
+ * Convert string to unsigned integer.
+ * If required, the resulting number is checked to be in the <min,max> range.
+ */
+static gboolean
+nmc_string_to_uint_base (const char *str,
+                         int base,
+                         gboolean range_check,
+                         unsigned long int min,
+                         unsigned long int max,
+                         unsigned long int *value)
+{
+	char *end;
+	unsigned long int tmp;
+
+	errno = 0;
+	tmp = strtoul (str, &end, base);
+	if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) {
+		return FALSE;
+	}
+	*value = tmp;
+	return TRUE;
+}
+
+gboolean
+nmc_string_to_uint (const char *str,
+                    gboolean range_check,
+                    unsigned long int min,
+                    unsigned long int max,
+                    unsigned long int *value)
+{
+	return nmc_string_to_uint_base (str, 10, range_check, min, max, value);
+}
+
+gboolean
+nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error)
+{
+	const char *s_true[] = { "true", "yes", "on", "1", NULL };
+	const char *s_false[] = { "false", "no", "off", "0", NULL };
+
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	if (g_strcmp0 (str, "o") == 0) {
+		g_set_error (error, 1, 0,
+		             /* Translators: the first %s is the partial value entered by
+		              * the user, the second %s a list of compatible values.
+		              */
+		             _("'%s' is ambiguous (%s)"), str, "on x off");
+		return FALSE;
+	}
+
+	if (nmc_string_is_valid (str, s_true, NULL))
+		*val_bool = TRUE;
+	else if (nmc_string_is_valid (str, s_false, NULL))
+		*val_bool = FALSE;
+	else {
+		g_set_error (error, 1, 0,
+		             _("'%s' is not valid; use [%s] or [%s]"),
+		             str, "true, yes, on", "false, no, off");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+gboolean
+nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error)
+{
+	const char *s_true[] = { "true", "yes", "on", NULL };
+	const char *s_false[] = { "false", "no", "off", NULL };
+	const char *s_unknown[] = { "unknown", NULL };
+
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	if (g_strcmp0 (str, "o") == 0) {
+		g_set_error (error, 1, 0,
+		             /* Translators: the first %s is the partial value entered by
+		              * the user, the second %s a list of compatible values.
+		              */
+		             _("'%s' is ambiguous (%s)"), str, "on x off");
+		return FALSE;
+	}
+
+	if (nmc_string_is_valid (str, s_true, NULL))
+		*val = NMC_TRI_STATE_YES;
+	else if (nmc_string_is_valid (str, s_false, NULL))
+		*val = NMC_TRI_STATE_NO;
+	else if (nmc_string_is_valid (str, s_unknown, NULL))
+		*val = NMC_TRI_STATE_UNKNOWN;
+	else {
+		g_set_error (error, 1, 0,
+		             _("'%s' is not valid; use [%s], [%s] or [%s]"),
+		             str, "true, yes, on", "false, no, off", "unknown");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/*
+ * Check whether 'input' is contained in 'allowed' array. It performs case
+ * insensitive comparison and supports shortcut strings if they are unique.
+ * Returns: a pointer to found string in allowed array on success or NULL.
+ * On failure: error->code : 0 - string not found; 1 - string is ambiguous
+ */
+const char *
+nmc_string_is_valid (const char *input, const char **allowed, GError **error)
+{
+	const char **p;
+	size_t input_ln, p_len;
+	gboolean prev_match = FALSE;
+	const char *ret = NULL;
+
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	if (!input || !*input)
+		goto finish;
+
+	input_ln = strlen (input);
+	for (p = allowed; p && *p; p++) {
+		p_len = strlen (*p);
+		if (g_ascii_strncasecmp (input, *p, input_ln) == 0) {
+			if (input_ln == p_len) {
+				ret = *p;
+				break;
+			}
+			if (!prev_match)
+				ret = *p;
+			else {
+				g_set_error (error, 1, 1, _("'%s' is ambiguous (%s x %s)"),
+				             input, ret, *p);
+				return NULL;
+			}
+			prev_match = TRUE;
+		}
+	}
+
+finish:
+	if (ret == NULL) {
+		char *valid_vals = g_strjoinv (", ", (char **) allowed);
+		if (!input || !*input)
+			g_set_error (error, 1, 0, _("missing name, try one of [%s]"), valid_vals);
+		else
+			g_set_error (error, 1, 0, _("'%s' not among [%s]"), input, valid_vals);
+
+		g_free (valid_vals);
+	}
+	return ret;
+}
+
+/*
+ * Wrapper function for g_strsplit_set() that removes empty strings
+ * from the vector as they are not useful in most cases.
+ */
+char **
+nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens)
+{
+	/* remove empty strings */
+	return _nm_utils_strv_cleanup (g_strsplit_set (str, delimiter, max_tokens),
+	                               FALSE, TRUE, FALSE);
+}
+
+gboolean
+matches (const char *cmd, const char *pattern)
+{
+	size_t len = strlen (cmd);
+	if (!len || len > strlen (pattern))
+		return FALSE;
+	return memcmp (pattern, cmd, len) == 0;
+}
+
+const char *
+nmc_bond_validate_mode (const char *mode, GError **error)
+{
+	unsigned long mode_int;
+	static const char *valid_modes[] = { "balance-rr",
+	                                     "active-backup",
+	                                     "balance-xor",
+	                                     "broadcast",
+	                                     "802.3ad",
+	                                     "balance-tlb",
+	                                     "balance-alb",
+	                                     NULL };
+	if (nmc_string_to_uint (mode, TRUE, 0, 6, &mode_int)) {
+		/* Translate bonding mode numbers to mode names:
+		 * https://www.kernel.org/doc/Documentation/networking/bonding.txt
+		 */
+		return valid_modes[mode_int];
+	} else
+		return nmc_string_is_valid (mode, valid_modes, error);
+}
+
+const char *
+nmc_device_state_to_string (NMDeviceState state)
+{
+	switch (state) {
+	case NM_DEVICE_STATE_UNMANAGED:
+		return _("unmanaged");
+	case NM_DEVICE_STATE_UNAVAILABLE:
+		return _("unavailable");
+	case NM_DEVICE_STATE_DISCONNECTED:
+		return _("disconnected");
+	case NM_DEVICE_STATE_PREPARE:
+		return _("connecting (prepare)");
+	case NM_DEVICE_STATE_CONFIG:
+		return _("connecting (configuring)");
+	case NM_DEVICE_STATE_NEED_AUTH:
+		return _("connecting (need authentication)");
+	case NM_DEVICE_STATE_IP_CONFIG:
+		return _("connecting (getting IP configuration)");
+	case NM_DEVICE_STATE_IP_CHECK:
+		return _("connecting (checking IP connectivity)");
+	case NM_DEVICE_STATE_SECONDARIES:
+		return _("connecting (starting secondary connections)");
+	case NM_DEVICE_STATE_ACTIVATED:
+		return _("connected");
+	case NM_DEVICE_STATE_DEACTIVATING:
+		return _("deactivating");
+	case NM_DEVICE_STATE_FAILED:
+		return _("connection failed");
+	case NM_DEVICE_STATE_UNKNOWN:
+		return _("unknown");
+	}
+
+	return _("unknown");
+}
+
+const char *
+nmc_device_metered_to_string (NMMetered value)
+{
+	switch (value) {
+	case NM_METERED_YES:
+		return _("yes");
+	case NM_METERED_NO:
+		return _("no");
+	case NM_METERED_GUESS_YES:
+		return _("yes (guessed)");
+	case NM_METERED_GUESS_NO:
+		return _("no (guessed)");
+	case NM_METERED_UNKNOWN:
+		return _("unknown");
+	}
+
+	return _("unknown");
+}
+
+const char *
+nmc_device_reason_to_string (NMDeviceStateReason reason)
+{
+	switch (reason) {
+	case NM_DEVICE_STATE_REASON_NONE:
+		return _("No reason given");
+	case NM_DEVICE_STATE_REASON_UNKNOWN:
+		return _("Unknown error");
+	case NM_DEVICE_STATE_REASON_NOW_MANAGED:
+		return _("Device is now managed");
+	case NM_DEVICE_STATE_REASON_NOW_UNMANAGED:
+		return _("Device is now unmanaged");
+	case NM_DEVICE_STATE_REASON_CONFIG_FAILED:
+		return _("The device could not be readied for configuration");
+	case NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE:
+		return _("IP configuration could not be reserved (no available address, timeout, etc.)");
+	case NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED:
+		return _("The IP configuration is no longer valid");
+	case NM_DEVICE_STATE_REASON_NO_SECRETS:
+		return _("Secrets were required, but not provided");
+	case NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT:
+		return _("802.1X supplicant disconnected");
+	case NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED:
+		return _("802.1X supplicant configuration failed");
+	case NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED:
+		return _("802.1X supplicant failed");
+	case NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT:
+		return _("802.1X supplicant took too long to authenticate");
+	case NM_DEVICE_STATE_REASON_PPP_START_FAILED:
+		return _("PPP service failed to start");
+	case NM_DEVICE_STATE_REASON_PPP_DISCONNECT:
+		return _("PPP service disconnected");
+	case NM_DEVICE_STATE_REASON_PPP_FAILED:
+		return _("PPP failed");
+	case NM_DEVICE_STATE_REASON_DHCP_START_FAILED:
+		return _("DHCP client failed to start");
+	case NM_DEVICE_STATE_REASON_DHCP_ERROR:
+		return _("DHCP client error");
+	case NM_DEVICE_STATE_REASON_DHCP_FAILED:
+		return _("DHCP client failed");
+	case NM_DEVICE_STATE_REASON_SHARED_START_FAILED:
+		return _("Shared connection service failed to start");
+	case NM_DEVICE_STATE_REASON_SHARED_FAILED:
+		return _("Shared connection service failed");
+	case NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED:
+		return _("AutoIP service failed to start");
+	case NM_DEVICE_STATE_REASON_AUTOIP_ERROR:
+		return _("AutoIP service error");
+	case NM_DEVICE_STATE_REASON_AUTOIP_FAILED:
+		return _("AutoIP service failed");
+	case NM_DEVICE_STATE_REASON_MODEM_BUSY:
+		return _("The line is busy");
+	case NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE:
+		return _("No dial tone");
+	case NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER:
+		return _("No carrier could be established");
+	case NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT:
+		return _("The dialing request timed out");
+	case NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED:
+		return _("The dialing attempt failed");
+	case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED:
+		return _("Modem initialization failed");
+	case NM_DEVICE_STATE_REASON_GSM_APN_FAILED:
+		return _("Failed to select the specified APN");
+	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING:
+		return _("Not searching for networks");
+	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED:
+		return _("Network registration denied");
+	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT:
+		return _("Network registration timed out");
+	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED:
+		return _("Failed to register with the requested network");
+	case NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED:
+		return _("PIN check failed");
+	case NM_DEVICE_STATE_REASON_FIRMWARE_MISSING:
+		return _("Necessary firmware for the device may be missing");
+	case NM_DEVICE_STATE_REASON_REMOVED:
+		return _("The device was removed");
+	case NM_DEVICE_STATE_REASON_SLEEPING:
+		return _("NetworkManager went to sleep");
+	case NM_DEVICE_STATE_REASON_CONNECTION_REMOVED:
+		return _("The device's active connection disappeared");
+	case NM_DEVICE_STATE_REASON_USER_REQUESTED:
+		return _("Device disconnected by user or client");
+	case NM_DEVICE_STATE_REASON_CARRIER:
+		return _("Carrier/link changed");
+	case NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED:
+		return _("The device's existing connection was assumed");
+	case NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE:
+		return _("The supplicant is now available");
+	case NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND:
+		return _("The modem could not be found");
+	case NM_DEVICE_STATE_REASON_BT_FAILED:
+		return _("The Bluetooth connection failed or timed out");
+	case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED:
+		return _("GSM Modem's SIM card not inserted");
+	case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED:
+		return _("GSM Modem's SIM PIN required");
+	case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED:
+		return _("GSM Modem's SIM PUK required");
+	case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG:
+		return _("GSM Modem's SIM wrong");
+	case NM_DEVICE_STATE_REASON_INFINIBAND_MODE:
+		return _("InfiniBand device does not support connected mode");
+        case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED:
+		return _("A dependency of the connection failed");
+	case NM_DEVICE_STATE_REASON_BR2684_FAILED:
+		return _("A problem with the RFC 2684 Ethernet over ADSL bridge");
+	case NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE:
+		return _("ModemManager is unavailable");
+	case NM_DEVICE_STATE_REASON_SSID_NOT_FOUND:
+		return _("The Wi-Fi network could not be found");
+	case NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED:
+		return _("A secondary connection of the base connection failed");
+	case NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED:
+		return _("DCB or FCoE setup failed");
+	case NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED:
+		return _("teamd control failed");
+	case NM_DEVICE_STATE_REASON_MODEM_FAILED:
+		return _("Modem failed or no longer available");
+	case NM_DEVICE_STATE_REASON_MODEM_AVAILABLE:
+		return _("Modem now ready and available");
+	case NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT:
+		return _("SIM PIN was incorrect");
+	case NM_DEVICE_STATE_REASON_NEW_ACTIVATION:
+		return _("New connection activation was enqueued");
+	case NM_DEVICE_STATE_REASON_PARENT_CHANGED:
+		return _("The device's parent changed");
+	case NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED:
+		return _("The device parent's management changed");
+
+	case NM_DEVICE_STATE_REASON_OVSDB_FAILED:
+		return _("OpenVSwitch database connection failed");
+	}
+
+	/* TRANSLATORS: Unknown reason for a device state change (NMDeviceStateReason) */
+	return _("Unknown");
+}
+
+const char *
+nm_active_connection_state_reason_to_string (NMActiveConnectionStateReason reason)
+{
+	switch (reason) {
+	case NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN:
+		return _("Unknown reason");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_NONE:
+		return _("The connection was disconnected");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED:
+		return _("Disconnected by user");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED:
+		return _("The base network connection was interrupted");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED:
+		return _("The VPN service stopped unexpectedly");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID:
+		return _("The VPN service returned invalid configuration");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT:
+		return _("The connection attempt timed out");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT:
+		return _("The VPN service did not start in time");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED:
+		return _("The VPN service failed to start");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS:
+		return _("No valid secrets");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED:
+		return _("Invalid secrets");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED:
+		return _("The connection was removed");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED:
+		return _("Master connection failed");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED:
+		return _("Could not create a software link");
+	case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED:
+		return _("The device disappeared");
+	default:
+		/* TRANSLATORS: Unknown reason for a connection state change (NMActiveConnectionStateReason) */
+		return _("Unknown");
+	}
+}
+
+NMActiveConnectionState
+nmc_activation_get_effective_state (NMActiveConnection *active,
+                                    NMDevice *device,
+                                    const char **reason)
+{
+	NMActiveConnectionState ac_state;
+	NMActiveConnectionStateReason ac_reason;
+	NMDeviceState dev_state = NM_DEVICE_STATE_UNKNOWN;
+	NMDeviceStateReason dev_reason = NM_DEVICE_STATE_REASON_UNKNOWN;
+
+	g_return_val_if_fail (active, NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
+	g_return_val_if_fail (reason, NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
+
+	*reason = NULL;
+	ac_reason = nm_active_connection_get_state_reason (active);
+
+	if (device) {
+		dev_state = nm_device_get_state (device);
+		dev_reason = nm_device_get_state_reason (device);
+	}
+
+	ac_state = nm_active_connection_get_state (active);
+	switch (ac_state) {
+	case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED:
+		if (   !device
+		    || ac_reason != NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED
+		    || nm_device_get_active_connection (device) != active) {
+			/* (1)
+			 * - we have no device,
+			 * - or, @ac_reason is specific
+			 * - or, @device no longer references the current @active
+			 * >> we complete with @ac_reason. */
+			*reason = nm_active_connection_state_reason_to_string (ac_reason);
+		} else if (   dev_state <= NM_DEVICE_STATE_DISCONNECTED
+		           || dev_state >= NM_DEVICE_STATE_FAILED) {
+			/* (2)
+			 * - not (1)
+			 * - and, the device is no longer in an activated state,
+			 * >> we complete with @dev_reason. */
+			*reason = nmc_device_reason_to_string (dev_reason);
+		} else {
+			/* (3)
+			 * we wait for the device go disconnect. We will get a better
+			 * failure reason from the device (2). */
+			return NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
+		}
+		break;
+	case NM_ACTIVE_CONNECTION_STATE_ACTIVATING:
+		/* activating master connection does not automatically activate any slaves, so their
+		 * active connection state will not progress beyond ACTIVATING state.
+		 * Monitor the device instead. */
+		if (   device
+		    && (   NM_IS_DEVICE_BOND (device)
+		        || NM_IS_DEVICE_TEAM (device)
+		        || NM_IS_DEVICE_BRIDGE (device))
+		    && dev_state >= NM_DEVICE_STATE_IP_CONFIG
+		    && dev_state <= NM_DEVICE_STATE_ACTIVATED) {
+			*reason = "master waiting for slaves";
+			return NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return ac_state;
+}
diff --git a/clients/common/nm-client-utils.h b/clients/common/nm-client-utils.h
new file mode 100644
index 00000000..ac18fe94
--- /dev/null
+++ b/clients/common/nm-client-utils.h
@@ -0,0 +1,59 @@
+/* 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.
+ */
+
+#ifndef __NM_CLIENT_UTILS_H__
+#define __NM_CLIENT_UTILS_H__
+
+#include "nm-meta-setting.h"
+#include "nm-active-connection.h"
+#include "nm-device.h"
+
+typedef enum {
+	NMC_TRI_STATE_NO,
+	NMC_TRI_STATE_YES,
+	NMC_TRI_STATE_UNKNOWN,
+} NMCTriStateValue;
+
+const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
+
+char **nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens);
+
+gboolean nmc_string_to_uint (const char *str,
+                             gboolean range_check,
+                             unsigned long int min,
+                             unsigned long int max,
+                             unsigned long int *value);
+gboolean nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error);
+gboolean nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error);
+
+gboolean matches (const char *cmd, const char *pattern);
+
+/* FIXME: don't expose this function on it's own, at least not from this file. */
+const char *nmc_bond_validate_mode (const char *mode, GError **error);
+
+const char *nm_active_connection_state_reason_to_string (NMActiveConnectionStateReason reason);
+const char *nmc_device_state_to_string (NMDeviceState state);
+const char *nmc_device_reason_to_string (NMDeviceStateReason reason);
+const char *nmc_device_metered_to_string (NMMetered value);
+
+NMActiveConnectionState nmc_activation_get_effective_state (NMActiveConnection *active,
+                                                            NMDevice *device,
+                                                            const char **reason);
+
+#endif /* __NM_CLIENT_UTILS_H__ */
diff --git a/clients/common/nm-meta-setting-access.c b/clients/common/nm-meta-setting-access.c
new file mode 100644
index 00000000..cd7ef783
--- /dev/null
+++ b/clients/common/nm-meta-setting-access.c
@@ -0,0 +1,638 @@
+/* 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-access.h"
+
+/*****************************************************************************/
+
+const NMMetaSettingInfoEditor *
+nm_meta_setting_info_editor_find_by_name (const char *setting_name, gboolean use_alias)
+{
+	const NMMetaSettingInfo *meta_setting_info;
+	const NMMetaSettingInfoEditor *setting_info;
+	guint i;
+
+	g_return_val_if_fail (setting_name, NULL);
+
+	meta_setting_info = nm_meta_setting_infos_by_name (setting_name);
+	setting_info = NULL;
+	if (meta_setting_info) {
+		nm_assert (nm_streq0 (meta_setting_info->setting_name, setting_name));
+		if (meta_setting_info->meta_type < G_N_ELEMENTS (nm_meta_setting_infos_editor)) {
+			setting_info = &nm_meta_setting_infos_editor[meta_setting_info->meta_type];
+			nm_assert (setting_info->general == meta_setting_info);
+		}
+	}
+	if (!setting_info && use_alias) {
+		for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+			if (nm_streq0 (nm_meta_setting_infos_editor[i].alias, setting_name)) {
+				setting_info = &nm_meta_setting_infos_editor[i];
+				break;
+			}
+		}
+	}
+
+	return setting_info;
+}
+
+const NMMetaSettingInfoEditor *
+nm_meta_setting_info_editor_find_by_gtype (GType gtype)
+{
+	const NMMetaSettingInfo *meta_setting_info;
+	const NMMetaSettingInfoEditor *setting_info;
+
+	meta_setting_info = nm_meta_setting_infos_by_gtype (gtype);
+
+	if (!meta_setting_info)
+		return NULL;
+
+	g_return_val_if_fail (meta_setting_info->get_setting_gtype, NULL);
+	g_return_val_if_fail (meta_setting_info->get_setting_gtype () == gtype, NULL);
+
+	if (meta_setting_info->meta_type >= G_N_ELEMENTS (nm_meta_setting_infos_editor))
+		return NULL;
+
+	setting_info = &nm_meta_setting_infos_editor[meta_setting_info->meta_type];
+
+	g_return_val_if_fail (setting_info->general == meta_setting_info, NULL);
+
+	return setting_info;
+}
+
+const NMMetaSettingInfoEditor *
+nm_meta_setting_info_editor_find_by_setting (NMSetting *setting)
+{
+	const NMMetaSettingInfoEditor *setting_info;
+
+	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
+
+	setting_info = nm_meta_setting_info_editor_find_by_gtype (G_OBJECT_TYPE (setting));
+
+	nm_assert (setting_info == nm_meta_setting_info_editor_find_by_name (nm_setting_get_name (setting), FALSE));
+	nm_assert (!setting_info || G_TYPE_CHECK_INSTANCE_TYPE (setting, setting_info->general->get_setting_gtype ()));
+
+	return setting_info;
+}
+
+const NMMetaPropertyInfo *
+nm_meta_setting_info_editor_get_property_info (const NMMetaSettingInfoEditor *setting_info, const char *property_name)
+{
+	guint i;
+
+	g_return_val_if_fail (setting_info, NULL);
+	g_return_val_if_fail (property_name, NULL);
+
+	for (i = 0; i < setting_info->properties_num; i++) {
+		nm_assert (setting_info->properties[i]->property_name);
+		nm_assert (setting_info->properties[i]->setting_info == setting_info);
+		if (nm_streq (setting_info->properties[i]->property_name, property_name))
+			return setting_info->properties[i];
+	}
+
+	return NULL;
+}
+
+const NMMetaPropertyInfo *
+nm_meta_property_info_find_by_name (const char *setting_name, const char *property_name)
+{
+	const NMMetaSettingInfoEditor *setting_info;
+	const NMMetaPropertyInfo *property_info;
+
+	setting_info = nm_meta_setting_info_editor_find_by_name (setting_name, FALSE);
+	if (!setting_info)
+		return NULL;
+
+	property_info = nm_meta_setting_info_editor_get_property_info (setting_info, property_name);
+	if (!property_info)
+		return NULL;
+
+	nm_assert (property_info->setting_info == setting_info);
+
+	return property_info;
+}
+
+const NMMetaPropertyInfo *
+nm_meta_property_info_find_by_setting (NMSetting *setting, const char *property_name)
+{
+	const NMMetaSettingInfoEditor *setting_info;
+	const NMMetaPropertyInfo *property_info;
+
+	setting_info = nm_meta_setting_info_editor_find_by_setting (setting);
+	if (!setting_info)
+		return NULL;
+	property_info = nm_meta_setting_info_editor_get_property_info (setting_info, property_name);
+	if (!property_info)
+		return NULL;
+
+	nm_assert (property_info->setting_info == setting_info);
+	nm_assert (property_info == nm_meta_property_info_find_by_name (nm_setting_get_name (setting), property_name));
+
+	return property_info;
+}
+
+NMSetting *
+nm_meta_setting_info_editor_new_setting (const NMMetaSettingInfoEditor *setting_info,
+                                         NMMetaAccessorSettingInitType init_type)
+{
+	NMSetting *setting;
+
+	g_return_val_if_fail (setting_info, NULL);
+
+	setting = g_object_new (setting_info->general->get_setting_gtype (), NULL);
+
+	if (   setting_info->setting_init_fcn
+	    && init_type != NM_META_ACCESSOR_SETTING_INIT_TYPE_DEFAULT) {
+		setting_info->setting_init_fcn (setting_info,
+		                                setting,
+		                                init_type);
+	}
+
+	return setting;
+}
+
+/*****************************************************************************/
+
+const NMMetaSettingInfoEditor *const*
+nm_meta_setting_infos_editor_p (void)
+{
+	static const NMMetaSettingInfoEditor *cache[_NM_META_SETTING_TYPE_NUM + 1] = { NULL };
+	guint i;
+
+	if (G_UNLIKELY (!cache[0])) {
+		for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++)
+			cache[i] = &nm_meta_setting_infos_editor[i];
+	}
+	return cache;
+}
+
+/*****************************************************************************/
+
+const char *
+nm_meta_abstract_info_get_name (const NMMetaAbstractInfo *abstract_info, gboolean for_header)
+{
+	const char *n;
+
+	nm_assert (abstract_info);
+	nm_assert (abstract_info->meta_type);
+	nm_assert (abstract_info->meta_type->get_name);
+	n = abstract_info->meta_type->get_name (abstract_info, for_header);
+	nm_assert (n && n[0]);
+	return n;
+}
+
+const NMMetaAbstractInfo *const*
+nm_meta_abstract_info_get_nested (const NMMetaAbstractInfo *abstract_info,
+                                  guint *out_len,
+                                  gpointer *nested_to_free)
+{
+	const NMMetaAbstractInfo *const*nested;
+	guint l = 0;
+	gs_free gpointer f = NULL;
+
+	nm_assert (abstract_info);
+	nm_assert (abstract_info->meta_type);
+	nm_assert (nested_to_free && !*nested_to_free);
+
+	if (abstract_info->meta_type->get_nested) {
+		nested = abstract_info->meta_type->get_nested (abstract_info, &l, &f);
+		nm_assert ((nested ? g_strv_length ((char **) nested) : 0) == l);
+		if (nested && nested[0]) {
+			NM_SET_OUT (out_len, l);
+			*nested_to_free = g_steal_pointer (&f);
+			return nested;
+		}
+	}
+	NM_SET_OUT (out_len, 0);
+	return NULL;
+}
+
+gconstpointer
+nm_meta_abstract_info_get (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)
+{
+	nm_assert (abstract_info);
+	nm_assert (abstract_info->meta_type);
+	nm_assert (!out_to_free || !*out_to_free);
+	nm_assert (out_flags);
+
+	*out_flags = NM_META_ACCESSOR_GET_OUT_FLAGS_NONE;
+
+	if (!abstract_info->meta_type->get_fcn)
+		g_return_val_if_reached (NULL);
+
+	return abstract_info->meta_type->get_fcn (abstract_info,
+	                                          environment,
+	                                          environment_user_data,
+	                                          target,
+	                                          get_type,
+	                                          get_flags,
+	                                          out_flags,
+	                                          out_to_free);
+}
+
+const char *const*
+nm_meta_abstract_info_complete (const NMMetaAbstractInfo *abstract_info,
+                                const NMMetaEnvironment *environment,
+                                gpointer environment_user_data,
+                                const NMMetaOperationContext *operation_context,
+                                const char *text,
+                                char ***out_to_free)
+{
+	const char *const*values;
+	gsize i, j, text_len;
+
+	nm_assert (abstract_info);
+	nm_assert (abstract_info->meta_type);
+	nm_assert (out_to_free && !*out_to_free);
+
+	*out_to_free = NULL;
+
+	if (!abstract_info->meta_type->complete_fcn)
+		return NULL;
+
+	values = abstract_info->meta_type->complete_fcn (abstract_info,
+	                                                 environment,
+	                                                 environment_user_data,
+	                                                 operation_context,
+	                                                 text,
+	                                                 out_to_free);
+
+	nm_assert (!*out_to_free || values == (const char *const*) *out_to_free);
+
+	if (!values)
+		return NULL;
+
+	if (!values[0]) {
+		nm_clear_g_free (out_to_free);
+		return NULL;
+	}
+
+	if (!text || !text[0])
+		return values;
+
+	/* for convenience, we allow the complete_fcn() implementations to
+	 * ignore "text". We filter out invalid matches here. */
+
+	text_len = strlen (text);
+
+	if (*out_to_free) {
+		char **v = *out_to_free;
+
+		for (i = 0, j = 0; v[i]; i++) {
+			if (strncmp (v[i], text, text_len) != 0) {
+				g_free (v[i]);
+				continue;
+			}
+			v[j++] = v[i];
+		}
+		if (j)
+			v[j++] = NULL;
+		else {
+			g_free (v);
+			*out_to_free = v = NULL;
+		}
+		return (const char *const*) v;
+	} else {
+		const char *const*v = values;
+		char **r;
+
+		for (i = 0, j = 0; v[i]; i++) {
+			if (strncmp (v[i], text, text_len) != 0)
+				continue;
+			j++;
+		}
+		if (j == i)
+			return values;
+		else if (!j)
+			return NULL;
+
+		r = g_new (char *, j + 1);
+		v = values;
+		for (i = 0, j = 0; v[i]; i++) {
+			if (strncmp (v[i], text, text_len) != 0)
+				continue;
+			r[j++] = g_strdup (v[i]);
+		}
+		r[j++] = NULL;
+		return (const char *const*) (*out_to_free = r);
+	}
+}
+
+/*****************************************************************************/
+
+char *
+nm_meta_abstract_info_get_nested_names_str (const NMMetaAbstractInfo *abstract_info, const char *name_prefix)
+{
+	gs_free gpointer nested_to_free = NULL;
+	guint i;
+	const NMMetaAbstractInfo *const*nested;
+	GString *allowed_fields;
+
+	nested = nm_meta_abstract_info_get_nested (abstract_info, NULL, &nested_to_free);
+	if (!nested)
+		return NULL;
+
+	allowed_fields = g_string_sized_new (256);
+
+	if (!name_prefix)
+		name_prefix = nm_meta_abstract_info_get_name (abstract_info, FALSE);
+
+	for (i = 0; nested[i]; i++) {
+		g_string_append_printf (allowed_fields, "%s.%s,",
+		                        name_prefix, nm_meta_abstract_info_get_name (nested[i], FALSE));
+	}
+	g_string_truncate (allowed_fields, allowed_fields->len - 1);
+	return g_string_free (allowed_fields, FALSE);
+}
+
+char *
+nm_meta_abstract_infos_get_names_str (const NMMetaAbstractInfo *const*fields_array, const char *name_prefix)
+{
+	GString *allowed_fields;
+	guint i;
+
+	if (!fields_array || !fields_array[0])
+		return NULL;
+
+	allowed_fields = g_string_sized_new (256);
+	for (i = 0; fields_array[i]; i++) {
+		if (name_prefix)
+			g_string_append_printf (allowed_fields, "%s.", name_prefix);
+		g_string_append_printf (allowed_fields, "%s,", nm_meta_abstract_info_get_name (fields_array[i], FALSE));
+	}
+	g_string_truncate (allowed_fields, allowed_fields->len - 1);
+	return g_string_free (allowed_fields, FALSE);
+}
+
+/*****************************************************************************/
+
+typedef struct {
+	guint idx;
+	gsize self_offset_plus_1;
+	gsize sub_offset_plus_1;
+} OutputSelectionItem;
+
+static NMMetaSelectionResultList *
+_output_selection_pack (const NMMetaAbstractInfo *const* fields_array,
+                        GArray *array,
+                        GString *str)
+{
+	NMMetaSelectionResultList *result;
+	guint i;
+	guint len;
+
+	len = array ? array->len : 0;
+
+	/* re-organize the collected output data in one buffer that can be freed using
+	 * g_free(). This makes allocation more complicated, but saves us from special
+	 * handling for free. */
+	result = g_malloc0 (sizeof (NMMetaSelectionResultList) + (len * sizeof (NMMetaSelectionItem)) + (str ? str->len : 0));
+	*((guint *) &result->num) = len;
+	if (len > 0) {
+		char *pdata = &((char *) result)[sizeof (NMMetaSelectionResultList) + (len * sizeof (NMMetaSelectionItem))];
+
+		if (str)
+			memcpy (pdata, str->str, str->len);
+		for (i = 0; i < len; i++) {
+			const OutputSelectionItem *a = &g_array_index (array, OutputSelectionItem, i);
+			NMMetaSelectionItem *p = (NMMetaSelectionItem *) &result->items[i];
+
+			p->info = fields_array[a->idx];
+			p->idx = a->idx;
+			if (a->self_offset_plus_1 > 0)
+				p->self_selection = &pdata[a->self_offset_plus_1 - 1];
+			if (a->sub_offset_plus_1 > 0)
+				p->sub_selection = &pdata[a->sub_offset_plus_1 - 1];
+		}
+	}
+
+	return result;
+}
+
+static gboolean
+_output_selection_select_one (const NMMetaAbstractInfo *const* fields_array,
+                              const char *fields_prefix,
+                              const char *fields_str,
+                              gboolean validate_nested,
+                              GArray **p_array,
+                              GString **p_str,
+                              GError **error)
+{
+	guint i, j;
+	const char *i_name;
+	const char *right;
+	gboolean found = FALSE;
+	const NMMetaAbstractInfo *fields_array_failure = NULL;
+	gs_free char *fields_str_clone = NULL;
+
+	nm_assert (fields_str);
+	nm_assert (p_array);
+	nm_assert (p_str);
+	nm_assert (!error || !*error);
+
+	right = strchr (fields_str, '.');
+	if (right) {
+		fields_str_clone = g_strdup (fields_str);
+		fields_str_clone[right - fields_str] = '\0';
+		i_name = fields_str_clone;
+		right = &fields_str_clone[right - fields_str + 1];
+	} else
+		i_name = fields_str;
+
+	if (!fields_array)
+		goto not_found;
+
+	for (i = 0; fields_array[i]; i++) {
+		const NMMetaAbstractInfo *fi = fields_array[i];
+		const NMMetaAbstractInfo *const*nested;
+		gs_free gpointer nested_to_free = NULL;
+
+		if (g_ascii_strcasecmp (i_name, nm_meta_abstract_info_get_name (fi, FALSE)) != 0)
+			continue;
+
+		if (!right || !validate_nested) {
+			found = TRUE;
+			break;
+		}
+
+		nested = nm_meta_abstract_info_get_nested (fi, NULL, &nested_to_free);
+		if (nested) {
+			for (j = 0; nested[j]; nested++) {
+				if (g_ascii_strcasecmp (right, nm_meta_abstract_info_get_name (nested[j], FALSE)) == 0) {
+					found = TRUE;
+					break;
+				}
+			}
+		}
+		fields_array_failure = fields_array[i];
+		break;
+	}
+
+	if (!found) {
+not_found:
+		if (   !right
+		    && !fields_prefix
+		    && (   !g_ascii_strcasecmp (i_name, "all")
+		        || !g_ascii_strcasecmp (i_name, "common")))
+			g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("field '%s' has to be alone"), i_name);
+		else {
+			gs_free char *allowed_fields = NULL;
+
+			if (fields_array_failure) {
+				gs_free char *p = NULL;
+
+				if (fields_prefix) {
+					p = g_strdup_printf ("%s.%s", fields_prefix,
+					                     nm_meta_abstract_info_get_name (fields_array_failure, FALSE));
+				}
+				allowed_fields = nm_meta_abstract_info_get_nested_names_str (fields_array_failure, p);
+			} else
+				allowed_fields = nm_meta_abstract_infos_get_names_str (fields_array, NULL);
+
+			g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("invalid field '%s%s%s%s%s'; %s%s%s"),
+			             fields_prefix ?: "", fields_prefix ? "." : "",
+			             i_name, right ? "." : "", right ?: "",
+			             NM_PRINT_FMT_QUOTED (allowed_fields, "allowed fields: ", allowed_fields, "", "no fields"));
+		}
+		return FALSE;
+	}
+
+	{
+		GString *str;
+		OutputSelectionItem s = {
+			.idx = i,
+		};
+
+		if (!*p_str)
+			*p_str = g_string_sized_new (64);
+		str = *p_str;
+
+		s.self_offset_plus_1 = str->len + 1;
+		if (fields_prefix) {
+			g_string_append (str, fields_prefix);
+			g_string_append_c (str, '.');
+		}
+		g_string_append_len (str, i_name, strlen (i_name) + 1);
+
+		if (right) {
+			s.sub_offset_plus_1 = str->len + 1;
+			g_string_append_len (str, right, strlen (right) + 1);
+		}
+
+		if (!*p_array)
+			*p_array = g_array_new (FALSE, FALSE, sizeof (OutputSelectionItem));
+		g_array_append_val (*p_array, s);
+	}
+
+	return TRUE;
+}
+
+NMMetaSelectionResultList *
+nm_meta_selection_create_all (const NMMetaAbstractInfo *const* fields_array)
+{
+	gs_unref_array GArray *array = NULL;
+	guint i;
+
+	if (fields_array) {
+		array = g_array_new (FALSE, FALSE, sizeof (OutputSelectionItem));
+		for (i = 0; fields_array[i]; i++) {
+			OutputSelectionItem s = {
+				.idx = i,
+			};
+
+			g_array_append_val (array, s);
+		}
+	}
+
+	return _output_selection_pack (fields_array, array, NULL);
+}
+
+NMMetaSelectionResultList *
+nm_meta_selection_create_parse_one (const NMMetaAbstractInfo *const* fields_array,
+                                    const char *fields_prefix,
+                                    const char *fields_str, /* one field selector (contains no commas) and is already stripped of spaces. */
+                                    gboolean validate_nested,
+                                    GError **error)
+{
+	gs_unref_array GArray *array = NULL;
+	nm_auto_free_gstring GString *str = NULL;
+
+	g_return_val_if_fail (!error || !*error, NULL);
+	nm_assert (fields_str && !strchr (fields_str, ','));
+
+	if (!_output_selection_select_one (fields_array,
+	                                   fields_prefix,
+	                                   fields_str,
+	                                   validate_nested,
+	                                   &array,
+	                                   &str,
+	                                   error))
+		return NULL;
+	return _output_selection_pack (fields_array, array, str);
+
+}
+
+NMMetaSelectionResultList *
+nm_meta_selection_create_parse_list (const NMMetaAbstractInfo *const* fields_array,
+                                     const char *fields_prefix,
+                                     const char *fields_str, /* a comma separated list of selectors */
+                                     gboolean validate_nested,
+                                     GError **error)
+{
+	gs_unref_array GArray *array = NULL;
+	nm_auto_free_gstring GString *str = NULL;
+	gs_free char *fields_str_clone = NULL;
+	char *fields_str_cur;
+	char *fields_str_next;
+
+	g_return_val_if_fail (!error || !*error, NULL);
+
+	if (!fields_str)
+		return nm_meta_selection_create_all (fields_array);
+
+	fields_str_clone = g_strdup (fields_str);
+	for (fields_str_cur = fields_str_clone; fields_str_cur; fields_str_cur = fields_str_next) {
+		fields_str_cur = nm_str_skip_leading_spaces (fields_str_cur);
+		fields_str_next = strchr (fields_str_cur, ',');
+		if (fields_str_next)
+			*fields_str_next++ = '\0';
+
+		g_strchomp (fields_str_cur);
+		if (!fields_str_cur[0])
+			continue;
+		if (!_output_selection_select_one (fields_array,
+		                                   fields_prefix,
+		                                   fields_str_cur,
+		                                   validate_nested,
+		                                   &array,
+		                                   &str,
+		                                   error))
+			return NULL;
+	}
+
+	return _output_selection_pack (fields_array, array, str);
+}
diff --git a/clients/common/nm-meta-setting-access.h b/clients/common/nm-meta-setting-access.h
new file mode 100644
index 00000000..54fc6c84
--- /dev/null
+++ b/clients/common/nm-meta-setting-access.h
@@ -0,0 +1,101 @@
+/* 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.
+ */
+
+#ifndef _NM_META_SETTING_ACCESS_H__
+#define _NM_META_SETTING_ACCESS_H__
+
+#include "nm-meta-setting.h"
+#include "nm-meta-setting-desc.h"
+
+/*****************************************************************************/
+
+NMSetting *nm_meta_setting_info_editor_new_setting (const NMMetaSettingInfoEditor *setting_info,
+                                                    NMMetaAccessorSettingInitType init_type);
+
+const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_name (const char *setting_name, gboolean use_alias);
+const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_gtype (GType gtype);
+const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_setting (NMSetting *setting);
+
+const NMMetaPropertyInfo *nm_meta_setting_info_editor_get_property_info (const NMMetaSettingInfoEditor *setting_info,
+                                                                         const char *property_name);
+const NMMetaPropertyInfo *nm_meta_property_info_find_by_name (const char *setting_name,
+                                                              const char *property_name);
+const NMMetaPropertyInfo *nm_meta_property_info_find_by_setting (NMSetting *setting,
+                                                                 const char *property_name);
+
+/*****************************************************************************/
+
+const NMMetaSettingInfoEditor *const*nm_meta_setting_infos_editor_p (void);
+
+/*****************************************************************************/
+
+const char *nm_meta_abstract_info_get_name (const NMMetaAbstractInfo *abstract_info, gboolean for_header);
+
+const NMMetaAbstractInfo *const*nm_meta_abstract_info_get_nested (const NMMetaAbstractInfo *abstract_info,
+                                                                  guint *out_len,
+                                                                  gpointer *nested_to_free);
+
+gconstpointer nm_meta_abstract_info_get (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 char *const*nm_meta_abstract_info_complete (const NMMetaAbstractInfo *abstract_info,
+                                                  const NMMetaEnvironment *environment,
+                                                  gpointer environment_user_data,
+                                                  const NMMetaOperationContext *operation_context,
+                                                  const char *text,
+                                                  char ***out_to_free);
+
+/*****************************************************************************/
+
+char *nm_meta_abstract_info_get_nested_names_str (const NMMetaAbstractInfo *abstract_info, const char *name_prefix);
+char *nm_meta_abstract_infos_get_names_str (const NMMetaAbstractInfo *const*fields_array, const char *name_prefix);
+
+/*****************************************************************************/
+
+typedef struct {
+	const NMMetaAbstractInfo *info;
+	const char *self_selection;
+	const char *sub_selection;
+	guint idx;
+} NMMetaSelectionItem;
+
+typedef struct {
+	const guint num;
+	const NMMetaSelectionItem items[];
+} NMMetaSelectionResultList;
+
+NMMetaSelectionResultList *nm_meta_selection_create_all (const NMMetaAbstractInfo *const* fields_array);
+NMMetaSelectionResultList *nm_meta_selection_create_parse_one (const NMMetaAbstractInfo *const* fields_array,
+                                                               const char *fields_prefix,
+                                                               const char *fields_str,
+                                                               gboolean validate_nested,
+                                                               GError **error);
+NMMetaSelectionResultList *nm_meta_selection_create_parse_list (const NMMetaAbstractInfo *const* fields_array,
+                                                                const char *fields_prefix,
+                                                                const char *fields_str,
+                                                                gboolean validate_nested,
+                                                                GError **error);
+
+#endif /* _NM_META_SETTING_ACCESS_H__ */
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 (&gtype_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",
+};
diff --git a/clients/common/nm-meta-setting-desc.h b/clients/common/nm-meta-setting-desc.h
new file mode 100644
index 00000000..e61b1fc4
--- /dev/null
+++ b/clients/common/nm-meta-setting-desc.h
@@ -0,0 +1,444 @@
+/* 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.
+ */
+
+#ifndef __NM_META_SETTING_DESC_H__
+#define __NM_META_SETTING_DESC_H__
+
+#include "nm-utils/nm-obj.h"
+#include "nm-meta-setting.h"
+
+struct _NMDevice;
+
+#define NM_META_TEXT_HIDDEN N_("<hidden>")
+
+#define NM_META_TEXT_PROMPT_ADSL_PROTO N_("Protocol")
+#define NM_META_TEXT_PROMPT_ADSL_PROTO_CHOICES "(" NM_SETTING_ADSL_PROTOCOL_PPPOA "/" NM_SETTING_ADSL_PROTOCOL_PPPOE "/" NM_SETTING_ADSL_PROTOCOL_IPOATM ")"
+
+#define NM_META_TEXT_PROMPT_ADSL_ENCAP N_("ADSL encapsulation")
+#define NM_META_TEXT_PROMPT_ADSL_ENCAP_CHOICES "(" NM_SETTING_ADSL_ENCAPSULATION_VCMUX "/" NM_SETTING_ADSL_ENCAPSULATION_LLC ") [none]"
+
+#define NM_META_TEXT_PROMPT_CON_TYPE    N_("Connection type")
+#define NM_META_TEXT_PROMPT_IFNAME      N_("Interface name [*]")
+#define NM_META_TEXT_PROMPT_VPN_TYPE    N_("VPN type")
+#define NM_META_TEXT_PROMPT_MASTER      N_("Master")
+
+#define NM_META_TEXT_PROMPT_IB_MODE     N_("Transport mode")
+#define NM_META_TEXT_WORD_DATAGRAM  "datagram"
+#define NM_META_TEXT_WORD_CONNECTED "connected"
+#define NM_META_TEXT_PROMPT_IB_MODE_CHOICES "(" NM_META_TEXT_WORD_DATAGRAM "/" NM_META_TEXT_WORD_CONNECTED ") [" NM_META_TEXT_WORD_DATAGRAM "]"
+
+#define NM_META_TEXT_PROMPT_BT_TYPE N_("Bluetooth type")
+#define NM_META_TEXT_WORD_PANU      "panu"
+#define NM_META_TEXT_WORD_NAP       "nap"
+#define NM_META_TEXT_WORD_DUN_GSM   "dun-gsm"
+#define NM_META_TEXT_WORD_DUN_CDMA  "dun-cdma"
+#define NM_META_TEXT_PROMPT_BT_TYPE_CHOICES "(" NM_META_TEXT_WORD_PANU "/" NM_META_TEXT_WORD_NAP "/" NM_META_TEXT_WORD_DUN_GSM "/" NM_META_TEXT_WORD_DUN_CDMA ") [" NM_META_TEXT_WORD_PANU "]"
+
+#define NM_META_TEXT_PROMPT_BOND_MODE N_("Bonding mode")
+
+#define NM_META_TEXT_PROMPT_BOND_MON_MODE N_("Bonding monitoring mode")
+#define NM_META_TEXT_WORD_MIIMON "miimon"
+#define NM_META_TEXT_WORD_ARP    "arp"
+#define NM_META_TEXT_PROMPT_BOND_MON_MODE_CHOICES "(" NM_META_TEXT_WORD_MIIMON "/" NM_META_TEXT_WORD_ARP ") [" NM_META_TEXT_WORD_MIIMON "]"
+
+#define NM_META_TEXT_PROMPT_WIFI_MODE N_("Wi-Fi mode")
+#define NM_META_TEXT_WORD_INFRA  "infrastructure"
+#define NM_META_TEXT_WORD_AP     "ap"
+#define NM_META_TEXT_WORD_ADHOC  "adhoc"
+#define NM_META_TEXT_PROMPT_WIFI_MODE_CHOICES "(" NM_META_TEXT_WORD_INFRA "/" NM_META_TEXT_WORD_AP "/" NM_META_TEXT_WORD_ADHOC ") [" NM_META_TEXT_WORD_INFRA "]"
+
+#define NM_META_TEXT_PROMPT_TUN_MODE N_("Tun mode")
+#define NM_META_TEXT_WORD_TUN  "tun"
+#define NM_META_TEXT_WORD_TAP  "tap"
+#define NM_META_TEXT_PROMPT_TUN_MODE_CHOICES "(" NM_META_TEXT_WORD_TUN "/" NM_META_TEXT_WORD_TAP ") [" NM_META_TEXT_WORD_TUN "]"
+
+#define NM_META_TEXT_PROMPT_IP_TUNNEL_MODE N_("IP Tunnel mode")
+
+#define NM_META_TEXT_PROMPT_MACVLAN_MODE N_("MACVLAN mode")
+
+#define NM_META_TEXT_PROMPT_MACSEC_MODE N_("MACsec mode")
+#define NM_META_TEXT_WORD_PSK "psk"
+#define NM_META_TEXT_WORD_EAP "eap"
+#define NM_META_TEXT_PROMPT_MACSEC_MODE_CHOICES "(" NM_META_TEXT_WORD_PSK "/" NM_META_TEXT_WORD_EAP ")"
+
+#define NM_META_TEXT_PROMPT_PROXY_METHOD N_("Proxy method")
+#define NM_META_TEXT_WORD_NONE "none"
+#define NM_META_TEXT_WORD_AUTO "auto"
+#define NM_META_TEXT_PROMPT_PROXY_METHOD_CHOICES "(" NM_META_TEXT_WORD_NONE "/" NM_META_TEXT_WORD_AUTO ") [" NM_META_TEXT_WORD_NONE "]"
+
+typedef enum {
+	NM_META_TERM_COLOR_NORMAL  = 0,
+	NM_META_TERM_COLOR_BLACK   = 1,
+	NM_META_TERM_COLOR_RED     = 2,
+	NM_META_TERM_COLOR_GREEN   = 3,
+	NM_META_TERM_COLOR_YELLOW  = 4,
+	NM_META_TERM_COLOR_BLUE    = 5,
+	NM_META_TERM_COLOR_MAGENTA = 6,
+	NM_META_TERM_COLOR_CYAN    = 7,
+	NM_META_TERM_COLOR_WHITE   = 8,
+} NMMetaTermColor;
+
+typedef enum {
+	NM_META_TERM_FORMAT_NORMAL     = 0,
+	NM_META_TERM_FORMAT_BOLD       = 1,
+	NM_META_TERM_FORMAT_DIM        = 2,
+	NM_META_TERM_FORMAT_UNDERLINE  = 3,
+	NM_META_TERM_FORMAT_BLINK      = 4,
+	NM_META_TERM_FORMAT_REVERSE    = 5,
+	NM_META_TERM_FORMAT_HIDDEN     = 6,
+} NMMetaTermFormat;
+
+typedef enum {
+	NM_META_ACCESSOR_GET_TYPE_PRETTY,
+	NM_META_ACCESSOR_GET_TYPE_PARSABLE,
+	NM_META_ACCESSOR_GET_TYPE_TERMFORMAT,
+} NMMetaAccessorGetType;
+
+typedef enum {
+	NM_META_ACCESSOR_SETTING_INIT_TYPE_DEFAULT,
+	NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI,
+} NMMetaAccessorSettingInitType;
+
+static inline void
+nm_meta_termformat_unpack (gconstpointer value, NMMetaTermColor *out_color, NMMetaTermFormat *out_format)
+{
+	/* get_fcn() with NM_META_ACCESSOR_GET_TYPE_TERMFORMAT returns a pointer
+	 * that encodes NMMetaTermColor and NMMetaTermFormat. Unpack it. */
+	if (!value) {
+		/* by default, objects that don't support NM_META_ACCESSOR_GET_TYPE_TERMFORMAT
+		 * return NULL. This allows for an explicit fallback value here... */
+		NM_SET_OUT (out_color, NM_META_TERM_COLOR_NORMAL);
+		NM_SET_OUT (out_format, NM_META_TERM_FORMAT_NORMAL);
+	} else {
+		NM_SET_OUT (out_color, GPOINTER_TO_UINT (value) & 0xFF);
+		NM_SET_OUT (out_format, (GPOINTER_TO_UINT (value) & 0xFF00) >> 8);
+	}
+}
+
+static inline gconstpointer
+nm_meta_termformat_pack (NMMetaTermColor color, NMMetaTermFormat format)
+{
+	/* get_fcn() with NM_META_ACCESSOR_GET_TYPE_TERMFORMAT returns a pointer
+	 * that encodes NMMetaTermColor and NMMetaTermFormat. Pack it. */
+	return GUINT_TO_POINTER (((guint) 0x10000) | (((guint) color) & 0xFFu) | ((((guint) format) & 0xFFu) << 8));
+}
+
+#define NM_META_TERMFORMAT_DEFAULT() (nm_meta_termformat_pack (NM_META_TERM_COLOR_NORMAL, NM_META_TERM_FORMAT_NORMAL))
+
+typedef enum {
+	NM_META_ACCESSOR_GET_FLAGS_NONE                                         = 0,
+	NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV                                  = (1LL <<  0),
+	NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS                                 = (1LL <<  1),
+} NMMetaAccessorGetFlags;
+
+typedef enum {
+	NM_META_ACCESSOR_GET_OUT_FLAGS_NONE                                     = 0,
+	NM_META_ACCESSOR_GET_OUT_FLAGS_STRV                                     = (1LL <<  0),
+} NMMetaAccessorGetOutFlags;
+
+typedef enum {
+	NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC                       = (1LL <<  0),
+	NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC_HEX                   = (1LL <<  1),
+	NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT                          = (1LL <<  2),
+	NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT_L10N                     = (1LL <<  3),
+	NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC                     = (1LL <<  4),
+	NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC_HEX                 = (1LL <<  5),
+	NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT                        = (1LL <<  6),
+} NMMetaPropertyTypFlags;
+
+typedef enum {
+	NM_META_PROPERTY_TYPE_MAC_MODE_DEFAULT,
+	NM_META_PROPERTY_TYPE_MAC_MODE_CLONED,
+	NM_META_PROPERTY_TYPE_MAC_MODE_INFINIBAND,
+} NMMetaPropertyTypeMacMode;
+
+typedef struct _NMMetaEnvironment           NMMetaEnvironment;
+typedef struct _NMMetaType                  NMMetaType;
+typedef struct _NMMetaAbstractInfo          NMMetaAbstractInfo;
+typedef struct _NMMetaSettingInfoEditor     NMMetaSettingInfoEditor;
+typedef struct _NMMetaPropertyInfo          NMMetaPropertyInfo;
+typedef struct _NMMetaPropertyType          NMMetaPropertyType;
+typedef struct _NMMetaPropertyTypData       NMMetaPropertyTypData;
+typedef struct _NMMetaOperationContext      NMMetaOperationContext;
+typedef struct _NMMetaNestedPropertyInfo    NMMetaNestedPropertyInfo;
+typedef struct _NMMetaPropertyTypDataNested NMMetaPropertyTypDataNested;
+
+/* this gives some context information for virtual functions.
+ * This command actually violates layering, and should be considered
+ * a hack. In the future, try to replace it's use. */
+struct _NMMetaOperationContext {
+	NMConnection *connection;
+};
+
+struct _NMMetaPropertyType {
+
+	/* should return a translated string */
+	const char *(*describe_fcn) (const NMMetaPropertyInfo *property_info,
+	                             char **out_to_free);
+
+	gconstpointer (*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);
+	gboolean (*set_fcn) (const NMMetaPropertyInfo *property_info,
+	                     const NMMetaEnvironment *environment,
+	                     gpointer environment_user_data,
+	                     NMSetting *setting,
+	                     const char *value,
+	                     GError **error);
+	gboolean (*remove_fcn) (const NMMetaPropertyInfo *property_info,
+	                        const NMMetaEnvironment *environment,
+	                        gpointer environment_user_data,
+	                        NMSetting *setting,
+	                        const char *option,
+	                        guint32 idx,
+	                        GError **error);
+
+	const char *const*(*values_fcn) (const NMMetaPropertyInfo *property_info,
+	                                 char ***out_to_free);
+
+	const char *const*(*complete_fcn) (const NMMetaPropertyInfo *property_info,
+	                                   const NMMetaEnvironment *environment,
+	                                   gpointer environment_user_data,
+	                                   const NMMetaOperationContext *operation_context,
+	                                   const char *text,
+	                                   char ***out_to_free);
+};
+
+struct _NMUtilsEnumValueInfo;
+
+typedef struct {
+	const char *nick;
+	gint64 value;
+} NMMetaUtilsIntValueInfo;
+
+struct _NMMetaPropertyTypData {
+	union {
+		struct {
+			gboolean (*fcn) (NMSetting *setting);
+		} get_with_default;
+		struct {
+			GType (*get_gtype) (void);
+			int min;
+			int max;
+			const struct _NMUtilsEnumValueInfo *value_infos;
+			void (*pre_set_notify) (const NMMetaPropertyInfo *property_info,
+			                        const NMMetaEnvironment *environment,
+			                        gpointer environment_user_data,
+			                        NMSetting *setting,
+			                        int value);
+		} gobject_enum;
+		struct {
+			gint64 min;
+			gint64 max;
+			guint base;
+			const NMMetaUtilsIntValueInfo *value_infos;
+		} gobject_int;
+		struct {
+			const char *(*validate_fcn) (const char *value, char **out_to_free, GError **error);
+		} gobject_string;
+		struct {
+			guint32 (*get_fcn) (NMSetting *setting);
+		} mtu;
+		struct {
+			NMMetaPropertyTypeMacMode mode;
+		} mac;
+	} subtype;
+	const char *const*values_static;
+	const NMMetaPropertyTypDataNested *nested;
+	NMMetaPropertyTypFlags typ_flags;
+};
+
+typedef enum {
+	NM_META_PROPERTY_INF_FLAG_NONE                      = 0x00,
+	NM_META_PROPERTY_INF_FLAG_REQD                      = 0x01, /* Don't ask to ask. */
+	NM_META_PROPERTY_INF_FLAG_DONT_ASK                  = 0x02, /* Don't ask interactively by default */
+	NM_META_PROPERTY_INF_FLAG_MULTI                     = 0x04, /* Ask multiple times, do an append instead of set. */
+} NMMetaPropertyInfFlags;
+
+enum {
+	_NM_META_PROPERTY_TYPE_VPN_SERVICE_TYPE                                 = 0,
+	_NM_META_PROPERTY_TYPE_CONNECTION_TYPE                                  = 3,
+};
+
+#define nm_meta_property_info_connection_type  (nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_CONNECTION].properties[_NM_META_PROPERTY_TYPE_CONNECTION_TYPE])
+#define nm_meta_property_info_vpn_service_type (nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_VPN].properties[_NM_META_PROPERTY_TYPE_VPN_SERVICE_TYPE])
+
+struct _NMMetaPropertyInfo {
+	union {
+		NMObjBaseInst parent;
+		const NMMetaType *meta_type;
+	};
+
+	const NMMetaSettingInfoEditor *setting_info;
+
+	const char *property_name;
+
+	const char *property_alias;
+
+	NMMetaPropertyInfFlags inf_flags;
+	bool is_secret:1;
+
+	bool is_cli_option:1;
+
+	const char *prompt;
+
+	const char *def_hint;
+
+	const char *describe_doc;
+
+	/* a non-translated but translatable static description (marked with N_()). */
+	const char *describe_message;
+
+	const NMMetaPropertyType    *property_type;
+	const NMMetaPropertyTypData *property_typ_data;
+};
+
+typedef struct _NMMetaSettingValidPartItem {
+	const NMMetaSettingInfoEditor *setting_info;
+	bool mandatory;
+} NMMetaSettingValidPartItem;
+
+struct _NMMetaSettingInfoEditor {
+	union {
+		NMObjBaseInst parent;
+		const NMMetaType *meta_type;
+	};
+	const NMMetaSettingInfo *general;
+	const char *alias;
+	const char *pretty_name;
+	const NMMetaPropertyInfo *const*properties;
+	guint properties_num;
+
+	/* a NMConnection has a main type (connection.type), which is a
+	 * main NMSetting instance. Depending on the type, a connection
+	 * may have a list of other allowed settings.
+	 *
+	 * For example, a connection of type "vlan" may have settings
+	 * of type "connection", "vlan", and "wired".
+	 *
+	 * Some setting types a not a main type (NMSettingProxy). They
+	 * don't have valid_settings but are usually referenced by other
+	 * settings to be valid for them. */
+	const NMMetaSettingValidPartItem *const*valid_parts;
+
+	void (*setting_init_fcn) (const NMMetaSettingInfoEditor *setting_info,
+	                          NMSetting *setting,
+	                          NMMetaAccessorSettingInitType init_type);
+};
+
+struct _NMMetaType {
+	NMObjBaseClass parent;
+	const char *type_name;
+	const char *(*get_name) (const NMMetaAbstractInfo *abstract_info,
+	                         gboolean for_header);
+	const NMMetaAbstractInfo *const*(*get_nested) (const NMMetaAbstractInfo *abstract_info,
+	                                               guint *out_len,
+	                                               gpointer *out_to_free);
+	gconstpointer (*get_fcn) (const NMMetaAbstractInfo *info,
+	                          const NMMetaEnvironment *environment,
+	                          gpointer environment_user_data,
+	                          gpointer target,
+	                          NMMetaAccessorGetType get_type,
+	                          NMMetaAccessorGetFlags get_flags,
+	                          NMMetaAccessorGetOutFlags *out_flags,
+	                          gpointer *out_to_free);
+	const char *const*(*complete_fcn) (const NMMetaAbstractInfo *info,
+	                                   const NMMetaEnvironment *environment,
+	                                   gpointer environment_user_data,
+	                                   const NMMetaOperationContext *operation_context,
+	                                   const char *text,
+	                                   char ***out_to_free);
+};
+
+struct _NMMetaAbstractInfo {
+	union {
+		NMObjBaseInst parent;
+		const NMMetaType *meta_type;
+	};
+};
+
+extern const NMMetaType nm_meta_type_setting_info_editor;
+extern const NMMetaType nm_meta_type_property_info;
+
+extern const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[_NM_META_SETTING_TYPE_NUM];
+
+extern const NMMetaSettingValidPartItem *const nm_meta_setting_info_valid_parts_default[];
+
+const NMMetaSettingValidPartItem *const*nm_meta_setting_info_valid_parts_for_slave_type (const char *slave_type, const char **out_slave_name);
+
+/*****************************************************************************/
+
+typedef enum {
+	NM_META_ENV_WARN_LEVEL_INFO,
+	NM_META_ENV_WARN_LEVEL_WARN,
+} NMMetaEnvWarnLevel;
+
+/* the settings-meta data is supposed to be independent of an actual client
+ * implementation. Hence, there is a need for hooks to the meta-data.
+ * The meta-data handlers may call back to the enviroment with certain
+ * actions. */
+struct _NMMetaEnvironment {
+
+	void (*warn_fcn) (const NMMetaEnvironment *environment,
+	                  gpointer environment_user_data,
+	                  NMMetaEnvWarnLevel warn_level,
+	                  const char *fmt_l10n, /* the untranslated format string, but it is marked for translation using N_(). */
+	                  va_list ap);
+
+	struct _NMDevice *const*(*get_nm_devices) (const NMMetaEnvironment *environment,
+	                                           gpointer environment_user_data,
+	                                           guint *out_len);
+
+	struct _NMRemoteConnection *const*(*get_nm_connections) (const NMMetaEnvironment *environment,
+	                                                         gpointer environment_user_data,
+	                                                         guint *out_len);
+
+};
+
+/*****************************************************************************/
+
+/* NMSettingBond is special in that it has nested properties.
+ * We will add API to proper handle such types (Bond, VPN, User),
+ * but for now just expose the type info directly. */
+
+extern const NMMetaType nm_meta_type_nested_property_info;
+
+struct _NMMetaNestedPropertyInfo  {
+	union {
+		const NMMetaType *meta_type;
+		NMMetaPropertyInfo base;
+	};
+	const NMMetaPropertyInfo *parent_info;
+};
+
+struct _NMMetaPropertyTypDataNested  {
+	const NMMetaNestedPropertyInfo *nested;
+	guint nested_len;
+};
+
+const NMMetaPropertyTypDataNested nm_meta_property_typ_data_bond;
+
+/*****************************************************************************/
+
+#endif /* __NM_META_SETTING_DESC_H__ */
diff --git a/clients/common/nm-secret-agent-simple.c b/clients/common/nm-secret-agent-simple.c
index b763bf89..4ef1be23 100644
--- a/clients/common/nm-secret-agent-simple.c
+++ b/clients/common/nm-secret-agent-simple.c
@@ -33,6 +33,8 @@
 
 #include <string.h>
 
+#include "nm-utils/nm-hash-utils.h"
+
 #include "NetworkManager.h"
 #include "nm-vpn-service-plugin.h"
 
@@ -86,7 +88,7 @@ nm_secret_agent_simple_init (NMSecretAgentSimple *agent)
 {
 	NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (agent);
 
-	priv->requests = g_hash_table_new_full (g_str_hash, g_str_equal,
+	priv->requests = g_hash_table_new_full (nm_str_hash, g_str_equal,
 	                                        g_free, nm_secret_agent_simple_request_free);
 }
 
@@ -399,20 +401,20 @@ add_vpn_secrets (NMSecretAgentSimpleRequest *request,
 {
 	NMSettingVpn *s_vpn = nm_connection_get_setting_vpn (request->connection);
 	const VpnPasswordName *secret_names, *p;
-	char *tmp = NULL;
+	const char *vpn_msg = NULL;
 	char **iter;
 
 	/* If hints are given, then always ask for what the hints require */
-	if (request->hints && g_strv_length (request->hints)) {
-		for (iter = request->hints; iter && *iter; iter++) {
-			if (!tmp && g_str_has_prefix (*iter, VPN_MSG_TAG))
-				tmp = g_strdup (*iter + strlen (VPN_MSG_TAG));
+	if (request->hints) {
+		for (iter = request->hints; *iter; iter++) {
+			if (!vpn_msg && g_str_has_prefix (*iter, VPN_MSG_TAG))
+				vpn_msg = &(*iter)[NM_STRLEN (VPN_MSG_TAG)];
 			else
 				add_vpn_secret_helper (secrets, s_vpn, *iter, *iter);
 		}
 	}
-	if (msg)
-		*msg = g_strdup (tmp);
+
+	NM_SET_OUT (msg, g_strdup (vpn_msg));
 
 	/* Now add what client thinks might be required, because hints may be empty or incomplete */
 	p = secret_names = nm_vpn_get_secret_names (nm_setting_vpn_get_service_type (s_vpn));
@@ -543,23 +545,30 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request)
 		                                            TRUE);
 		g_ptr_array_add (secrets, secret);
 	} else if (nm_connection_is_type (request->connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
-		NMSetting *setting;
-
-		setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_GSM_SETTING_NAME);
-		if (!setting)
-			setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_CDMA_SETTING_NAME);
+		NMSetting *setting = NULL;
+
+		setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_BLUETOOTH_SETTING_NAME);
+		if (   setting
+		    && !nm_streq0 (nm_setting_bluetooth_get_connection_type (NM_SETTING_BLUETOOTH (setting)), NM_SETTING_BLUETOOTH_TYPE_NAP)) {
+			setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_GSM_SETTING_NAME);
+			if (!setting)
+				setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_CDMA_SETTING_NAME);
+		}
 
-		title = _("Mobile broadband network password");
-		msg = g_strdup_printf (_("A password is required to connect to '%s'."),
-		                       nm_connection_get_id (request->connection));
+		if (setting) {
+			title = _("Mobile broadband network password");
+			msg = g_strdup_printf (_("A password is required to connect to '%s'."),
+			                       nm_connection_get_id (request->connection));
 
-		secret = nm_secret_agent_simple_secret_new (_("Password"),
-		                                            setting,
-		                                            "password",
-		                                            NULL,
-		                                            NULL,
-		                                            TRUE);
-		g_ptr_array_add (secrets, secret);
+			secret = nm_secret_agent_simple_secret_new (_("Password"),
+			                                            setting,
+			                                            "password",
+			                                            NULL,
+			                                            NULL,
+			                                            TRUE);
+			g_ptr_array_add (secrets, secret);
+		} else
+			ok = FALSE;
 	} else if (nm_connection_is_type (request->connection, NM_SETTING_VPN_SETTING_NAME)) {
 		NMSettingConnection *s_con;
 
@@ -576,6 +585,15 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request)
 		ok = FALSE;
 
 	if (!ok) {
+		gs_free_error GError *error = NULL;
+
+		error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED,
+		                     "Cannot service a secrets request %s for a %s connection",
+		                     request->request_id,
+		                     nm_connection_get_connection_type (request->connection));
+		request->callback (NM_SECRET_AGENT_OLD (request->self), request->connection,
+		                   NULL, error, request->callback_data);
+		g_hash_table_remove (priv->requests, request->request_id);
 		g_ptr_array_unref (secrets);
 		return;
 	}
@@ -678,7 +696,7 @@ nm_secret_agent_simple_response (NMSecretAgentSimple *self,
 
 		g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}"));
 
-		settings = g_hash_table_new (g_str_hash, g_str_equal);
+		settings = g_hash_table_new (nm_str_hash, g_str_equal);
 		for (i = 0; i < secrets->len; i++) {
 			NMSecretAgentSimpleSecretReal *secret = secrets->pdata[i];
 
@@ -730,7 +748,12 @@ nm_secret_agent_simple_cancel_get_secrets (NMSecretAgentOld *agent,
                                            const gchar      *connection_path,
                                            const gchar      *setting_name)
 {
-	/* We don't support cancellation. Sorry! */
+	NMSecretAgentSimple *self = NM_SECRET_AGENT_SIMPLE (agent);
+	NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self);
+	gs_free char *request_id = NULL;
+
+	request_id = g_strdup_printf ("%s/%s", connection_path, setting_name);
+	g_hash_table_remove (priv->requests, request_id);
 }
 
 static void
diff --git a/clients/common/nm-vpn-helpers.c b/clients/common/nm-vpn-helpers.c
index d2bb8cba..15611c45 100644
--- a/clients/common/nm-vpn-helpers.c
+++ b/clients/common/nm-vpn-helpers.c
@@ -115,22 +115,33 @@ nm_vpn_supports_ipv6 (NMConnection *connection)
 const VpnPasswordName *
 nm_vpn_get_secret_names (const char *service_type)
 {
+	static const VpnPasswordName const generic_vpn_secrets[] = {
+		{ "password", N_("Password") },
+		{ 0 }
+	};
+	static const VpnPasswordName const openvpn_secrets[] = {
+		{ "password", N_("Password") },
+		{ "cert-pass", N_("Certificate password") },
+		{ "http-proxy-password", N_("HTTP proxy password") },
+		{ 0 }
+	};
+	static const VpnPasswordName const vpnc_secrets[] = {
+		{ "Xauth password", N_("Password") },
+		{ "IPSec secret", N_("Group password") },
+		{ 0 }
+	};
+	static const VpnPasswordName const swan_secrets[] = {
+		{ "xauthpassword", N_("Password") },
+		{ "pskvalue", N_("Group password") },
+		{ 0 }
+	};
+	static const VpnPasswordName const openconnect_secrets[] = {
+		{ "gateway", N_("Gateway") },
+		{ "cookie", N_("Cookie") },
+		{ "gwcert", N_("Gateway certificate hash") },
+		{ 0 }
+	};
 	const char *type;
-	static VpnPasswordName generic_vpn_secrets[] = { {"password", N_("Password")}, {NULL, NULL} };
-	static VpnPasswordName openvpn_secrets[] = { {"password", N_("Password")},
-	                                             {"cert-pass", N_("Certificate password")},
-	                                             {"http-proxy-password", N_("HTTP proxy password")},
-	                                             {NULL, NULL} };
-	static VpnPasswordName vpnc_secrets[] = { {"Xauth password", N_("Password")},
-	                                          {"IPSec secret", N_("Group password")},
-	                                          {NULL, NULL} };
-	static VpnPasswordName swan_secrets[] = { {"xauthpassword", N_("Password")},
-	                                          {"pskvalue", N_("Group password")},
-	                                          {NULL, NULL} };
-	static VpnPasswordName openconnect_secrets[] = { {"gateway", N_("Gateway")},
-	                                                 {"cookie", N_("Cookie")},
-	                                                 {"gwcert", N_("Gateway certificate hash")},
-	                                                 {NULL, NULL} };
 
 	if (!service_type)
 		return NULL;
diff --git a/clients/common/settings-docs.c b/clients/common/settings-docs.c
new file mode 100644
index 00000000..b523a394
--- /dev/null
+++ b/clients/common/settings-docs.c
@@ -0,0 +1,363 @@
+/* Generated file. Do not edit. */
+
+#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_CHANNEL N_("Channel on which the mesh network to join is located.")
+#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS N_("Anycast DHCP MAC address used when requesting an IP address via DHCP. The specific anycast address used determines which DHCP server class answers the request.")
+#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_SSID N_("SSID of the mesh network to join.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_BAND N_("802.11 frequency band of the network.  One of \"a\" for 5GHz 802.11a or \"bg\" for 2.4GHz 802.11.  This will lock associations to the Wi-Fi network to the specific band, i.e. if \"a\" is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible.  This setting depends on specific driver capability and may not work with all drivers.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_BSSID N_("If specified, directs the device to only associate with the given access point.  This capability is highly driver dependent and not supported by all devices.  Note: this property does not control the BSSID used when creating an Ad-Hoc network and is unlikely to in the future.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_CHANNEL N_("Wireless channel to use for the Wi-Fi connection.  The device will only join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel.  Because channel numbers overlap between bands, this property also requires the \"band\" property to be set.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS N_("If specified, request that the device use this MAC address instead. This is known as MAC cloning or spoofing. Beside explicitly specifying a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address of the device. \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"preserve\" (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK N_("With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting \"FE:FF:FF:00:00:00\" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the \"random\" or \"stable\" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of \"FE:FF:FF:00:00:00 68:F7:28:00:00:00\" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of \"02:00:00:00:00:00 00:00:00:00:00:00\" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, \"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00\" will create a fully scrambled MAC address, randomly locally or globally administered.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_HIDDEN N_("If TRUE, indicates this network is a non-broadcasting network that hides its SSID.  In this case various workarounds may take place, such as probe-scanning the SSID for more reliable network discovery.  However, these workarounds expose inherent insecurities with hidden SSID networks, and thus hidden SSID networks should be used with caution.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MAC_ADDRESS N_("If specified, this connection will only apply to the Wi-Fi device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST N_("A list of permanent MAC addresses of Wi-Fi devices to which this connection should never apply.  Each MAC address should be given in the standard hex-digits-and-colons notation (eg \"00:11:22:33:44:55\").")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION N_("One of NM_SETTING_MAC_RANDOMIZATION_DEFAULT (0) (never randomize unless the user has set a global default to randomize and the supplicant supports randomization),  NM_SETTING_MAC_RANDOMIZATION_NEVER (1) (never randomize the MAC address), or NM_SETTING_MAC_RANDOMIZATION_ALWAYS (2) (always randomize the MAC address). This property is deprecated for 'cloned-mac-address'. Deprecated: 1")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MODE N_("Wi-Fi network mode; one of \"infrastructure\", \"adhoc\" or \"ap\".  If blank, infrastructure is assumed.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_POWERSAVE N_("One of NM_SETTING_WIRELESS_POWERSAVE_DISABLE (2) (disable Wi-Fi power saving), NM_SETTING_WIRELESS_POWERSAVE_ENABLE (3) (enable Wi-Fi power saving), NM_SETTING_WIRELESS_POWERSAVE_IGNORE (1) (don't touch currently configure setting) or NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (0) (use the globally configured value). All other values are reserved.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_RATE N_("If non-zero, directs the device to only use the specified bitrate for communication with the access point.  Units are in Kb/s, ie 5500 = 5.5 Mbit/s.  This property is highly driver dependent and not all devices support setting a static bitrate.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SEEN_BSSIDS N_("A list of BSSIDs (each BSSID formatted as a MAC address like \"00:11:22:33:44:55\") that have been detected as part of the Wi-Fi network.  NetworkManager internally tracks previously seen BSSIDs. The property is only meant for reading and reflects the BSSID list of NetworkManager. The changes you make to this property will not be preserved.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SSID N_("SSID of the Wi-Fi network. Must be specified.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_TX_POWER N_("If non-zero, directs the device to use the specified transmit power. Units are dBm.  This property is highly driver dependent and not all devices support setting a static transmit power.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_AUTH_ALG N_("When WEP is used (ie, key-mgmt = \"none\" or \"ieee8021x\") indicate the 802.11 authentication algorithm required by the AP here.  One of \"open\" for Open System, \"shared\" for Shared Key, or \"leap\" for Cisco LEAP.  When using Cisco LEAP (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\") the \"leap-username\" and \"leap-password\" properties must be specified.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_GROUP N_("A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list.  For maximum compatibility leave this property empty.  Each list element may be one of \"wep40\", \"wep104\", \"tkip\", or \"ccmp\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_KEY_MGMT N_("Key management used for the connection.  One of \"none\" (WEP), \"ieee8021x\" (Dynamic WEP), \"wpa-none\" (Ad-Hoc WPA-PSK), \"wpa-psk\" (infrastructure WPA-PSK), or \"wpa-eap\" (WPA-Enterprise).  This property must be set for any Wi-Fi connection that uses security.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD N_("The login password for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS N_("Flags indicating how to handle the \"leap-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME N_("The login username for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PAIRWISE N_("A list of pairwise encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty.  Each list element may be one of \"tkip\" or \"ccmp\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PMF N_("Indicates whether Protected Management Frames (802.11w) must be enabled for the connection.  One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable PMF), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail if not supported).  When set to NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no global default is set, PMF will be optionally enabled.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PROTO N_("List of strings specifying the allowed WPA protocol versions to use. Each element may be one \"wpa\" (allow WPA) or \"rsn\" (allow WPA2/RSN).  If not specified, both WPA and RSN connections are allowed.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK N_("Pre-Shared-Key for WPA networks.  If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key.  Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS N_("Flags indicating how to handle the \"psk\" property.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS N_("Flags indicating how to handle the \"wep-key0\", \"wep-key1\", \"wep-key2\", and \"wep-key3\" properties.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE N_("Controls the interpretation of WEP keys.  Allowed values are NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character hexadecimal string, or a 5- or 13-character ASCII password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a string and will be hashed using the de-facto MD5 method to derive the actual WEP key.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY0 N_("Index 0 WEP key.  This is the WEP key used in most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY1 N_("Index 1 WEP key.  This WEP index is not used by most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY2 N_("Index 2 WEP key.  This WEP index is not used by most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY3 N_("Index 3 WEP key.  This WEP index is not used by most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX N_("When static WEP is used (ie, key-mgmt = \"none\") and a non-default WEP key index is used by the AP, put that WEP key index here.  Valid values are 0 (default key) through 3.  Note that some consumer access points (like the Linksys WRT54G) number the keys 1 - 4.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WPS_METHOD N_("Flags indicating which mode of WPS is to be used if any. There's little point in changing the default setting as NetworkManager will automatically determine whether it's feasible to start WPS enrollment from the Access Point capabilities. WPS can be disabled by setting this property to a value of 1.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_ALTSUBJECT_MATCHES N_("List of strings to be matched against the altSubjectName of the certificate presented by the authentication server. If the list is empty, no verification of the server certificate's altSubjectName is performed.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_ANONYMOUS_IDENTITY N_("Anonymous identity string for EAP authentication methods.  Used as the unencrypted identity with EAP types that support different tunneled identity like EAP-TTLS.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_AUTH_TIMEOUT N_("A timeout for the authentication. Zero means the global default; if the global default is not set, the authentication timeout is 25 seconds.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT N_("Contains the CA certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT_PASSWORD N_("The password used to access the CA certificate stored in \"ca-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"ca-cert-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_PATH N_("UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"ca-cert\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT N_("Contains the client certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD N_("The password used to access the client certificate stored in \"client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"client-cert-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server.  If a matching dNSName is found, this constraint is met.  If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_EAP N_("The allowed EAP method to be used when authenticating to the network with 802.1x.  Valid methods are: \"leap\", \"md5\", \"tls\", \"peap\", \"ttls\", \"pwd\", and \"fast\".  Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_IDENTITY N_("Identity string for EAP authentication methods.  Often the user's user or login name.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PAC_FILE N_("UTF-8 encoded file path containing PAC for EAP-FAST.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PASSWORD N_("UTF-8 encoded password used for EAP authentication methods. If both the \"password\" property and the \"password-raw\" property are specified, \"password\" is preferred.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PASSWORD_RAW N_("Password used for EAP authentication methods, given as a byte array to allow passwords in other encodings than UTF-8 to be used. If both the \"password\" property and the \"password-raw\" property are specified, \"password\" is preferred.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PASSWORD_RAW_FLAGS N_("Flags indicating how to handle the \"password-raw\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE1_AUTH_FLAGS N_("Specifies authentication flags to use in \"phase 1\" outer authentication using NMSetting8021xAuthFlags options. The individual TLS versions can be explicitly disabled. If a certain TLS disable flag is not set, it is up to the supplicant to allow or forbid it. The TLS options map to tls_disable_tlsv1_x settings. See the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING N_("Enables or disables in-line provisioning of EAP-FAST credentials when FAST is specified as the EAP method in the \"eap\" property. Recognized values are \"0\" (disabled), \"1\" (allow unauthenticated provisioning), \"2\" (allow authenticated provisioning), and \"3\" (allow both authenticated and unauthenticated provisioning).  See the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE1_PEAPLABEL N_("Forces use of the new PEAP label during key derivation.  Some RADIUS servers may require forcing the new PEAP label to interoperate with PEAPv1.  Set to \"1\" to force use of the new PEAP label.  See the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE1_PEAPVER N_("Forces which PEAP version is used when PEAP is set as the EAP method in the \"eap\" property.  When unset, the version reported by the server will be used.  Sometimes when using older RADIUS servers, it is necessary to force the client to use a particular PEAP version.  To do so, this property may be set to \"0\" or \"1\" to force that specific PEAP version.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES N_("List of strings to be matched against the altSubjectName of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If the list is empty, no verification of the server certificate's altSubjectName is performed.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_AUTH N_("Specifies the allowed \"phase 2\" inner non-EAP authentication methods when an EAP method that uses an inner TLS tunnel is specified in the \"eap\" property.  Recognized non-EAP \"phase 2\" methods are \"pap\", \"chap\", \"mschap\", \"mschapv2\", \"gtc\", \"otp\", \"md5\", and \"tls\". Each \"phase 2\" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_AUTHEAP N_("Specifies the allowed \"phase 2\" inner EAP-based authentication methods when an EAP method that uses an inner TLS tunnel is specified in the \"eap\" property.  Recognized EAP-based \"phase 2\" methods are \"md5\", \"mschapv2\", \"otp\", \"gtc\", and \"tls\". Each \"phase 2\" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT N_("Contains the \"phase 2\" CA certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD N_("The password used to access the \"phase2\" CA certificate stored in \"phase2-ca-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-ca-cert-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_PATH N_("UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"phase2-ca-cert\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT N_("Contains the \"phase 2\" client certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD N_("The password used to access the \"phase2\" client certificate stored in \"phase2-client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-client-cert-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication.  If a matching dNSName is found, this constraint is met.  If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY N_("Contains the \"phase 2\" inner private key when the \"phase2-auth\" or \"phase2-autheap\" property is set to \"tls\". Key data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the \"phase2-private-key-password\" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte, and as with the blob scheme the \"phase2-private-key-password\" property must be set to the password used to decode the PKCS#12 private key and certificate.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD N_("The password used to decrypt the \"phase 2\" private key specified in the \"phase2-private-key\" property when the private key either uses the path scheme, or is a PKCS#12 format key.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-private-key-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH N_("Substring to be matched against the subject of the certificate presented by the authentication server during the inner \"phase 2\" authentication. When unset, no verification of the authentication server certificate's subject is performed.  This property provides little security, if any, and its use is deprecated in favor of NMSetting8021x:phase2-domain-suffix-match.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PIN N_("PIN used for EAP authentication methods.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PIN_FLAGS N_("Flags indicating how to handle the \"pin\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PRIVATE_KEY N_("Contains the private key when the \"eap\" property is set to \"tls\". Key data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the \"private-key-password\" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte, and as with the blob scheme the \"private-key-password\" property must be set to the password used to decode the PKCS#12 private key and certificate. WARNING: \"private-key\" is not a \"secret\" property, and thus unencrypted private key data using the BLOB scheme may be readable by unprivileged users.  Private keys should always be encrypted with a private key password to prevent unauthorized access to unencrypted private key data.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD N_("The password used to decrypt the private key specified in the \"private-key\" property when the private key either uses the path scheme, or if the private key is a PKCS#12 format key.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS N_("Flags indicating how to handle the \"private-key-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_SUBJECT_MATCH N_("Substring to be matched against the subject of the certificate presented by the authentication server. When unset, no verification of the authentication server certificate's subject is performed.  This property provides little security, if any, and its use is deprecated in favor of NMSetting8021x:domain-suffix-match.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_SYSTEM_CA_CERTS N_("When TRUE, overrides the \"ca-path\" and \"phase2-ca-path\" properties using the system CA directory specified at configure time with the --system-ca-path switch.  The certificates in this directory are added to the verification chain in addition to any certificates specified by the \"ca-cert\" and \"phase2-ca-cert\" properties. If the path provided with --system-ca-path is rather a file name (bundle of trusted CA certificates), it overrides \"ca-cert\" and \"phase2-ca-cert\" properties instead (sets ca_cert/ca_cert2 options for wpa_supplicant).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_AUTO_NEGOTIATE N_("If TRUE, enforce auto-negotiation of port speed and duplex mode.  If FALSE, \"speed\" and \"duplex\" properties should be both set or link configuration will be skipped.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_CLONED_MAC_ADDRESS N_("If specified, request that the device use this MAC address instead. This is known as MAC cloning or spoofing. Beside explicitly specifying a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address if the device has one (otherwise this is treated as \"preserve\"). \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"preserve\" (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_DUPLEX N_("Can be specified only when \"auto-negotiate\" is \"off\". In that case, statically configures the device to use that specified duplex mode, either \"half\" or \"full\". Must be set together with the \"speed\" property if specified. Before specifying a duplex mode be sure your device supports it.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK N_("With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting \"FE:FF:FF:00:00:00\" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the \"random\" or \"stable\" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of \"FE:FF:FF:00:00:00 68:F7:28:00:00:00\" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of \"02:00:00:00:00:00 00:00:00:00:00:00\" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, \"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00\" will create a fully scrambled MAC address, randomly locally or globally administered.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_MAC_ADDRESS N_("If specified, this connection will only apply to the Ethernet device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST N_("If specified, this connection will never apply to the Ethernet device whose permanent MAC address matches an address in the list.  Each MAC address is in the standard hex-digits-and-colons notation (00:11:22:33:44:55).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_PORT N_("Specific port type to use if the device supports multiple attachment methods.  One of \"tp\" (Twisted Pair), \"aui\" (Attachment Unit Interface), \"bnc\" (Thin Ethernet) or \"mii\" (Media Independent Interface). If the device supports only one port type, this setting is ignored.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_S390_NETTYPE N_("s390 network device type; one of \"qeth\", \"lcs\", or \"ctc\", representing the different types of virtual network devices available on s390 systems.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_S390_OPTIONS N_("Dictionary of key/value pairs of s390-specific device options.  Both keys and values must be strings.  Allowed keys include \"portno\", \"layer2\", \"portname\", \"protocol\", among others.  Key names must contain only alphanumeric characters (ie, [a-zA-Z0-9]).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_S390_SUBCHANNELS N_("Identifies specific subchannels that this network device uses for communication with z/VM or s390 host.  Like the \"mac-address\" property for non-z/VM devices, this property can be used to ensure this connection only applies to the network device that uses these subchannels.  The list should contain exactly 3 strings, and each string may only be composed of hexadecimal characters and the period (.) character.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_SPEED N_("Can be set to a value greater than zero only when \"auto-negotiate\" is \"off\". In that case, statically configures the device to use that specified speed. In Mbit/s, ie 100 == 100Mbit/s. Must be set together with the \"duplex\" property when non-zero. Before specifying a speed value be sure your device supports it.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_WAKE_ON_LAN N_("The NMSettingWiredWakeOnLan options to enable. Not all devices support all options. May be any combination of NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST (0x4), NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST (0x8), NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST (0x10), NM_SETTING_WIRED_WAKE_ON_LAN_ARP (0x20), NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC (0x40) or the special values NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (0x1) (to use global settings) and NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (0x8000) (to disable management of Wake-on-LAN in NetworkManager).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD N_("If specified, the password used with magic-packet-based Wake-on-LAN, represented as an Ethernet MAC address.  If NULL, no password will be required.")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_ENCAPSULATION N_("Encapsulation of ADSL connection.  Can be \"vcmux\" or \"llc\".")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_PASSWORD N_("Password used to authenticate with the ADSL service.")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_PROTOCOL N_("ADSL connection protocol.  Can be \"pppoa\", \"pppoe\" or \"ipoatm\".")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_USERNAME N_("Username used to authenticate with the ADSL service.")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_VCI N_("VCI of ADSL connection")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_VPI N_("VPI of ADSL connection")
+#define DESCRIBE_DOC_NM_SETTING_BLUETOOTH_BDADDR N_("The Bluetooth address of the device.")
+#define DESCRIBE_DOC_NM_SETTING_BLUETOOTH_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_BLUETOOTH_TYPE N_("Either \"dun\" for Dial-Up Networking connections or \"panu\" for Personal Area Networking connections to devices supporting the NAP profile.")
+#define DESCRIBE_DOC_NM_SETTING_BOND_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_BOND_OPTIONS N_("Dictionary of key/value pairs of bonding options.  Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, [a-zA-Z0-9]).")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_AGEING_TIME N_("The Ethernet MAC address aging time, in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_FORWARD_DELAY N_("The Spanning Tree Protocol (STP) forwarding delay, in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_FORWARD_MASK N_("A mask of group addresses to forward. Usually, group addresses in the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to standards. This property is a mask of 16 bits, each corresponding to a group address in that range that must be forwarded. The mask can't have bits 0, 1 or 2 set because they are used for STP, MAC pause frames and LACP.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_HELLO_TIME N_("The Spanning Tree Protocol (STP) hello time, in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAC_ADDRESS N_("If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the \"ethernet.cloned-mac-address\" is referred instead to generate the initial MAC address. Note that setting \"ethernet.cloned-mac-address\" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAX_AGE N_("The Spanning Tree Protocol (STP) maximum message age, in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_SNOOPING N_("Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PRIORITY N_("Sets the Spanning Tree Protocol (STP) priority for this bridge.  Lower values are \"better\"; the lowest priority bridge will be elected the root bridge.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_STP N_("Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE N_("Enables or disables \"hairpin mode\" for the port, which allows frames to be sent back out through the port the frame was received on.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PATH_COST N_("The Spanning Tree Protocol (STP) port cost for destinations via this port.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PRIORITY N_("The Spanning Tree Protocol (STP) priority of this bridge port.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_NUMBER N_("The number to dial to establish the connection to the CDMA-based mobile broadband network, if any.  If not specified, the default number (#777) is used when required.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_PASSWORD N_("The password used to authenticate with the network, if required.  Many providers do not require a password, or accept any password.  But if a password is required, it is specified here.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_USERNAME N_("The username used to authenticate with the network, if required.  Many providers do not require a username, or accept any username.  But if a username is required, it is specified here.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTH_RETRIES N_("The number of retries for the authentication. Zero means to try indefinitely; -1 means to use a global default. If the global default is not set, the authentication retries for 3 times before failing the connection. Currently this only applies to 802-1x authentication.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT N_("Whether or not the connection should be automatically connected by NetworkManager when the resources for the connection are available. TRUE to automatically activate the connection, FALSE to require manual intervention to activate the connection.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY N_("The autoconnect priority. If the connection is set to autoconnect, connections with higher priority will be preferred. Defaults to 0. The higher number means higher priority.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES N_("The number of times a connection should be tried when autoactivating before giving up. Zero means forever, -1 means the global default (4 times if not overridden). Setting this to 1 means to try activation only once before blocking autoconnect. Note that after a timeout, NetworkManager will try to autoconnect again.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES N_("Whether or not slaves of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for master connections. The permitted values are: 0: leave slave connections untouched, 1: activate all the slave connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-slaves is read to determine the real value. If it is default as well, this fallbacks to 0.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT N_("If greater than zero, delay success of IP addressing until either the timeout is reached, or an IP gateway replies to a ping.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_ID N_("A human readable unique identifier for the connection, like \"Work Wi-Fi\" or \"T-Mobile 3G\".")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_INTERFACE_NAME N_("The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_LLDP N_("Whether LLDP is enabled for the connection.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_MASTER N_("Interface name of the master device or UUID of the master connection.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_METERED N_("Whether the connection is metered. When updating this property on a currently activated connection, the change takes effect immediately.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_PERMISSIONS N_("An array of strings defining what access a given user has to this connection.  If this is NULL or empty, all users are allowed to access this connection; otherwise users are allowed if and only if they are in this list.  When this is not empty, the connection can be active only when one of the specified users is logged into an active session.  Each entry is of the form \"[type]:[id]:[reserved]\"; for example, \"user:dcbw:blah\". At this time only the \"user\" [type] is allowed.  Any other values are ignored and reserved for future use.  [id] is the username that this permission refers to, which may not contain the \":\" character. Any [reserved] information present must be ignored and is reserved for future use.  All of [type], [id], and [reserved] must be valid UTF-8.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_READ_ONLY N_("FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_SECONDARIES N_("List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_SLAVE_TYPE N_("Setting name of the device type of this slave's master connection (eg, \"bond\"), or NULL if this connection is not a slave.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("Token to generate stable IDs for the connection. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. Note that also the interface name of the activating connection and a per-host secret key is included into the address generation so that the same stable-id on different hosts/devices yields different addresses. If the value is unset, an ID unique for the connection is used. Specifying a stable-id allows multiple connections to generate the same addresses. Another use is to generate IDs at runtime via dynamic substitutions. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-boot, or every time. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}/${BOOT}\" to create a unique id for this connection that changes with every reboot. Note that two connections only use the same effective id if their stable-id is also identical before performing dynamic substitutions.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("A universally unique identifier for the connection, for example generated with libuuid.  It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network.  For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\").")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_ZONE N_("The trust level of a the connection.  Free form case-insensitive string (for example \"Home\", \"Work\", \"Public\").  NULL or unspecified zone means the connection will be placed in the default zone as defined by the firewall. When updating this property on a currently activated connection, the change takes effect immediately.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_FLAGS N_("Specifies the NMSettingDcbFlags for the DCB FCoE application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_MODE N_("The FCoE controller mode; either \"fabric\" (default) or \"vn2vn\".")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_PRIORITY N_("The highest User Priority (0 - 7) which FCoE frames should use, or -1 for default priority.  Only used when the \"app-fcoe-flags\" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FIP_FLAGS N_("Specifies the NMSettingDcbFlags for the DCB FIP application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FIP_PRIORITY N_("The highest User Priority (0 - 7) which FIP frames should use, or -1 for default priority.  Only used when the \"app-fip-flags\" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_ISCSI_FLAGS N_("Specifies the NMSettingDcbFlags for the DCB iSCSI application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_ISCSI_PRIORITY N_("The highest User Priority (0 - 7) which iSCSI frames should use, or -1 for default priority. Only used when the \"app-iscsi-flags\" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_BANDWIDTH N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the percentage of bandwidth of the priority's assigned group that the priority may use.  The sum of all percentages for priorities which belong to the same group must total 100 percents.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_FLOW_CONTROL N_("An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the corresponding priority should transmit priority pause.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS N_("Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH N_("An array of 8 uint values, where the array index corresponds to the Priority Group ID (0 - 7) and the value indicates the percentage of link bandwidth allocated to that group.  Allowed values are 0 - 100, and the sum of all values must total 100 percents.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_GROUP_FLAGS N_("Specifies the NMSettingDcbFlags for DCB Priority Groups.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_GROUP_ID N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the Priority Group ID.  Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted group.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH N_("An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped.")
+#define DESCRIBE_DOC_NM_SETTING_DUMMY_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_GENERIC_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_GSM_APN N_("The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network.  The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_DEVICE_ID N_("The device unique identifier (as given by the WWAN management service) which this connection applies to.  If given, the connection will only apply to the specified device.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_HOME_ONLY N_("When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_GSM_NETWORK_ID N_("The Network ID (GSM LAI format, ie MCC-MNC) to force specific network registration.  If the Network ID is specified, NetworkManager will attempt to force the device to register only on the specified network. This can be used to ensure that the device does not roam when direct roaming control of the device is not otherwise possible.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_NUMBER N_("Number to dial when establishing a PPP data session with the GSM-based mobile broadband network.  Many modems do not require PPP for connections to the mobile network and thus this property should be left blank, which allows NetworkManager to select the appropriate settings automatically.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_PASSWORD N_("The password used to authenticate with the network, if required.  Many providers do not require a password, or accept any password.  But if a password is required, it is specified here.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_PIN N_("If the SIM is locked with a PIN it must be unlocked before any other operations are requested.  Specify the PIN here to allow operation of the device.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_PIN_FLAGS N_("Flags indicating how to handle the \"pin\" property.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_SIM_ID N_("The SIM card unique identifier (as given by the WWAN management service) which this connection applies to.  If given, the connection will apply to any device also allowed by \"device-id\" which contains a SIM card matching the given identifier.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_SIM_OPERATOR_ID N_("A MCC/MNC string like \"310260\" or \"21601\" identifying the specific mobile network operator which this connection applies to.  If given, the connection will apply to any device also allowed by \"device-id\" and \"sim-id\" which contains a SIM card provisioned by the given operator.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_USERNAME N_("The username used to authenticate with the network, if required.  Many providers do not require a username, or accept any username.  But if a username is required, it is specified here.")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_MAC_ADDRESS N_("If specified, this connection will only apply to the IPoIB device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_P_KEY N_("The InfiniBand P_Key to use for this device. A value of -1 means to use the default P_Key (aka \"the P_Key at index 0\").  Otherwise it is a 16-bit unsigned integer, whose high bit is set if it is a \"full membership\" P_Key.")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_PARENT N_("The interface name of the parent device of this device. Normally NULL, but if the \"p_key\" property is set, then you must specify the base device by setting either this property or \"mac-address\".")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_TRANSPORT_MODE N_("The IP-over-InfiniBand transport mode. Either \"datagram\" or \"connected\".")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT N_("How many additional levels of encapsulation are permitted to be prepended to packets. This property applies only to IPv6 tunnels.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_FLOW_LABEL N_("The flow label to assign to tunnel packets. This property applies only to IPv6 tunnels.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_INPUT_KEY N_("The key used for tunnel input packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_LOCAL N_("The local endpoint of the tunnel; the value can be empty, otherwise it must contain an IPv4 or IPv6 address.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_MODE N_("The tunneling mode, for example NM_IP_TUNNEL_MODE_IPIP (1) or NM_IP_TUNNEL_MODE_GRE (2).")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_OUTPUT_KEY N_("The key used for tunnel output packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_PARENT N_("If given, specifies the parent interface name or parent connection UUID the new device will be bound to so that tunneled packets will only be routed via that interface.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY N_("Whether to enable Path MTU Discovery on this tunnel.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_REMOTE N_("The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 address.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_TOS N_("The type of service (IPv4) or traffic class (IPv6) field to be set on tunneled packets.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_TTL N_("The TTL to assign to tunneled packets. 0 is a special value meaning that packets inherit the TTL value.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ADDRESSES N_("Array of IP addresses.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DAD_TIMEOUT N_("Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network.  If an address conflict is detected, the activation will fail.  A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or 3 seconds).  A value greater than zero is a timeout in milliseconds.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID N_("A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options. When the property is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which case the first byte is assumed to be the 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC address). If the property is not a hex string it is considered as a non-hardware-address client ID and the 'type' field is set to 0.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_FQDN N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified FQDN will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-hostname\" are mutually exclusive and cannot be set at the same time.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer.  If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("Intra-connection DNS priority. The relative priority to be used when determining the order of DNS servers in resolv.conf.  A lower value means that servers will be on top of the file.  Zero selects the default value, which is 50 for VPNs and 100 for other connections.  Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. For that, just specify the DNS servers in the desired order. When multiple devices have configurations with the same priority, the one with an active default route will be preferred. Note that when using dns=dnsmasq the order is meaningless since dnsmasq forwards queries to all known servers at the same time. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_SEARCH N_("Array of DNS search domains.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out.  Note that at least one IP configuration must succeed or overall network configuration will still fail.  For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration.  The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_METRIC N_("The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is chosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_TABLE N_("Enable policy routing (source routing) and set the routing table used when adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes and static routes. But note that static routes can individually overwrite the setting by explicitly specifying a non-zero routing table. If the table setting is left at zero, it is eligible to be overwritten via global configuration. If the property is zero even after applying the global configuration value, policy routing is disabled for the address family of this connection. Policy routing disabled means that NetworkManager will add all routes to the main table (except static routes that explicitly configure a different table). Additionally, NetworkManager will not delete any extraneous routes from tables except the main table. This is to preserve backward compatibility for users who manage routing tables outside of NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTES N_("Array of IP routes.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE N_("Configure method for creating the address for use with RFC4862 IPv6 Stateless Address Autoconfiguration. The permitted values are: NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 (0) or NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY (1). If the property is set to EUI64, the addresses will be generated using the interface tokens derived from hardware address. This makes the host part of the address to stay constant, making it possible to track host's presence when it changes networks. The address changes when the interface hardware is replaced. The value of stable-privacy enables use of cryptographically secure hash of a secret host-specific key along with the connection's stable-id and the network address as specified by RFC7217. This makes it impossible to use the address track host's presence, and makes the address stable when the network interface hardware is replaced. On D-Bus, the absence of an addr-gen-mode setting equals enabling stable-privacy. For keyfile plugin, the absence of the setting on disk means EUI64 so that the property doesn't change on upgrade from older versions. Note that this setting is distinct from the Privacy Extensions as configured by \"ip6-privacy\" property and it does not affect the temporary addresses configured with this option.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDRESSES N_("Array of IP addresses.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DAD_TIMEOUT N_("Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network.  If an address conflict is detected, the activation will fail.  A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or 3 seconds).  A value greater than zero is a timeout in milliseconds.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer.  If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS N_("Array of IP addresses of DNS servers.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_PRIORITY N_("Intra-connection DNS priority. The relative priority to be used when determining the order of DNS servers in resolv.conf.  A lower value means that servers will be on top of the file.  Zero selects the default value, which is 50 for VPNs and 100 for other connections.  Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. For that, just specify the DNS servers in the desired order. When multiple devices have configurations with the same priority, the one with an active default route will be preferred. Note that when using dns=dnsmasq the order is meaningless since dnsmasq forwards queries to all known servers at the same time. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_SEARCH N_("Array of DNS search domains.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IP6_PRIVACY N_("Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941.  If enabled, it makes the kernel generate a temporary IPv6 address in addition to the public one generated from MAC address via modified EUI-64.  This enhances privacy, but could cause problems in some applications, on the other hand.  The permitted values are: -1: unknown, 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary addresses). Having a per-connection setting set to \"-1\" (unknown) means fallback to global configuration \"ipv6.ip6-privacy\". If also global configuration is unspecified or set to \"-1\", fallback to read \"/proc/sys/net/ipv6/conf/default/use_tempaddr\". Note that this setting is distinct from the Stable Privacy addresses that can be enabled with the \"addr-gen-mode\" property's \"stable-privacy\" setting as another way of avoiding host tracking with IPv6 addresses.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out.  Note that at least one IP configuration must succeed or overall network configuration will still fail.  For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration.  The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_METRIC N_("The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is chosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_TABLE N_("Enable policy routing (source routing) and set the routing table used when adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes and static routes. But note that static routes can individually overwrite the setting by explicitly specifying a non-zero routing table. If the table setting is left at zero, it is eligible to be overwritten via global configuration. If the property is zero even after applying the global configuration value, policy routing is disabled for the address family of this connection. Policy routing disabled means that NetworkManager will add all routes to the main table (except static routes that explicitly configure a different table). Additionally, NetworkManager will not delete any extraneous routes from tables except the main table. This is to preserve backward compatibility for users who manage routing tables outside of NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTES N_("Array of IP routes.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_TOKEN N_("Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_ENCRYPT N_("Whether the transmitted traffic must be encrypted.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CAK N_("The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CAK_FLAGS N_("Flags indicating how to handle the \"mka-cak\" property.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CKN N_("The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_MODE N_("Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_PORT N_("The port component of the SCI (Secure Channel Identifier), between 1 and 65534.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_VALIDATION N_("Specifies the validation mode for incoming frames.")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_MODE N_("The macvlan mode, which specifies the communication mechanism between multiple macvlans on the same lower device.")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this MAC-VLAN interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PROMISCUOUS N_("Whether the interface should be put in promiscuous mode.")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_TAP N_("Whether the interface should be a MACVTAP.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_FAIL_MODE N_("The bridge failure mode. One of \"secure\", \"standalone\" or empty.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE N_("Enable or disable multicast snooping.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_RSTP_ENABLE N_("Enable or disable RSTP.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_STP_ENABLE N_("Enable or disable STP.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_INTERFACE_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_INTERFACE_TYPE N_("The interface type. Either \"internal\", or empty.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PATCH_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PATCH_PEER N_("Specifies the unicast destination IP address of a remote OpenVSwitch bridge port to connect to.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_DOWNDELAY N_("The time port must be inactive in order to be considered down.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_MODE N_("Bonding mode. One of \"active-backup\", \"balance-slb\", or \"balance-tcp\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_UPDELAY N_("The time port must be active befor it starts forwarding traffic.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_LACP N_("LACP mode. One of \"active\", \"off\", or \"passive\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_TAG N_("The VLAN tag in the range 0-4095.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_VLAN_MODE N_("The VLAN mode. One of \"access\", \"native-tagged\", \"native-untagged\", \"trunk\" or unset.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_BAUD N_("If non-zero, instruct pppd to set the serial port to the specified baudrate.  This value should normally be left as 0 to automatically choose the speed.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_CRTSCTS N_("If TRUE, specify that pppd should set the serial port to use hardware flow control with RTS and CTS signals.  This value should normally be set to FALSE.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_LCP_ECHO_FAILURE N_("If non-zero, instruct pppd to presume the connection to the peer has failed if the specified number of LCP echo-requests go unanswered by the peer.  The \"lcp-echo-interval\" property must also be set to a non-zero value if this property is used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_LCP_ECHO_INTERVAL N_("If non-zero, instruct pppd to send an LCP echo-request frame to the peer every n seconds (where n is the specified value).  Note that some PPP peers will respond to echo requests and some will not, and it is not possible to autodetect this.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_MPPE_STATEFUL N_("If TRUE, stateful MPPE is used.  See pppd documentation for more information on stateful MPPE.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_MRU N_("If non-zero, instruct pppd to request that the peer send packets no larger than the specified size.  If non-zero, the MRU should be between 128 and 16384.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_MTU N_("If non-zero, instruct pppd to send packets no larger than the specified size.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NO_VJ_COMP N_("If TRUE, Van Jacobsen TCP header compression will not be requested.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NOAUTH N_("If TRUE, do not require the other side (usually the PPP server) to authenticate itself to the client.  If FALSE, require authentication from the remote side.  In almost all cases, this should be TRUE.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NOBSDCOMP N_("If TRUE, BSD compression will not be requested.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NODEFLATE N_("If TRUE, \"deflate\" compression will not be requested.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_CHAP N_("If TRUE, the CHAP authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_EAP N_("If TRUE, the EAP authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_MSCHAP N_("If TRUE, the MSCHAP authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_MSCHAPV2 N_("If TRUE, the MSCHAPv2 authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_PAP N_("If TRUE, the PAP authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REQUIRE_MPPE N_("If TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for the PPP session.  If either 64-bit or 128-bit MPPE is not available the session will fail.  Note that MPPE is not used on mobile broadband connections.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REQUIRE_MPPE_128 N_("If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be required for the PPP session, and the \"require-mppe\" property must also be set to TRUE.  If 128-bit MPPE is not available the session will fail.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_PARENT N_("If given, specifies the parent interface name on which this PPPoE connection should be created.  If this property is not specified, the connection is activated on the interface specified in \"interface-name\" of NMSettingConnection.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_PASSWORD N_("Password used to authenticate with the PPPoE service.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_SERVICE N_("If specified, instruct PPPoE to only initiate sessions with access concentrators that provide the specified service.  For most providers, this should be left blank.  It is only required if there are multiple access concentrators or a specific service is known to be required.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_USERNAME N_("Username used to authenticate with the PPPoE service.")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_BROWSER_ONLY N_("Whether the proxy configuration is for browser only.")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_METHOD N_("Method for proxy configuration, Default is NM_SETTING_PROXY_METHOD_NONE (0)")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_PAC_SCRIPT N_("PAC script for the connection.")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_PAC_URL N_("PAC URL for obtaining PAC file.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_BAUD N_("Speed to use for communication over the serial port.  Note that this value usually has no effect for mobile broadband modems as they generally ignore speed settings and use the highest available speed.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_BITS N_("Byte-width of the serial communication. The 8 in \"8n1\" for example.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_PARITY N_("Parity setting of the serial port.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_SEND_DELAY N_("Time to delay between each byte sent to the modem, in microseconds.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_STOPBITS N_("Number of stop bits for communication on the serial port.  Either 1 or 2. The 1 in \"8n1\" for example.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_CONFIG N_("The JSON configuration for the team network interface.  The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used.  See man teamd.conf for the format details.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_CONFIG N_("The JSON configuration for the team port. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_TUN_GROUP N_("The group ID which will own the device. If set to NULL everyone will be able to use the device.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_MODE N_("The operating mode of the virtual device. Allowed values are NM_SETTING_TUN_MODE_TUN (1) to create a layer 3 device and NM_SETTING_TUN_MODE_TAP (2) to create an Ethernet-like layer 2 one.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_MULTI_QUEUE N_("If the property is set to TRUE, the interface will support multiple file descriptors (queues) to parallelize packet sending or receiving. Otherwise, the interface will only support a single queue.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_TUN_OWNER N_("The user ID which will own the device. If set to NULL everyone will be able to use the device.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_PI N_("If TRUE the interface will prepend a 4 byte header describing the physical interface to the packets.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_VNET_HDR N_("If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio network header.")
+#define DESCRIBE_DOC_NM_SETTING_USER_DATA N_("A dictionary of key/value pairs with user data. This data is ignored by NetworkManager and can be used at the users discretion. The keys only support a strict ascii format, but the values can be arbitrary UTF8 strings up to a certain length.")
+#define DESCRIBE_DOC_NM_SETTING_USER_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_EGRESS_PRIORITY_MAP N_("For outgoing packets, a list of mappings from Linux SKB priorities to 802.1p priorities.  The mapping is given in the format \"from:to\" where both \"from\" and \"to\" are unsigned integers, ie \"7:3\".")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_FLAGS N_("One or more flags which control the behavior and features of the VLAN interface.  Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use of the GVRP protocol), and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose binding of the interface to its master device's operating state). NM_VLAN_FLAG_MVRP (0x8) (use of the MVRP protocol). The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, but it used to be 0. To preserve backward compatibility, the default-value in the D-Bus API continues to be 0 and a missing property on D-Bus is still considered as 0.")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_ID N_("The VLAN identifier that the interface created by this connection should be assigned. The valid range is from 0 to 4094, without the reserved id 4095.")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_INGRESS_PRIORITY_MAP N_("For incoming packets, a list of mappings from 802.1p priorities to Linux SKB priorities.  The mapping is given in the format \"from:to\" where both \"from\" and \"to\" are unsigned integers, ie \"7:3\".")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this VLAN interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_DATA N_("Dictionary of key/value pairs of VPN plugin specific data.  Both keys and values must be strings.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_VPN_PERSISTENT N_("If the VPN service supports persistence, and this property is TRUE, the VPN will attempt to stay connected across link changes and outages, until explicitly disconnected.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_SECRETS N_("Dictionary of key/value pairs of VPN plugin specific secrets like passwords or private keys.  Both keys and values must be strings.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_SERVICE_TYPE N_("D-Bus service name of the VPN plugin that this setting uses to connect to its network.  i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_TIMEOUT N_("Timeout for the VPN service to establish the connection. Some services may take quite a long time to connect. Value of 0 means a default timeout, which is 60 seconds (unless overridden by vpn.timeout in configuration file). Values greater than zero mean timeout in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_USER_NAME N_("If the VPN connection requires a user name for authentication, that name should be provided here.  If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty.  If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_AGEING N_("Specifies the lifetime in seconds of FDB entries learnt by the kernel.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_DESTINATION_PORT N_("Specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_ID N_("Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to use.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_L2_MISS N_("Specifies whether netlink LL ADDR miss notifications are generated.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_L3_MISS N_("Specifies whether netlink IP ADDR miss notifications are generated.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_LEARNING N_("Specifies whether unknown source link layer addresses and IP addresses are entered into the VXLAN device forwarding database.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_LIMIT N_("Specifies the maximum number of FDB entries. A value of zero means that the kernel will store unlimited entries.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_LOCAL N_("If given, specifies the source IP address to use in outgoing packets.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_PARENT N_("If given, specifies the parent interface name or parent connection UUID.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_PROXY N_("Specifies whether ARP proxy is turned on.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_REMOTE N_("Specifies the unicast destination IP address to use in outgoing packets when the destination link layer address is not known in the VXLAN device forwarding database, or the multicast IP address to join.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_RSC N_("Specifies whether route short circuit is turned on.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_SOURCE_PORT_MAX N_("Specifies the maximum UDP source port to communicate to the remote VXLAN tunnel endpoint.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_SOURCE_PORT_MIN N_("Specifies the minimum UDP source port to communicate to the remote VXLAN tunnel endpoint.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_TOS N_("Specifies the TOS value to use in outgoing packets.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_TTL N_("Specifies the time-to-live value to use in outgoing packets.")
+#define DESCRIBE_DOC_NM_SETTING_WIMAX_MAC_ADDRESS N_("If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1")
+#define DESCRIBE_DOC_NM_SETTING_WIMAX_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_WIMAX_NETWORK_NAME N_("Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1")
diff --git a/clients/common/settings-docs.c.in b/clients/common/settings-docs.c.in
new file mode 100644
index 00000000..b523a394
--- /dev/null
+++ b/clients/common/settings-docs.c.in
@@ -0,0 +1,363 @@
+/* Generated file. Do not edit. */
+
+#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_CHANNEL N_("Channel on which the mesh network to join is located.")
+#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS N_("Anycast DHCP MAC address used when requesting an IP address via DHCP. The specific anycast address used determines which DHCP server class answers the request.")
+#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_SSID N_("SSID of the mesh network to join.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_BAND N_("802.11 frequency band of the network.  One of \"a\" for 5GHz 802.11a or \"bg\" for 2.4GHz 802.11.  This will lock associations to the Wi-Fi network to the specific band, i.e. if \"a\" is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible.  This setting depends on specific driver capability and may not work with all drivers.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_BSSID N_("If specified, directs the device to only associate with the given access point.  This capability is highly driver dependent and not supported by all devices.  Note: this property does not control the BSSID used when creating an Ad-Hoc network and is unlikely to in the future.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_CHANNEL N_("Wireless channel to use for the Wi-Fi connection.  The device will only join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel.  Because channel numbers overlap between bands, this property also requires the \"band\" property to be set.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS N_("If specified, request that the device use this MAC address instead. This is known as MAC cloning or spoofing. Beside explicitly specifying a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address of the device. \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"preserve\" (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK N_("With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting \"FE:FF:FF:00:00:00\" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the \"random\" or \"stable\" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of \"FE:FF:FF:00:00:00 68:F7:28:00:00:00\" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of \"02:00:00:00:00:00 00:00:00:00:00:00\" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, \"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00\" will create a fully scrambled MAC address, randomly locally or globally administered.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_HIDDEN N_("If TRUE, indicates this network is a non-broadcasting network that hides its SSID.  In this case various workarounds may take place, such as probe-scanning the SSID for more reliable network discovery.  However, these workarounds expose inherent insecurities with hidden SSID networks, and thus hidden SSID networks should be used with caution.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MAC_ADDRESS N_("If specified, this connection will only apply to the Wi-Fi device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST N_("A list of permanent MAC addresses of Wi-Fi devices to which this connection should never apply.  Each MAC address should be given in the standard hex-digits-and-colons notation (eg \"00:11:22:33:44:55\").")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION N_("One of NM_SETTING_MAC_RANDOMIZATION_DEFAULT (0) (never randomize unless the user has set a global default to randomize and the supplicant supports randomization),  NM_SETTING_MAC_RANDOMIZATION_NEVER (1) (never randomize the MAC address), or NM_SETTING_MAC_RANDOMIZATION_ALWAYS (2) (always randomize the MAC address). This property is deprecated for 'cloned-mac-address'. Deprecated: 1")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MODE N_("Wi-Fi network mode; one of \"infrastructure\", \"adhoc\" or \"ap\".  If blank, infrastructure is assumed.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_POWERSAVE N_("One of NM_SETTING_WIRELESS_POWERSAVE_DISABLE (2) (disable Wi-Fi power saving), NM_SETTING_WIRELESS_POWERSAVE_ENABLE (3) (enable Wi-Fi power saving), NM_SETTING_WIRELESS_POWERSAVE_IGNORE (1) (don't touch currently configure setting) or NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (0) (use the globally configured value). All other values are reserved.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_RATE N_("If non-zero, directs the device to only use the specified bitrate for communication with the access point.  Units are in Kb/s, ie 5500 = 5.5 Mbit/s.  This property is highly driver dependent and not all devices support setting a static bitrate.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SEEN_BSSIDS N_("A list of BSSIDs (each BSSID formatted as a MAC address like \"00:11:22:33:44:55\") that have been detected as part of the Wi-Fi network.  NetworkManager internally tracks previously seen BSSIDs. The property is only meant for reading and reflects the BSSID list of NetworkManager. The changes you make to this property will not be preserved.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SSID N_("SSID of the Wi-Fi network. Must be specified.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_TX_POWER N_("If non-zero, directs the device to use the specified transmit power. Units are dBm.  This property is highly driver dependent and not all devices support setting a static transmit power.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_AUTH_ALG N_("When WEP is used (ie, key-mgmt = \"none\" or \"ieee8021x\") indicate the 802.11 authentication algorithm required by the AP here.  One of \"open\" for Open System, \"shared\" for Shared Key, or \"leap\" for Cisco LEAP.  When using Cisco LEAP (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\") the \"leap-username\" and \"leap-password\" properties must be specified.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_GROUP N_("A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list.  For maximum compatibility leave this property empty.  Each list element may be one of \"wep40\", \"wep104\", \"tkip\", or \"ccmp\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_KEY_MGMT N_("Key management used for the connection.  One of \"none\" (WEP), \"ieee8021x\" (Dynamic WEP), \"wpa-none\" (Ad-Hoc WPA-PSK), \"wpa-psk\" (infrastructure WPA-PSK), or \"wpa-eap\" (WPA-Enterprise).  This property must be set for any Wi-Fi connection that uses security.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD N_("The login password for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS N_("Flags indicating how to handle the \"leap-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME N_("The login username for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PAIRWISE N_("A list of pairwise encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty.  Each list element may be one of \"tkip\" or \"ccmp\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PMF N_("Indicates whether Protected Management Frames (802.11w) must be enabled for the connection.  One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable PMF), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail if not supported).  When set to NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no global default is set, PMF will be optionally enabled.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PROTO N_("List of strings specifying the allowed WPA protocol versions to use. Each element may be one \"wpa\" (allow WPA) or \"rsn\" (allow WPA2/RSN).  If not specified, both WPA and RSN connections are allowed.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK N_("Pre-Shared-Key for WPA networks.  If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key.  Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS N_("Flags indicating how to handle the \"psk\" property.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS N_("Flags indicating how to handle the \"wep-key0\", \"wep-key1\", \"wep-key2\", and \"wep-key3\" properties.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE N_("Controls the interpretation of WEP keys.  Allowed values are NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character hexadecimal string, or a 5- or 13-character ASCII password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a string and will be hashed using the de-facto MD5 method to derive the actual WEP key.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY0 N_("Index 0 WEP key.  This is the WEP key used in most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY1 N_("Index 1 WEP key.  This WEP index is not used by most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY2 N_("Index 2 WEP key.  This WEP index is not used by most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY3 N_("Index 3 WEP key.  This WEP index is not used by most networks.  See the \"wep-key-type\" property for a description of how this key is interpreted.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX N_("When static WEP is used (ie, key-mgmt = \"none\") and a non-default WEP key index is used by the AP, put that WEP key index here.  Valid values are 0 (default key) through 3.  Note that some consumer access points (like the Linksys WRT54G) number the keys 1 - 4.")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WPS_METHOD N_("Flags indicating which mode of WPS is to be used if any. There's little point in changing the default setting as NetworkManager will automatically determine whether it's feasible to start WPS enrollment from the Access Point capabilities. WPS can be disabled by setting this property to a value of 1.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_ALTSUBJECT_MATCHES N_("List of strings to be matched against the altSubjectName of the certificate presented by the authentication server. If the list is empty, no verification of the server certificate's altSubjectName is performed.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_ANONYMOUS_IDENTITY N_("Anonymous identity string for EAP authentication methods.  Used as the unencrypted identity with EAP types that support different tunneled identity like EAP-TTLS.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_AUTH_TIMEOUT N_("A timeout for the authentication. Zero means the global default; if the global default is not set, the authentication timeout is 25 seconds.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT N_("Contains the CA certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT_PASSWORD N_("The password used to access the CA certificate stored in \"ca-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"ca-cert-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_PATH N_("UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"ca-cert\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT N_("Contains the client certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD N_("The password used to access the client certificate stored in \"client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"client-cert-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server.  If a matching dNSName is found, this constraint is met.  If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_EAP N_("The allowed EAP method to be used when authenticating to the network with 802.1x.  Valid methods are: \"leap\", \"md5\", \"tls\", \"peap\", \"ttls\", \"pwd\", and \"fast\".  Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_IDENTITY N_("Identity string for EAP authentication methods.  Often the user's user or login name.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PAC_FILE N_("UTF-8 encoded file path containing PAC for EAP-FAST.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PASSWORD N_("UTF-8 encoded password used for EAP authentication methods. If both the \"password\" property and the \"password-raw\" property are specified, \"password\" is preferred.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PASSWORD_RAW N_("Password used for EAP authentication methods, given as a byte array to allow passwords in other encodings than UTF-8 to be used. If both the \"password\" property and the \"password-raw\" property are specified, \"password\" is preferred.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PASSWORD_RAW_FLAGS N_("Flags indicating how to handle the \"password-raw\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE1_AUTH_FLAGS N_("Specifies authentication flags to use in \"phase 1\" outer authentication using NMSetting8021xAuthFlags options. The individual TLS versions can be explicitly disabled. If a certain TLS disable flag is not set, it is up to the supplicant to allow or forbid it. The TLS options map to tls_disable_tlsv1_x settings. See the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING N_("Enables or disables in-line provisioning of EAP-FAST credentials when FAST is specified as the EAP method in the \"eap\" property. Recognized values are \"0\" (disabled), \"1\" (allow unauthenticated provisioning), \"2\" (allow authenticated provisioning), and \"3\" (allow both authenticated and unauthenticated provisioning).  See the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE1_PEAPLABEL N_("Forces use of the new PEAP label during key derivation.  Some RADIUS servers may require forcing the new PEAP label to interoperate with PEAPv1.  Set to \"1\" to force use of the new PEAP label.  See the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE1_PEAPVER N_("Forces which PEAP version is used when PEAP is set as the EAP method in the \"eap\" property.  When unset, the version reported by the server will be used.  Sometimes when using older RADIUS servers, it is necessary to force the client to use a particular PEAP version.  To do so, this property may be set to \"0\" or \"1\" to force that specific PEAP version.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES N_("List of strings to be matched against the altSubjectName of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If the list is empty, no verification of the server certificate's altSubjectName is performed.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_AUTH N_("Specifies the allowed \"phase 2\" inner non-EAP authentication methods when an EAP method that uses an inner TLS tunnel is specified in the \"eap\" property.  Recognized non-EAP \"phase 2\" methods are \"pap\", \"chap\", \"mschap\", \"mschapv2\", \"gtc\", \"otp\", \"md5\", and \"tls\". Each \"phase 2\" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_AUTHEAP N_("Specifies the allowed \"phase 2\" inner EAP-based authentication methods when an EAP method that uses an inner TLS tunnel is specified in the \"eap\" property.  Recognized EAP-based \"phase 2\" methods are \"md5\", \"mschapv2\", \"otp\", \"gtc\", and \"tls\". Each \"phase 2\" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT N_("Contains the \"phase 2\" CA certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD N_("The password used to access the \"phase2\" CA certificate stored in \"phase2-ca-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-ca-cert-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_PATH N_("UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"phase2-ca-cert\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT N_("Contains the \"phase 2\" client certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD N_("The password used to access the \"phase2\" client certificate stored in \"phase2-client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-client-cert-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication.  If a matching dNSName is found, this constraint is met.  If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY N_("Contains the \"phase 2\" inner private key when the \"phase2-auth\" or \"phase2-autheap\" property is set to \"tls\". Key data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the \"phase2-private-key-password\" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte, and as with the blob scheme the \"phase2-private-key-password\" property must be set to the password used to decode the PKCS#12 private key and certificate.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD N_("The password used to decrypt the \"phase 2\" private key specified in the \"phase2-private-key\" property when the private key either uses the path scheme, or is a PKCS#12 format key.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-private-key-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH N_("Substring to be matched against the subject of the certificate presented by the authentication server during the inner \"phase 2\" authentication. When unset, no verification of the authentication server certificate's subject is performed.  This property provides little security, if any, and its use is deprecated in favor of NMSetting8021x:phase2-domain-suffix-match.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PIN N_("PIN used for EAP authentication methods.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PIN_FLAGS N_("Flags indicating how to handle the \"pin\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PRIVATE_KEY N_("Contains the private key when the \"eap\" property is set to \"tls\". Key data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the \"private-key-password\" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte, and as with the blob scheme the \"private-key-password\" property must be set to the password used to decode the PKCS#12 private key and certificate. WARNING: \"private-key\" is not a \"secret\" property, and thus unencrypted private key data using the BLOB scheme may be readable by unprivileged users.  Private keys should always be encrypted with a private key password to prevent unauthorized access to unencrypted private key data.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD N_("The password used to decrypt the private key specified in the \"private-key\" property when the private key either uses the path scheme, or if the private key is a PKCS#12 format key.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS N_("Flags indicating how to handle the \"private-key-password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_SUBJECT_MATCH N_("Substring to be matched against the subject of the certificate presented by the authentication server. When unset, no verification of the authentication server certificate's subject is performed.  This property provides little security, if any, and its use is deprecated in favor of NMSetting8021x:domain-suffix-match.")
+#define DESCRIBE_DOC_NM_SETTING_802_1X_SYSTEM_CA_CERTS N_("When TRUE, overrides the \"ca-path\" and \"phase2-ca-path\" properties using the system CA directory specified at configure time with the --system-ca-path switch.  The certificates in this directory are added to the verification chain in addition to any certificates specified by the \"ca-cert\" and \"phase2-ca-cert\" properties. If the path provided with --system-ca-path is rather a file name (bundle of trusted CA certificates), it overrides \"ca-cert\" and \"phase2-ca-cert\" properties instead (sets ca_cert/ca_cert2 options for wpa_supplicant).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_AUTO_NEGOTIATE N_("If TRUE, enforce auto-negotiation of port speed and duplex mode.  If FALSE, \"speed\" and \"duplex\" properties should be both set or link configuration will be skipped.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_CLONED_MAC_ADDRESS N_("If specified, request that the device use this MAC address instead. This is known as MAC cloning or spoofing. Beside explicitly specifying a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address if the device has one (otherwise this is treated as \"preserve\"). \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"preserve\" (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_DUPLEX N_("Can be specified only when \"auto-negotiate\" is \"off\". In that case, statically configures the device to use that specified duplex mode, either \"half\" or \"full\". Must be set together with the \"speed\" property if specified. Before specifying a duplex mode be sure your device supports it.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK N_("With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting \"FE:FF:FF:00:00:00\" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the \"random\" or \"stable\" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of \"FE:FF:FF:00:00:00 68:F7:28:00:00:00\" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of \"02:00:00:00:00:00 00:00:00:00:00:00\" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, \"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00\" will create a fully scrambled MAC address, randomly locally or globally administered.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_MAC_ADDRESS N_("If specified, this connection will only apply to the Ethernet device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST N_("If specified, this connection will never apply to the Ethernet device whose permanent MAC address matches an address in the list.  Each MAC address is in the standard hex-digits-and-colons notation (00:11:22:33:44:55).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_PORT N_("Specific port type to use if the device supports multiple attachment methods.  One of \"tp\" (Twisted Pair), \"aui\" (Attachment Unit Interface), \"bnc\" (Thin Ethernet) or \"mii\" (Media Independent Interface). If the device supports only one port type, this setting is ignored.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_S390_NETTYPE N_("s390 network device type; one of \"qeth\", \"lcs\", or \"ctc\", representing the different types of virtual network devices available on s390 systems.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_S390_OPTIONS N_("Dictionary of key/value pairs of s390-specific device options.  Both keys and values must be strings.  Allowed keys include \"portno\", \"layer2\", \"portname\", \"protocol\", among others.  Key names must contain only alphanumeric characters (ie, [a-zA-Z0-9]).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_S390_SUBCHANNELS N_("Identifies specific subchannels that this network device uses for communication with z/VM or s390 host.  Like the \"mac-address\" property for non-z/VM devices, this property can be used to ensure this connection only applies to the network device that uses these subchannels.  The list should contain exactly 3 strings, and each string may only be composed of hexadecimal characters and the period (.) character.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_SPEED N_("Can be set to a value greater than zero only when \"auto-negotiate\" is \"off\". In that case, statically configures the device to use that specified speed. In Mbit/s, ie 100 == 100Mbit/s. Must be set together with the \"duplex\" property when non-zero. Before specifying a speed value be sure your device supports it.")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_WAKE_ON_LAN N_("The NMSettingWiredWakeOnLan options to enable. Not all devices support all options. May be any combination of NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST (0x4), NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST (0x8), NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST (0x10), NM_SETTING_WIRED_WAKE_ON_LAN_ARP (0x20), NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC (0x40) or the special values NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (0x1) (to use global settings) and NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (0x8000) (to disable management of Wake-on-LAN in NetworkManager).")
+#define DESCRIBE_DOC_NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD N_("If specified, the password used with magic-packet-based Wake-on-LAN, represented as an Ethernet MAC address.  If NULL, no password will be required.")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_ENCAPSULATION N_("Encapsulation of ADSL connection.  Can be \"vcmux\" or \"llc\".")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_PASSWORD N_("Password used to authenticate with the ADSL service.")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_PROTOCOL N_("ADSL connection protocol.  Can be \"pppoa\", \"pppoe\" or \"ipoatm\".")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_USERNAME N_("Username used to authenticate with the ADSL service.")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_VCI N_("VCI of ADSL connection")
+#define DESCRIBE_DOC_NM_SETTING_ADSL_VPI N_("VPI of ADSL connection")
+#define DESCRIBE_DOC_NM_SETTING_BLUETOOTH_BDADDR N_("The Bluetooth address of the device.")
+#define DESCRIBE_DOC_NM_SETTING_BLUETOOTH_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_BLUETOOTH_TYPE N_("Either \"dun\" for Dial-Up Networking connections or \"panu\" for Personal Area Networking connections to devices supporting the NAP profile.")
+#define DESCRIBE_DOC_NM_SETTING_BOND_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_BOND_OPTIONS N_("Dictionary of key/value pairs of bonding options.  Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, [a-zA-Z0-9]).")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_AGEING_TIME N_("The Ethernet MAC address aging time, in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_FORWARD_DELAY N_("The Spanning Tree Protocol (STP) forwarding delay, in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_FORWARD_MASK N_("A mask of group addresses to forward. Usually, group addresses in the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to standards. This property is a mask of 16 bits, each corresponding to a group address in that range that must be forwarded. The mask can't have bits 0, 1 or 2 set because they are used for STP, MAC pause frames and LACP.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_HELLO_TIME N_("The Spanning Tree Protocol (STP) hello time, in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAC_ADDRESS N_("If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the \"ethernet.cloned-mac-address\" is referred instead to generate the initial MAC address. Note that setting \"ethernet.cloned-mac-address\" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAX_AGE N_("The Spanning Tree Protocol (STP) maximum message age, in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_SNOOPING N_("Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PRIORITY N_("Sets the Spanning Tree Protocol (STP) priority for this bridge.  Lower values are \"better\"; the lowest priority bridge will be elected the root bridge.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_STP N_("Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE N_("Enables or disables \"hairpin mode\" for the port, which allows frames to be sent back out through the port the frame was received on.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PATH_COST N_("The Spanning Tree Protocol (STP) port cost for destinations via this port.")
+#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PRIORITY N_("The Spanning Tree Protocol (STP) priority of this bridge port.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_NUMBER N_("The number to dial to establish the connection to the CDMA-based mobile broadband network, if any.  If not specified, the default number (#777) is used when required.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_PASSWORD N_("The password used to authenticate with the network, if required.  Many providers do not require a password, or accept any password.  But if a password is required, it is specified here.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_CDMA_USERNAME N_("The username used to authenticate with the network, if required.  Many providers do not require a username, or accept any username.  But if a username is required, it is specified here.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTH_RETRIES N_("The number of retries for the authentication. Zero means to try indefinitely; -1 means to use a global default. If the global default is not set, the authentication retries for 3 times before failing the connection. Currently this only applies to 802-1x authentication.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT N_("Whether or not the connection should be automatically connected by NetworkManager when the resources for the connection are available. TRUE to automatically activate the connection, FALSE to require manual intervention to activate the connection.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY N_("The autoconnect priority. If the connection is set to autoconnect, connections with higher priority will be preferred. Defaults to 0. The higher number means higher priority.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES N_("The number of times a connection should be tried when autoactivating before giving up. Zero means forever, -1 means the global default (4 times if not overridden). Setting this to 1 means to try activation only once before blocking autoconnect. Note that after a timeout, NetworkManager will try to autoconnect again.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES N_("Whether or not slaves of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for master connections. The permitted values are: 0: leave slave connections untouched, 1: activate all the slave connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-slaves is read to determine the real value. If it is default as well, this fallbacks to 0.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT N_("If greater than zero, delay success of IP addressing until either the timeout is reached, or an IP gateway replies to a ping.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_ID N_("A human readable unique identifier for the connection, like \"Work Wi-Fi\" or \"T-Mobile 3G\".")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_INTERFACE_NAME N_("The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_LLDP N_("Whether LLDP is enabled for the connection.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_MASTER N_("Interface name of the master device or UUID of the master connection.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_METERED N_("Whether the connection is metered. When updating this property on a currently activated connection, the change takes effect immediately.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_PERMISSIONS N_("An array of strings defining what access a given user has to this connection.  If this is NULL or empty, all users are allowed to access this connection; otherwise users are allowed if and only if they are in this list.  When this is not empty, the connection can be active only when one of the specified users is logged into an active session.  Each entry is of the form \"[type]:[id]:[reserved]\"; for example, \"user:dcbw:blah\". At this time only the \"user\" [type] is allowed.  Any other values are ignored and reserved for future use.  [id] is the username that this permission refers to, which may not contain the \":\" character. Any [reserved] information present must be ignored and is reserved for future use.  All of [type], [id], and [reserved] must be valid UTF-8.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_READ_ONLY N_("FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_SECONDARIES N_("List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_SLAVE_TYPE N_("Setting name of the device type of this slave's master connection (eg, \"bond\"), or NULL if this connection is not a slave.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("Token to generate stable IDs for the connection. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. Note that also the interface name of the activating connection and a per-host secret key is included into the address generation so that the same stable-id on different hosts/devices yields different addresses. If the value is unset, an ID unique for the connection is used. Specifying a stable-id allows multiple connections to generate the same addresses. Another use is to generate IDs at runtime via dynamic substitutions. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-boot, or every time. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}/${BOOT}\" to create a unique id for this connection that changes with every reboot. Note that two connections only use the same effective id if their stable-id is also identical before performing dynamic substitutions.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("A universally unique identifier for the connection, for example generated with libuuid.  It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network.  For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\").")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_ZONE N_("The trust level of a the connection.  Free form case-insensitive string (for example \"Home\", \"Work\", \"Public\").  NULL or unspecified zone means the connection will be placed in the default zone as defined by the firewall. When updating this property on a currently activated connection, the change takes effect immediately.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_FLAGS N_("Specifies the NMSettingDcbFlags for the DCB FCoE application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_MODE N_("The FCoE controller mode; either \"fabric\" (default) or \"vn2vn\".")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_PRIORITY N_("The highest User Priority (0 - 7) which FCoE frames should use, or -1 for default priority.  Only used when the \"app-fcoe-flags\" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FIP_FLAGS N_("Specifies the NMSettingDcbFlags for the DCB FIP application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FIP_PRIORITY N_("The highest User Priority (0 - 7) which FIP frames should use, or -1 for default priority.  Only used when the \"app-fip-flags\" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_ISCSI_FLAGS N_("Specifies the NMSettingDcbFlags for the DCB iSCSI application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_APP_ISCSI_PRIORITY N_("The highest User Priority (0 - 7) which iSCSI frames should use, or -1 for default priority. Only used when the \"app-iscsi-flags\" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_BANDWIDTH N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the percentage of bandwidth of the priority's assigned group that the priority may use.  The sum of all percentages for priorities which belong to the same group must total 100 percents.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_FLOW_CONTROL N_("An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the corresponding priority should transmit priority pause.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS N_("Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH N_("An array of 8 uint values, where the array index corresponds to the Priority Group ID (0 - 7) and the value indicates the percentage of link bandwidth allocated to that group.  Allowed values are 0 - 100, and the sum of all values must total 100 percents.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_GROUP_FLAGS N_("Specifies the NMSettingDcbFlags for DCB Priority Groups.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_GROUP_ID N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the Priority Group ID.  Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted group.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH N_("An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group.")
+#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped.")
+#define DESCRIBE_DOC_NM_SETTING_DUMMY_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_GENERIC_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_GSM_APN N_("The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network.  The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_DEVICE_ID N_("The device unique identifier (as given by the WWAN management service) which this connection applies to.  If given, the connection will only apply to the specified device.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_HOME_ONLY N_("When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_GSM_NETWORK_ID N_("The Network ID (GSM LAI format, ie MCC-MNC) to force specific network registration.  If the Network ID is specified, NetworkManager will attempt to force the device to register only on the specified network. This can be used to ensure that the device does not roam when direct roaming control of the device is not otherwise possible.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_NUMBER N_("Number to dial when establishing a PPP data session with the GSM-based mobile broadband network.  Many modems do not require PPP for connections to the mobile network and thus this property should be left blank, which allows NetworkManager to select the appropriate settings automatically.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_PASSWORD N_("The password used to authenticate with the network, if required.  Many providers do not require a password, or accept any password.  But if a password is required, it is specified here.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_PIN N_("If the SIM is locked with a PIN it must be unlocked before any other operations are requested.  Specify the PIN here to allow operation of the device.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_PIN_FLAGS N_("Flags indicating how to handle the \"pin\" property.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_SIM_ID N_("The SIM card unique identifier (as given by the WWAN management service) which this connection applies to.  If given, the connection will apply to any device also allowed by \"device-id\" which contains a SIM card matching the given identifier.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_SIM_OPERATOR_ID N_("A MCC/MNC string like \"310260\" or \"21601\" identifying the specific mobile network operator which this connection applies to.  If given, the connection will apply to any device also allowed by \"device-id\" and \"sim-id\" which contains a SIM card provisioned by the given operator.")
+#define DESCRIBE_DOC_NM_SETTING_GSM_USERNAME N_("The username used to authenticate with the network, if required.  Many providers do not require a username, or accept any username.  But if a username is required, it is specified here.")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_MAC_ADDRESS N_("If specified, this connection will only apply to the IPoIB device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_P_KEY N_("The InfiniBand P_Key to use for this device. A value of -1 means to use the default P_Key (aka \"the P_Key at index 0\").  Otherwise it is a 16-bit unsigned integer, whose high bit is set if it is a \"full membership\" P_Key.")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_PARENT N_("The interface name of the parent device of this device. Normally NULL, but if the \"p_key\" property is set, then you must specify the base device by setting either this property or \"mac-address\".")
+#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_TRANSPORT_MODE N_("The IP-over-InfiniBand transport mode. Either \"datagram\" or \"connected\".")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT N_("How many additional levels of encapsulation are permitted to be prepended to packets. This property applies only to IPv6 tunnels.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_FLOW_LABEL N_("The flow label to assign to tunnel packets. This property applies only to IPv6 tunnels.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_INPUT_KEY N_("The key used for tunnel input packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_LOCAL N_("The local endpoint of the tunnel; the value can be empty, otherwise it must contain an IPv4 or IPv6 address.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_MODE N_("The tunneling mode, for example NM_IP_TUNNEL_MODE_IPIP (1) or NM_IP_TUNNEL_MODE_GRE (2).")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_OUTPUT_KEY N_("The key used for tunnel output packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_PARENT N_("If given, specifies the parent interface name or parent connection UUID the new device will be bound to so that tunneled packets will only be routed via that interface.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY N_("Whether to enable Path MTU Discovery on this tunnel.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_REMOTE N_("The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 address.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_TOS N_("The type of service (IPv4) or traffic class (IPv6) field to be set on tunneled packets.")
+#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_TTL N_("The TTL to assign to tunneled packets. 0 is a special value meaning that packets inherit the TTL value.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ADDRESSES N_("Array of IP addresses.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DAD_TIMEOUT N_("Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network.  If an address conflict is detected, the activation will fail.  A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or 3 seconds).  A value greater than zero is a timeout in milliseconds.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID N_("A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options. When the property is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which case the first byte is assumed to be the 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC address). If the property is not a hex string it is considered as a non-hardware-address client ID and the 'type' field is set to 0.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_FQDN N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified FQDN will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-hostname\" are mutually exclusive and cannot be set at the same time.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer.  If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("Intra-connection DNS priority. The relative priority to be used when determining the order of DNS servers in resolv.conf.  A lower value means that servers will be on top of the file.  Zero selects the default value, which is 50 for VPNs and 100 for other connections.  Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. For that, just specify the DNS servers in the desired order. When multiple devices have configurations with the same priority, the one with an active default route will be preferred. Note that when using dns=dnsmasq the order is meaningless since dnsmasq forwards queries to all known servers at the same time. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_SEARCH N_("Array of DNS search domains.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out.  Note that at least one IP configuration must succeed or overall network configuration will still fail.  For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration.  The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_METRIC N_("The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is chosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_TABLE N_("Enable policy routing (source routing) and set the routing table used when adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes and static routes. But note that static routes can individually overwrite the setting by explicitly specifying a non-zero routing table. If the table setting is left at zero, it is eligible to be overwritten via global configuration. If the property is zero even after applying the global configuration value, policy routing is disabled for the address family of this connection. Policy routing disabled means that NetworkManager will add all routes to the main table (except static routes that explicitly configure a different table). Additionally, NetworkManager will not delete any extraneous routes from tables except the main table. This is to preserve backward compatibility for users who manage routing tables outside of NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTES N_("Array of IP routes.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE N_("Configure method for creating the address for use with RFC4862 IPv6 Stateless Address Autoconfiguration. The permitted values are: NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 (0) or NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY (1). If the property is set to EUI64, the addresses will be generated using the interface tokens derived from hardware address. This makes the host part of the address to stay constant, making it possible to track host's presence when it changes networks. The address changes when the interface hardware is replaced. The value of stable-privacy enables use of cryptographically secure hash of a secret host-specific key along with the connection's stable-id and the network address as specified by RFC7217. This makes it impossible to use the address track host's presence, and makes the address stable when the network interface hardware is replaced. On D-Bus, the absence of an addr-gen-mode setting equals enabling stable-privacy. For keyfile plugin, the absence of the setting on disk means EUI64 so that the property doesn't change on upgrade from older versions. Note that this setting is distinct from the Privacy Extensions as configured by \"ip6-privacy\" property and it does not affect the temporary addresses configured with this option.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDRESSES N_("Array of IP addresses.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DAD_TIMEOUT N_("Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network.  If an address conflict is detected, the activation will fail.  A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or 3 seconds).  A value greater than zero is a timeout in milliseconds.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer.  If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS N_("Array of IP addresses of DNS servers.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_PRIORITY N_("Intra-connection DNS priority. The relative priority to be used when determining the order of DNS servers in resolv.conf.  A lower value means that servers will be on top of the file.  Zero selects the default value, which is 50 for VPNs and 100 for other connections.  Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. For that, just specify the DNS servers in the desired order. When multiple devices have configurations with the same priority, the one with an active default route will be preferred. Note that when using dns=dnsmasq the order is meaningless since dnsmasq forwards queries to all known servers at the same time. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_SEARCH N_("Array of DNS search domains.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IP6_PRIVACY N_("Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941.  If enabled, it makes the kernel generate a temporary IPv6 address in addition to the public one generated from MAC address via modified EUI-64.  This enhances privacy, but could cause problems in some applications, on the other hand.  The permitted values are: -1: unknown, 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary addresses). Having a per-connection setting set to \"-1\" (unknown) means fallback to global configuration \"ipv6.ip6-privacy\". If also global configuration is unspecified or set to \"-1\", fallback to read \"/proc/sys/net/ipv6/conf/default/use_tempaddr\". Note that this setting is distinct from the Stable Privacy addresses that can be enabled with the \"addr-gen-mode\" property's \"stable-privacy\" setting as another way of avoiding host tracking with IPv6 addresses.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out.  Note that at least one IP configuration must succeed or overall network configuration will still fail.  For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration.  The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_METRIC N_("The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is chosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_TABLE N_("Enable policy routing (source routing) and set the routing table used when adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes and static routes. But note that static routes can individually overwrite the setting by explicitly specifying a non-zero routing table. If the table setting is left at zero, it is eligible to be overwritten via global configuration. If the property is zero even after applying the global configuration value, policy routing is disabled for the address family of this connection. Policy routing disabled means that NetworkManager will add all routes to the main table (except static routes that explicitly configure a different table). Additionally, NetworkManager will not delete any extraneous routes from tables except the main table. This is to preserve backward compatibility for users who manage routing tables outside of NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTES N_("Array of IP routes.")
+#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_TOKEN N_("Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_ENCRYPT N_("Whether the transmitted traffic must be encrypted.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CAK N_("The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CAK_FLAGS N_("Flags indicating how to handle the \"mka-cak\" property.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CKN N_("The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_MODE N_("Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_PORT N_("The port component of the SCI (Secure Channel Identifier), between 1 and 65534.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_VALIDATION N_("Specifies the validation mode for incoming frames.")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_MODE N_("The macvlan mode, which specifies the communication mechanism between multiple macvlans on the same lower device.")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this MAC-VLAN interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PROMISCUOUS N_("Whether the interface should be put in promiscuous mode.")
+#define DESCRIBE_DOC_NM_SETTING_MACVLAN_TAP N_("Whether the interface should be a MACVTAP.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_FAIL_MODE N_("The bridge failure mode. One of \"secure\", \"standalone\" or empty.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE N_("Enable or disable multicast snooping.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_RSTP_ENABLE N_("Enable or disable RSTP.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_STP_ENABLE N_("Enable or disable STP.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_INTERFACE_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_INTERFACE_TYPE N_("The interface type. Either \"internal\", or empty.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PATCH_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PATCH_PEER N_("Specifies the unicast destination IP address of a remote OpenVSwitch bridge port to connect to.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_DOWNDELAY N_("The time port must be inactive in order to be considered down.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_MODE N_("Bonding mode. One of \"active-backup\", \"balance-slb\", or \"balance-tcp\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_UPDELAY N_("The time port must be active befor it starts forwarding traffic.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_LACP N_("LACP mode. One of \"active\", \"off\", or \"passive\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_TAG N_("The VLAN tag in the range 0-4095.")
+#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_VLAN_MODE N_("The VLAN mode. One of \"access\", \"native-tagged\", \"native-untagged\", \"trunk\" or unset.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_BAUD N_("If non-zero, instruct pppd to set the serial port to the specified baudrate.  This value should normally be left as 0 to automatically choose the speed.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_CRTSCTS N_("If TRUE, specify that pppd should set the serial port to use hardware flow control with RTS and CTS signals.  This value should normally be set to FALSE.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_LCP_ECHO_FAILURE N_("If non-zero, instruct pppd to presume the connection to the peer has failed if the specified number of LCP echo-requests go unanswered by the peer.  The \"lcp-echo-interval\" property must also be set to a non-zero value if this property is used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_LCP_ECHO_INTERVAL N_("If non-zero, instruct pppd to send an LCP echo-request frame to the peer every n seconds (where n is the specified value).  Note that some PPP peers will respond to echo requests and some will not, and it is not possible to autodetect this.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_MPPE_STATEFUL N_("If TRUE, stateful MPPE is used.  See pppd documentation for more information on stateful MPPE.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_MRU N_("If non-zero, instruct pppd to request that the peer send packets no larger than the specified size.  If non-zero, the MRU should be between 128 and 16384.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_MTU N_("If non-zero, instruct pppd to send packets no larger than the specified size.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NO_VJ_COMP N_("If TRUE, Van Jacobsen TCP header compression will not be requested.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NOAUTH N_("If TRUE, do not require the other side (usually the PPP server) to authenticate itself to the client.  If FALSE, require authentication from the remote side.  In almost all cases, this should be TRUE.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NOBSDCOMP N_("If TRUE, BSD compression will not be requested.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_NODEFLATE N_("If TRUE, \"deflate\" compression will not be requested.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_CHAP N_("If TRUE, the CHAP authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_EAP N_("If TRUE, the EAP authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_MSCHAP N_("If TRUE, the MSCHAP authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_MSCHAPV2 N_("If TRUE, the MSCHAPv2 authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REFUSE_PAP N_("If TRUE, the PAP authentication method will not be used.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REQUIRE_MPPE N_("If TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for the PPP session.  If either 64-bit or 128-bit MPPE is not available the session will fail.  Note that MPPE is not used on mobile broadband connections.")
+#define DESCRIBE_DOC_NM_SETTING_PPP_REQUIRE_MPPE_128 N_("If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be required for the PPP session, and the \"require-mppe\" property must also be set to TRUE.  If 128-bit MPPE is not available the session will fail.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_PARENT N_("If given, specifies the parent interface name on which this PPPoE connection should be created.  If this property is not specified, the connection is activated on the interface specified in \"interface-name\" of NMSettingConnection.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_PASSWORD N_("Password used to authenticate with the PPPoE service.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_SERVICE N_("If specified, instruct PPPoE to only initiate sessions with access concentrators that provide the specified service.  For most providers, this should be left blank.  It is only required if there are multiple access concentrators or a specific service is known to be required.")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_USERNAME N_("Username used to authenticate with the PPPoE service.")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_BROWSER_ONLY N_("Whether the proxy configuration is for browser only.")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_METHOD N_("Method for proxy configuration, Default is NM_SETTING_PROXY_METHOD_NONE (0)")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_PAC_SCRIPT N_("PAC script for the connection.")
+#define DESCRIBE_DOC_NM_SETTING_PROXY_PAC_URL N_("PAC URL for obtaining PAC file.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_BAUD N_("Speed to use for communication over the serial port.  Note that this value usually has no effect for mobile broadband modems as they generally ignore speed settings and use the highest available speed.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_BITS N_("Byte-width of the serial communication. The 8 in \"8n1\" for example.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_PARITY N_("Parity setting of the serial port.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_SEND_DELAY N_("Time to delay between each byte sent to the modem, in microseconds.")
+#define DESCRIBE_DOC_NM_SETTING_SERIAL_STOPBITS N_("Number of stop bits for communication on the serial port.  Either 1 or 2. The 1 in \"8n1\" for example.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_CONFIG N_("The JSON configuration for the team network interface.  The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used.  See man teamd.conf for the format details.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_CONFIG N_("The JSON configuration for the team port. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_TUN_GROUP N_("The group ID which will own the device. If set to NULL everyone will be able to use the device.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_MODE N_("The operating mode of the virtual device. Allowed values are NM_SETTING_TUN_MODE_TUN (1) to create a layer 3 device and NM_SETTING_TUN_MODE_TAP (2) to create an Ethernet-like layer 2 one.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_MULTI_QUEUE N_("If the property is set to TRUE, the interface will support multiple file descriptors (queues) to parallelize packet sending or receiving. Otherwise, the interface will only support a single queue.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_TUN_OWNER N_("The user ID which will own the device. If set to NULL everyone will be able to use the device.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_PI N_("If TRUE the interface will prepend a 4 byte header describing the physical interface to the packets.")
+#define DESCRIBE_DOC_NM_SETTING_TUN_VNET_HDR N_("If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio network header.")
+#define DESCRIBE_DOC_NM_SETTING_USER_DATA N_("A dictionary of key/value pairs with user data. This data is ignored by NetworkManager and can be used at the users discretion. The keys only support a strict ascii format, but the values can be arbitrary UTF8 strings up to a certain length.")
+#define DESCRIBE_DOC_NM_SETTING_USER_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_EGRESS_PRIORITY_MAP N_("For outgoing packets, a list of mappings from Linux SKB priorities to 802.1p priorities.  The mapping is given in the format \"from:to\" where both \"from\" and \"to\" are unsigned integers, ie \"7:3\".")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_FLAGS N_("One or more flags which control the behavior and features of the VLAN interface.  Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use of the GVRP protocol), and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose binding of the interface to its master device's operating state). NM_VLAN_FLAG_MVRP (0x8) (use of the MVRP protocol). The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, but it used to be 0. To preserve backward compatibility, the default-value in the D-Bus API continues to be 0 and a missing property on D-Bus is still considered as 0.")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_ID N_("The VLAN identifier that the interface created by this connection should be assigned. The valid range is from 0 to 4094, without the reserved id 4095.")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_INGRESS_PRIORITY_MAP N_("For incoming packets, a list of mappings from 802.1p priorities to Linux SKB priorities.  The mapping is given in the format \"from:to\" where both \"from\" and \"to\" are unsigned integers, ie \"7:3\".")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_VLAN_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this VLAN interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_DATA N_("Dictionary of key/value pairs of VPN plugin specific data.  Both keys and values must be strings.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_VPN_PERSISTENT N_("If the VPN service supports persistence, and this property is TRUE, the VPN will attempt to stay connected across link changes and outages, until explicitly disconnected.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_SECRETS N_("Dictionary of key/value pairs of VPN plugin specific secrets like passwords or private keys.  Both keys and values must be strings.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_SERVICE_TYPE N_("D-Bus service name of the VPN plugin that this setting uses to connect to its network.  i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_TIMEOUT N_("Timeout for the VPN service to establish the connection. Some services may take quite a long time to connect. Value of 0 means a default timeout, which is 60 seconds (unless overridden by vpn.timeout in configuration file). Values greater than zero mean timeout in seconds.")
+#define DESCRIBE_DOC_NM_SETTING_VPN_USER_NAME N_("If the VPN connection requires a user name for authentication, that name should be provided here.  If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty.  If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_AGEING N_("Specifies the lifetime in seconds of FDB entries learnt by the kernel.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_DESTINATION_PORT N_("Specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_ID N_("Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to use.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_L2_MISS N_("Specifies whether netlink LL ADDR miss notifications are generated.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_L3_MISS N_("Specifies whether netlink IP ADDR miss notifications are generated.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_LEARNING N_("Specifies whether unknown source link layer addresses and IP addresses are entered into the VXLAN device forwarding database.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_LIMIT N_("Specifies the maximum number of FDB entries. A value of zero means that the kernel will store unlimited entries.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_LOCAL N_("If given, specifies the source IP address to use in outgoing packets.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_PARENT N_("If given, specifies the parent interface name or parent connection UUID.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_PROXY N_("Specifies whether ARP proxy is turned on.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_REMOTE N_("Specifies the unicast destination IP address to use in outgoing packets when the destination link layer address is not known in the VXLAN device forwarding database, or the multicast IP address to join.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_RSC N_("Specifies whether route short circuit is turned on.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_SOURCE_PORT_MAX N_("Specifies the maximum UDP source port to communicate to the remote VXLAN tunnel endpoint.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_SOURCE_PORT_MIN N_("Specifies the minimum UDP source port to communicate to the remote VXLAN tunnel endpoint.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_TOS N_("Specifies the TOS value to use in outgoing packets.")
+#define DESCRIBE_DOC_NM_SETTING_VXLAN_TTL N_("Specifies the time-to-live value to use in outgoing packets.")
+#define DESCRIBE_DOC_NM_SETTING_WIMAX_MAC_ADDRESS N_("If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1")
+#define DESCRIBE_DOC_NM_SETTING_WIMAX_NAME N_("The setting's name, which uniquely identifies the setting within the connection.  Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_WIMAX_NETWORK_NAME N_("Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1")
diff --git a/clients/common/settings-docs.xsl b/clients/common/settings-docs.xsl
new file mode 100644
index 00000000..0d08a0c8
--- /dev/null
+++ b/clients/common/settings-docs.xsl
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:output
+      method="text"
+      doctype-public="-//OASIS//DTD DocBook XML V4.3//EN"
+      doctype-system="http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+      />
+
+  <xsl:template match="nm-setting-docs">/* Generated file. Do not edit. */
+
+<xsl:apply-templates select="setting" mode="properties"><xsl:sort select="@name"/></xsl:apply-templates>
+  </xsl:template>
+
+
+  <xsl:template match="setting" mode="properties">
+<xsl:apply-templates select="property">
+    <xsl:sort select="@name"/>
+    <xsl:with-param name="setting_name_upper" select="@name_upper"/>
+</xsl:apply-templates>
+
+</xsl:template>
+
+  <xsl:template match="property">
+    <xsl:param name="setting_name_upper" />
+    <xsl:variable name="docs">
+      <xsl:call-template name="escape_quotes">
+        <xsl:with-param name="string" select="@description"/>
+      </xsl:call-template>
+    </xsl:variable>#define DESCRIBE_DOC_NM_SETTING_<xsl:value-of select="$setting_name_upper"/>_<xsl:value-of select="@name_upper"/> N_("<xsl:value-of select="$docs"/>")
+</xsl:template>
+
+  <xsl:template match="setting" mode="settings">
+        { "<xsl:value-of select="@name"/>", setting_<xsl:value-of select="translate(@name,'-','_')"/>, <xsl:value-of select="count(./property)"/> },</xsl:template>
+
+  <xsl:template name="escape_quotes">
+    <xsl:param name="string" />
+      <xsl:choose>
+        <xsl:when test="contains($string, '&quot;')">
+          <xsl:value-of select="substring-before($string, '&quot;')" />\&quot;<xsl:call-template name="escape_quotes"><xsl:with-param name="string" select="substring-after($string, '&quot;')" /></xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="$string" />
+        </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/clients/common/tests/test-general.c b/clients/common/tests/test-general.c
new file mode 100644
index 00000000..64efd14d
--- /dev/null
+++ b/clients/common/tests/test-general.c
@@ -0,0 +1,162 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * 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, 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 2017 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "NetworkManager.h"
+
+#include "nm-utils/nm-hash-utils.h"
+
+#include "nm-meta-setting-access.h"
+
+#include "nm-utils/nm-test-utils.h"
+
+/*****************************************************************************/
+
+static void
+test_client_meta_check (void)
+{
+	const NMMetaSettingInfoEditor *const*infos_p;
+	NMMetaSettingType m;
+	guint p;
+
+	G_STATIC_ASSERT (G_STRUCT_OFFSET (NMMetaAbstractInfo, meta_type) == G_STRUCT_OFFSET (NMMetaSettingInfoEditor, meta_type));
+	G_STATIC_ASSERT (G_STRUCT_OFFSET (NMMetaAbstractInfo, meta_type) == G_STRUCT_OFFSET (NMMetaPropertyInfo, meta_type));
+
+	for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++) {
+		const NMMetaSettingInfo *info = &nm_meta_setting_infos[m];
+		GType gtype;
+
+		g_assert (info);
+		g_assert (info->meta_type == m);
+		g_assert (info->setting_name);
+		g_assert (info->get_setting_gtype);
+
+		gtype = info->get_setting_gtype ();
+		g_assert (gtype != NM_TYPE_SETTING);
+
+		{
+			nm_auto_unref_gtypeclass GTypeClass *gclass = g_type_class_ref (gtype);
+
+			g_assert (G_TYPE_CHECK_CLASS_TYPE (gclass, gtype));
+		}
+		{
+			gs_unref_object NMSetting *setting = g_object_new (gtype, NULL);
+
+			g_assert (NM_IS_SETTING (setting));
+			g_assert (G_TYPE_CHECK_INSTANCE_TYPE (setting, gtype));
+			g_assert_cmpstr (nm_setting_get_name (setting), ==, info->setting_name);
+		}
+	}
+
+	for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++) {
+		const NMMetaSettingInfoEditor *info = &nm_meta_setting_infos_editor[m];
+
+		g_assert (info);
+		g_assert (info->meta_type == &nm_meta_type_setting_info_editor);
+		g_assert (info->general);
+		g_assert (info->general == &nm_meta_setting_infos[m]);
+
+		g_assert_cmpstr (info->general->setting_name, ==, info->meta_type->get_name ((const NMMetaAbstractInfo *) info, FALSE));
+		g_assert_cmpstr ("name", ==, info->meta_type->get_name ((const NMMetaAbstractInfo *) info, TRUE));
+
+		g_assert (info->properties_num == NM_PTRARRAY_LEN (info->properties));
+
+		if (info->properties_num) {
+			gs_unref_hashtable GHashTable *property_names = g_hash_table_new (nm_str_hash, g_str_equal);
+
+			g_assert (info->properties);
+			for (p = 0; p < info->properties_num; p++) {
+				const NMMetaPropertyInfo *pi = info->properties[p];
+
+				g_assert (pi);
+				g_assert (pi->meta_type == &nm_meta_type_property_info);
+				g_assert (pi->setting_info == info);
+				g_assert (pi->property_name);
+
+				g_assert (nm_g_hash_table_add (property_names, (gpointer) pi->property_name));
+
+				g_assert_cmpstr (pi->property_name, ==, pi->meta_type->get_name ((const NMMetaAbstractInfo *) pi, FALSE));
+				g_assert_cmpstr (pi->property_name, ==, pi->meta_type->get_name ((const NMMetaAbstractInfo *) pi, TRUE));
+
+				g_assert (pi->property_type);
+				g_assert (pi->property_type->get_fcn);
+			}
+			g_assert (!info->properties[info->properties_num]);
+		} else
+			g_assert (!info->properties);
+
+		if (info->valid_parts) {
+			gsize i, l;
+			gs_unref_hashtable GHashTable *dup = g_hash_table_new (NULL, NULL);
+
+			l = NM_PTRARRAY_LEN (info->valid_parts);
+			g_assert (l >= 2);
+
+			for (i = 0; info->valid_parts[i]; i++) {
+				g_assert (info->valid_parts[i]->setting_info);
+				g_assert (nm_g_hash_table_add (dup, (gpointer) info->valid_parts[i]->setting_info));
+
+				if (i == 0) {
+					g_assert (info->valid_parts[i]->setting_info == &nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_CONNECTION]);
+					g_assert (info->valid_parts[i]->mandatory);
+				}
+				if (i == 1) {
+					g_assert (info->valid_parts[i]->setting_info == &nm_meta_setting_infos_editor[m]);
+					g_assert (info->valid_parts[i]->mandatory);
+				}
+			}
+			g_assert (i == l);
+		}
+	}
+
+	for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++) {
+		const NMMetaSettingInfoEditor *info = &nm_meta_setting_infos_editor[m];
+
+		g_assert (nm_meta_setting_info_editor_find_by_name (info->general->setting_name, FALSE) == info);
+		g_assert (nm_meta_setting_info_editor_find_by_gtype (info->general->get_setting_gtype ()) == info);
+
+		for (p = 0; p < info->properties_num; p++) {
+			const NMMetaPropertyInfo *pi = info->properties[p];
+
+			g_assert (nm_meta_setting_info_editor_get_property_info (info, pi->property_name) == pi);
+			g_assert (nm_meta_property_info_find_by_name (info->general->setting_name, pi->property_name) == pi);
+		}
+	}
+
+	infos_p = nm_meta_setting_infos_editor_p ();
+	g_assert (infos_p);
+	for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++)
+		g_assert (infos_p[m] == &nm_meta_setting_infos_editor[m]);
+	g_assert (!infos_p[m]);
+}
+
+/*****************************************************************************/
+
+NMTST_DEFINE ();
+
+int
+main (int argc, char **argv)
+{
+	nmtst_init (&argc, &argv, TRUE);
+
+	g_test_add_func ("/client/meta/check", test_client_meta_check);
+
+	return g_test_run ();
+}
diff --git a/clients/tui/newt/nmt-newt-entry-numeric.c b/clients/tui/newt/nmt-newt-entry-numeric.c
index b79f056a..a52fe868 100644
--- a/clients/tui/newt/nmt-newt-entry-numeric.c
+++ b/clients/tui/newt/nmt-newt-entry-numeric.c
@@ -37,13 +37,15 @@ G_DEFINE_TYPE (NmtNewtEntryNumeric, nmt_newt_entry_numeric, NMT_TYPE_NEWT_ENTRY)
 #define NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_NEWT_ENTRY_NUMERIC, NmtNewtEntryNumericPrivate))
 
 typedef struct {
-	int min, max;
+	gint64 min, max;
+	bool optional;
 } NmtNewtEntryNumericPrivate;
 
 enum {
 	PROP_0,
 	PROP_MINIMUM,
 	PROP_MAXIMUM,
+	PROP_OPTIONAL,
 
 	LAST_PROP
 };
@@ -61,13 +63,38 @@ enum {
  */
 NmtNewtWidget *
 nmt_newt_entry_numeric_new (int width,
-                            int min,
-                            int max)
+                            gint64 min,
+                            gint64 max)
+{
+	return nmt_newt_entry_numeric_new_full (width,
+	                                        min,
+	                                        max,
+	                                        FALSE);
+}
+
+/**
+ * nmt_newt_entry_numeric_new_full:
+ * @width: the entry's width in characters
+ * @min: the minimum valid value
+ * @max: the maximum valid value
+ * @optional: whether an empty entry is valid
+ *
+ * Creates a new #NmtNewtEntryNumeric, accepting values in the
+ * indicated range.
+ *
+ * Returns: a new #NmtNewtEntryNumeric
+ */
+NmtNewtWidget *
+nmt_newt_entry_numeric_new_full (int width,
+                                 gint64 min,
+                                 gint64 max,
+                                 gboolean optional)
 {
 	return g_object_new (NMT_TYPE_NEWT_ENTRY_NUMERIC,
 	                     "width", width,
 	                     "minimum", min,
 	                     "maximum", max,
+	                     "optional", optional,
 	                     NULL);
 }
 
@@ -95,19 +122,13 @@ newt_entry_numeric_validate (NmtNewtEntry *entry,
                              gpointer      user_data)
 {
 	NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE (entry);
-	int val;
-	char *end;
+	gint64 val;
 
 	if (!*text)
-		return FALSE;
+		return priv->optional ? TRUE : FALSE;
 
-	val = strtoul (text, &end, 10);
-	if (*end)
-		return FALSE;
-	if (val < priv->min || val > priv->max)
-		return FALSE;
-
-	return TRUE;
+	val = _nm_utils_ascii_str_to_int64 (text, 10, priv->min, priv->max, 0);
+	return val != 0 || errno == 0;
 }
 
 static void
@@ -125,7 +146,7 @@ nmt_newt_entry_numeric_constructed (GObject *object)
 	if (!*nmt_newt_entry_get_text (NMT_NEWT_ENTRY (object))) {
 		char buf[32];
 
-		g_snprintf (buf, sizeof (buf), "%d", priv->min);
+		g_snprintf (buf, sizeof (buf), "%lld", (long long) priv->min);
 		nmt_newt_entry_set_text (NMT_NEWT_ENTRY (object), buf);
 	}
 
@@ -142,10 +163,13 @@ nmt_newt_entry_numeric_set_property (GObject      *object,
 
 	switch (prop_id) {
 	case PROP_MINIMUM:
-		priv->min = g_value_get_int (value);
+		priv->min = g_value_get_int64 (value);
 		break;
 	case PROP_MAXIMUM:
-		priv->max = g_value_get_int (value);
+		priv->max = g_value_get_int64 (value);
+		break;
+	case PROP_OPTIONAL:
+		priv->optional = g_value_get_boolean (value);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -163,10 +187,13 @@ nmt_newt_entry_numeric_get_property (GObject    *object,
 
 	switch (prop_id) {
 	case PROP_MINIMUM:
-		g_value_set_int (value, priv->min);
+		g_value_set_int64 (value, priv->min);
 		break;
 	case PROP_MAXIMUM:
-		g_value_set_int (value, priv->max);
+		g_value_set_int64 (value, priv->max);
+		break;
+	case PROP_OPTIONAL:
+		g_value_set_boolean (value, priv->optional);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -195,11 +222,11 @@ nmt_newt_entry_numeric_class_init (NmtNewtEntryNumericClass *entry_class)
 	 */
 	g_object_class_install_property
 		(object_class, PROP_MINIMUM,
-		 g_param_spec_int ("minimum", "", "",
-		                   G_MININT, G_MAXINT, 0,
-		                   G_PARAM_READWRITE |
-		                   G_PARAM_CONSTRUCT_ONLY |
-		                   G_PARAM_STATIC_STRINGS));
+		 g_param_spec_int64 ("minimum", "", "",
+		                     G_MININT64, G_MAXINT64, 0,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_CONSTRUCT_ONLY |
+		                     G_PARAM_STATIC_STRINGS));
 	/**
 	 * NmtNewtEntryNumeric:maximum:
 	 *
@@ -207,9 +234,22 @@ nmt_newt_entry_numeric_class_init (NmtNewtEntryNumericClass *entry_class)
 	 */
 	g_object_class_install_property
 		(object_class, PROP_MAXIMUM,
-		 g_param_spec_int ("maximum", "", "",
-		                   G_MININT, G_MAXINT, G_MAXINT,
-		                   G_PARAM_READWRITE |
-		                   G_PARAM_CONSTRUCT_ONLY |
-		                   G_PARAM_STATIC_STRINGS));
+		 g_param_spec_int64 ("maximum", "", "",
+		                     G_MININT64, G_MAXINT64, G_MAXINT64,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_CONSTRUCT_ONLY |
+		                     G_PARAM_STATIC_STRINGS));
+	/**
+	 * NmtNewtEntryNumeric:optional:
+	 *
+	 * If %TRUE, allow empty string to indicate some default value.
+	 * It means the property is optional and can be left at the default
+	 */
+	g_object_class_install_property
+		(object_class, PROP_OPTIONAL,
+		 g_param_spec_boolean ("optional", "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT_ONLY |
+		                       G_PARAM_STATIC_STRINGS));
 }
diff --git a/clients/tui/newt/nmt-newt-entry-numeric.h b/clients/tui/newt/nmt-newt-entry-numeric.h
index 00e19739..bfcabd88 100644
--- a/clients/tui/newt/nmt-newt-entry-numeric.h
+++ b/clients/tui/newt/nmt-newt-entry-numeric.h
@@ -41,7 +41,12 @@ typedef struct {
 GType nmt_newt_entry_numeric_get_type (void);
 
 NmtNewtWidget *nmt_newt_entry_numeric_new (int width,
-                                           int min,
-                                           int max);
+                                           gint64 min,
+                                           gint64 max);
+
+NmtNewtWidget *nmt_newt_entry_numeric_new_full (int width,
+                                                gint64 min,
+                                                gint64 max,
+                                                gboolean optional);
 
 #endif /* NMT_NEWT_ENTRY_NUMERIC_H */
diff --git a/clients/tui/nm-editor-bindings.c b/clients/tui/nm-editor-bindings.c
index 3753aaa9..647ac8df 100644
--- a/clients/tui/nm-editor-bindings.c
+++ b/clients/tui/nm-editor-bindings.c
@@ -71,45 +71,6 @@ nm_editor_bindings_init (void)
 }
 
 static gboolean
-parse_addr_prefix (const char  *text,
-                   int          family,
-                   char       **addr,
-                   guint32     *prefix)
-{
-	const char *slash;
-	char *addrstr, *end;
-	gboolean valid;
-
-	slash = strchr (text, '/');
-
-	if (slash)
-		addrstr = g_strndup (text, slash - text);
-	else
-		addrstr = g_strdup (text);
-	valid = nm_utils_ipaddr_valid (family, addrstr);
-
-	if (slash) {
-		*prefix = strtoul (slash + 1, &end, 10);
-		if (   *end
-		    || *prefix == 0
-		    || (family == AF_INET && *prefix > 32)
-		    || (family == AF_INET6 && *prefix > 128))
-			valid = FALSE;
-	} else if (prefix) {
-		if (family == AF_INET)
-			*prefix = 32;
-		else
-			*prefix = 128;
-	}
-
-	if (addr && valid)
-		*addr = addrstr;
-	else
-		g_free (addrstr);
-	return valid;
-}
-
-static gboolean
 ip_addresses_with_prefix_to_strv (GBinding     *binding,
                                   const GValue *source_value,
                                   GValue       *target_value,
@@ -146,12 +107,12 @@ ip_addresses_with_prefix_from_strv (GBinding     *binding,
                                     GValue       *target_value,
                                     gpointer      user_data)
 {
-	int family = GPOINTER_TO_INT (user_data);
+	int addr_family = GPOINTER_TO_INT (user_data);
 	char **strings;
 	GPtrArray *addrs;
 	NMIPAddress *addr;
 	char *addrstr;
-	guint32 prefix;
+	int prefix;
 	int i;
 
 	strings = g_value_get_boxed (source_value);
@@ -162,7 +123,7 @@ ip_addresses_with_prefix_from_strv (GBinding     *binding,
 
 	for (i = 0; strings[i]; i++) {
 		if (i >= addrs->len) {
-			if (family == AF_INET)
+			if (addr_family == AF_INET)
 				addr = nm_ip_address_new (AF_INET, "0.0.0.0", 32, NULL);
 			else
 				addr = nm_ip_address_new (AF_INET6, "::", 128, NULL);
@@ -170,11 +131,24 @@ ip_addresses_with_prefix_from_strv (GBinding     *binding,
 		} else
 			addr = addrs->pdata[i];
 
-		if (!parse_addr_prefix (strings[i], family, &addrstr, &prefix)) {
+		if (!nm_utils_parse_inaddr_prefix (addr_family, strings[i], &addrstr, &prefix)) {
 			g_ptr_array_unref (addrs);
 			return FALSE;
 		}
 
+		if (prefix == -1) {
+			if (addr_family == AF_INET) {
+				in_addr_t v4;
+
+				inet_pton (addr_family, addrstr, &v4);
+				if (nm_utils_ip_is_site_local (AF_INET, &v4))
+					prefix = nm_utils_ip4_get_default_prefix (v4);
+				else
+					prefix = 32;
+			} else
+				prefix = 64;
+		}
+
 		nm_ip_address_set_address (addr, addrstr);
 		nm_ip_address_set_prefix (addr, prefix);
 		g_free (addrstr);
@@ -187,7 +161,7 @@ ip_addresses_with_prefix_from_strv (GBinding     *binding,
 
 /**
  * nm_editor_bind_ip_addresses_with_prefix_to_strv:
- * @family: the IP address family
+ * @addr_family: the IP address family
  * @source: the source object (eg, an #NMSettingIP4Config)
  * @source_property: the property on @source to bind (eg,
  *   %NM_SETTING_IP4_CONFIG_ADDRESSES)
@@ -204,7 +178,7 @@ ip_addresses_with_prefix_from_strv (GBinding     *binding,
  * vice versa if %G_BINDING_BIDIRECTIONAL) is specified.
  */
 void
-nm_editor_bind_ip_addresses_with_prefix_to_strv (int            family,
+nm_editor_bind_ip_addresses_with_prefix_to_strv (int            addr_family,
                                                  gpointer       source,
                                                  const gchar   *source_property,
                                                  gpointer       target,
@@ -216,7 +190,7 @@ nm_editor_bind_ip_addresses_with_prefix_to_strv (int            family,
 	                             flags,
 	                             ip_addresses_with_prefix_to_strv,
 	                             ip_addresses_with_prefix_from_strv,
-	                             GINT_TO_POINTER (family), NULL);
+	                             GINT_TO_POINTER (addr_family), NULL);
 }
 
 static gboolean
@@ -225,14 +199,14 @@ ip_addresses_check_and_copy (GBinding     *binding,
                              GValue       *target_value,
                              gpointer      user_data)
 {
-	int family = GPOINTER_TO_INT (user_data);
+	int addr_family = GPOINTER_TO_INT (user_data);
 	char **strings;
 	int i;
 
 	strings = g_value_get_boxed (source_value);
 
 	for (i = 0; strings[i]; i++) {
-		if (!nm_utils_ipaddr_valid (family, strings[i]))
+		if (!nm_utils_ipaddr_valid (addr_family, strings[i]))
 			return FALSE;
 	}
 
@@ -242,7 +216,7 @@ ip_addresses_check_and_copy (GBinding     *binding,
 
 /**
  * nm_editor_bind_ip_addresses_to_strv:
- * @family: the IP address family
+ * @addr_family: the IP address family
  * @source: the source object (eg, an #NMSettingIP4Config)
  * @source_property: the property on @source to bind (eg,
  *   %NM_SETTING_IP4_CONFIG_DNS)
@@ -253,10 +227,10 @@ ip_addresses_check_and_copy (GBinding     *binding,
  *
  * Binds the %G_TYPE_STRV property @source_property on @source to the
  * %G_TYPE_STRV property @target_property on @target, verifying that
- * each string is a valid address of type @family when copying.
+ * each string is a valid address of type @addr_family when copying.
  */
 void
-nm_editor_bind_ip_addresses_to_strv (int            family,
+nm_editor_bind_ip_addresses_to_strv (int            addr_family,
                                      gpointer       source,
                                      const gchar   *source_property,
                                      gpointer       target,
@@ -268,7 +242,7 @@ nm_editor_bind_ip_addresses_to_strv (int            family,
 	                             flags,
 	                             ip_addresses_check_and_copy,
 	                             ip_addresses_check_and_copy,
-	                             GINT_TO_POINTER (family), NULL);
+	                             GINT_TO_POINTER (addr_family), NULL);
 }
 
 static gboolean
@@ -287,11 +261,11 @@ ip_gateway_from_string (GBinding     *binding,
                         GValue       *target_value,
                         gpointer      user_data)
 {
-	int family = GPOINTER_TO_INT (user_data);
+	int addr_family = GPOINTER_TO_INT (user_data);
 	const char *gateway;
 
 	gateway = g_value_get_string (source_value);
-	if (gateway && !nm_utils_ipaddr_valid (family, gateway))
+	if (gateway && !nm_utils_ipaddr_valid (addr_family, gateway))
 		gateway = NULL;
 
 	g_value_set_string (target_value, gateway);
@@ -329,7 +303,7 @@ ip_addresses_to_sensitivity (GBinding     *binding,
 
 /**
  * nm_editor_bind_ip_gateway_to_string:
- * @family: the IP address family
+ * @addr_family: the IP address family
  * @source: the source #NMSettingIPConfig
  * @target: the target object (eg, an #NmtIPEntry)
  * @target_property: the property on @target to bind (eg, "text")
@@ -351,7 +325,7 @@ ip_addresses_to_sensitivity (GBinding     *binding,
  * address.
  */
 void
-nm_editor_bind_ip_gateway_to_string (int                family,
+nm_editor_bind_ip_gateway_to_string (int                addr_family,
                                      NMSettingIPConfig *source,
                                      gpointer           target,
                                      const gchar       *target_property,
@@ -363,7 +337,7 @@ nm_editor_bind_ip_gateway_to_string (int                family,
 	                             flags,
 	                             ip_gateway_to_string,
 	                             ip_gateway_from_string,
-	                             GINT_TO_POINTER (family), NULL);
+	                             GINT_TO_POINTER (addr_family), NULL);
 	g_object_bind_property_full (source, "addresses",
 	                             source, "gateway",
 	                             (flags & G_BINDING_SYNC_CREATE),
@@ -447,14 +421,14 @@ ip_route_transform_from_dest_string (GBinding     *binding,
                                      GValue       *target_value,
                                      gpointer      user_data)
 {
-	int family = GPOINTER_TO_INT (user_data);
+	int addr_family = GPOINTER_TO_INT (user_data);
 	NMIPRoute *route;
 	const char *text;
 	char *addrstr;
-	guint32 prefix;
+	int prefix;
 
 	text = g_value_get_string (source_value);
-	if (!parse_addr_prefix (text, family, &addrstr, &prefix))
+	if (!nm_utils_parse_inaddr_prefix (addr_family, text, &addrstr, &prefix))
 		return FALSE;
 
 	/* Fetch the original property value */
@@ -462,6 +436,21 @@ ip_route_transform_from_dest_string (GBinding     *binding,
 	              g_binding_get_source_property (binding), &route,
 	              NULL);
 
+	if (prefix == -1) {
+		if (addr_family == AF_INET) {
+			in_addr_t v4;
+
+			inet_pton (addr_family, addrstr, &v4);
+			if (nm_utils_ip_is_site_local (AF_INET, &v4)) {
+				prefix = nm_utils_ip4_get_default_prefix (v4);
+				if (v4 & (~nm_utils_ip4_prefix_to_netmask (prefix)))
+					prefix = 32;
+			} else
+				prefix = 32;
+		} else
+			prefix = 64;
+	}
+
 	nm_ip_route_set_dest (route, addrstr);
 	nm_ip_route_set_prefix (route, prefix);
 	g_free (addrstr);
@@ -476,13 +465,13 @@ ip_route_transform_from_next_hop_string (GBinding     *binding,
                                          GValue       *target_value,
                                          gpointer      user_data)
 {
-	int family = GPOINTER_TO_INT (user_data);
+	int addr_family = GPOINTER_TO_INT (user_data);
 	NMIPRoute *route;
 	const char *text;
 
 	text = g_value_get_string (source_value);
 	if (*text) {
-		if (!nm_utils_ipaddr_valid (family, text))
+		if (!nm_utils_ipaddr_valid (addr_family, text))
 			return FALSE;
 	} else
 		text = NULL;
@@ -509,10 +498,7 @@ ip_route_transform_from_metric_string (GBinding     *binding,
 	gint64 metric;
 
 	text = g_value_get_string (source_value);
-	if (*text)
-		metric = strtoul (text, NULL, 10);
-	else
-		metric = -1;
+	metric = _nm_utils_ascii_str_to_int64 (text, 10, 0, G_MAXUINT32, -1);
 
 	/* Fetch the original property value */
 	g_object_get (g_binding_get_source (binding),
@@ -527,7 +513,7 @@ ip_route_transform_from_metric_string (GBinding     *binding,
 
 /**
  * nm_editor_bind_ip_route_to_strings:
- * @family: the IP address family
+ * @addr_family: the IP address family
  * @source: the source object
  * @source_property: the source property
  * @dest_target: the target object for the route's destionation
@@ -547,7 +533,7 @@ ip_route_transform_from_metric_string (GBinding     *binding,
  * is a plain IP address, and @metric_target_property is a number.
  */
 void
-nm_editor_bind_ip_route_to_strings (int            family,
+nm_editor_bind_ip_route_to_strings (int            addr_family,
                                     gpointer       source,
                                     const gchar   *source_property,
                                     gpointer       dest_target,
@@ -563,19 +549,19 @@ nm_editor_bind_ip_route_to_strings (int            family,
 	                             flags,
 	                             ip_route_transform_to_dest_string,
 	                             ip_route_transform_from_dest_string,
-	                             GINT_TO_POINTER (family), NULL);
+	                             GINT_TO_POINTER (addr_family), NULL);
 	g_object_bind_property_full (source, source_property,
 	                             next_hop_target, next_hop_target_property,
 	                             flags,
 	                             ip_route_transform_to_next_hop_string,
 	                             ip_route_transform_from_next_hop_string,
-	                             GINT_TO_POINTER (family), NULL);
+	                             GINT_TO_POINTER (addr_family), NULL);
 	g_object_bind_property_full (source, source_property,
 	                             metric_target, metric_target_property,
 	                             flags,
 	                             ip_route_transform_to_metric_string,
 	                             ip_route_transform_from_metric_string,
-	                             GINT_TO_POINTER (family), NULL);
+	                             GINT_TO_POINTER (addr_family), NULL);
 }
 
 /* Wireless security method binding */
@@ -599,6 +585,9 @@ get_security_type (NMEditorWirelessSecurityMethodBinding *binding)
 		return "none";
 
 	key_mgmt = nm_setting_wireless_security_get_key_mgmt (binding->s_wsec);
+	if (!key_mgmt)
+		return "none";
+
 	auth_alg = nm_setting_wireless_security_get_auth_alg (binding->s_wsec);
 
 	/* No IEEE 802.1x */
diff --git a/clients/tui/nmt-connect-connection-list.c b/clients/tui/nmt-connect-connection-list.c
index 86286129..6e69a04b 100644
--- a/clients/tui/nmt-connect-connection-list.c
+++ b/clients/tui/nmt-connect-connection-list.c
@@ -30,6 +30,8 @@
 
 #include "NetworkManager.h"
 
+#include "nm-utils/nm-hash-utils.h"
+
 #include "nmtui.h"
 #include "nmt-connect-connection-list.h"
 
@@ -88,6 +90,7 @@ nmt_connect_connection_free (NmtConnectConnection *nmtconn)
 	g_clear_object (&nmtconn->ap);
 	g_clear_object (&nmtconn->active);
 	g_free (nmtconn->ssid);
+	g_slice_free (NmtConnectConnection, nmtconn);
 }
 
 static void
@@ -97,6 +100,7 @@ nmt_connect_device_free (NmtConnectDevice *nmtdev)
 	g_clear_object (&nmtdev->device);
 
 	g_slist_free_full (nmtdev->conns, (GDestroyNotify) nmt_connect_connection_free);
+	g_slice_free (NmtConnectDevice, nmtdev);
 }
 
 static const char *device_sort_order[] = {
@@ -272,7 +276,7 @@ add_connections_for_aps (NmtConnectDevice *nmtdev,
 	if (!aps->len)
 		return;
 
-	seen_ssids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	seen_ssids = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL);
 
 	for (i = 0; i < aps->len; i++) {
 		ap = aps->pdata[i];
@@ -360,7 +364,7 @@ append_nmt_devices_for_virtual_devices (GSList          *nmt_devices,
 	NmtConnectConnection *nmtconn;
 	int sort_order;
 
-	devices_by_name = g_hash_table_new (g_str_hash, g_str_equal);
+	devices_by_name = g_hash_table_new (nm_str_hash, g_str_equal);
 
 	for (i = 0; i < connections->len; i++) {
 		conn = connections->pdata[i];
diff --git a/clients/tui/nmt-ip-entry.c b/clients/tui/nmt-ip-entry.c
index 8d8f888f..66838680 100644
--- a/clients/tui/nmt-ip-entry.c
+++ b/clients/tui/nmt-ip-entry.c
@@ -123,39 +123,12 @@ ip_entry_validate (NmtNewtEntry *entry,
                    gpointer      user_data)
 {
 	NmtIPEntryPrivate *priv = NMT_IP_ENTRY_GET_PRIVATE (entry);
-	guchar buf[16];
-	guint32 prefix;
-	const char *slash;
-	char *addrstr, *end;
-	gboolean valid;
 
 	if (!*text)
 		return priv->optional;
-
-	slash = strchr (text, '/');
-
-	if (slash) {
-		if (!priv->prefix)
-			return FALSE;
-		addrstr = g_strndup (text, slash - text);
-	} else
-		addrstr = g_strdup (text);
-	valid = (inet_pton (priv->family, addrstr, buf) == 1);
-	g_free (addrstr);
-
-	if (!valid)
-		return FALSE;
-
-	if (slash) {
-		prefix = strtoul (slash + 1, &end, 10);
-		if (   *end
-		    || prefix == 0
-		    || (priv->family == AF_INET && prefix > 32)
-		    || (priv->family == AF_INET6 && prefix > 128))
-			valid = FALSE;
-	}
-
-	return valid;
+	if (priv->prefix)
+		return nm_utils_parse_inaddr_prefix (priv->family, text, NULL, NULL);
+	return nm_utils_parse_inaddr (priv->family, text, NULL);
 }
 
 static void
diff --git a/clients/tui/nmt-page-bond.c b/clients/tui/nmt-page-bond.c
index 48070dbf..e39a4c96 100644
--- a/clients/tui/nmt-page-bond.c
+++ b/clients/tui/nmt-page-bond.c
@@ -29,6 +29,7 @@
 
 #include "nmt-page-bond.h"
 
+#include "nmt-mac-entry.h"
 #include "nmt-address-list.h"
 #include "nmt-slave-list.h"
 
@@ -336,6 +337,7 @@ nmt_page_bond_constructed (GObject *object)
 	NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
 	NmtEditorSection *section;
 	NmtEditorGrid *grid;
+	NMSettingWired *s_wired;
 	NMSettingBond *s_bond;
 	NmtNewtWidget *widget, *label;
 	NMConnection *conn;
@@ -348,6 +350,12 @@ nmt_page_bond_constructed (GObject *object)
 	}
 	priv->s_bond = s_bond;
 
+	s_wired = nm_connection_get_setting_wired (conn);
+	if (!s_wired) {
+		nm_connection_add_setting (conn, nm_setting_wired_new ());
+		s_wired = nm_connection_get_setting_wired (conn);
+	}
+
 	section = nmt_editor_section_new (_("BOND"), NULL, TRUE);
 	grid = nmt_editor_section_get_body (section);
 
@@ -413,6 +421,12 @@ nmt_page_bond_constructed (GObject *object)
 	nmt_editor_grid_append (grid, _("ARP targets"), widget, NULL);
 	priv->arp_ip_target = NMT_ADDRESS_LIST (widget);
 
+	widget = nmt_mac_entry_new (40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED);
+	g_object_bind_property (s_wired, NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
+	                        widget, "mac-address",
+	                        G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+	nmt_editor_grid_append (grid, _("Cloned MAC address"), widget, NULL);
+
 	g_signal_connect (s_bond, "notify::" NM_SETTING_BOND_OPTIONS,
 	                  G_CALLBACK (bond_options_changed), bond);
 	bond_options_changed (G_OBJECT (s_bond), NULL, bond);
diff --git a/clients/tui/nmt-page-bridge.c b/clients/tui/nmt-page-bridge.c
index 08526db4..cf141f59 100644
--- a/clients/tui/nmt-page-bridge.c
+++ b/clients/tui/nmt-page-bridge.c
@@ -147,6 +147,12 @@ nmt_page_bridge_constructed (GObject *object)
 	label = nmt_newt_label_new (_("seconds"));
 	nmt_editor_grid_append (grid, _("Max age"), widget, label);
 
+	widget = nmt_newt_entry_numeric_new (10, 0, 65535);
+	g_object_bind_property (s_bridge, NM_SETTING_BRIDGE_GROUP_FORWARD_MASK,
+	                        widget, "text",
+	                        G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+	nmt_editor_grid_append (grid, _("Group forward mask"), widget, NULL);
+
 	nmt_editor_page_add_section (NMT_EDITOR_PAGE (bridge), section);
 
 	G_OBJECT_CLASS (nmt_page_bridge_parent_class)->constructed (object);
diff --git a/clients/tui/nmt-page-ip4.c b/clients/tui/nmt-page-ip4.c
index deb0f509..cfeb2d1e 100644
--- a/clients/tui/nmt-page-ip4.c
+++ b/clients/tui/nmt-page-ip4.c
@@ -182,6 +182,12 @@ nmt_page_ip4_constructed (GObject *object)
 	                        G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
 	nmt_editor_grid_append (grid, NULL, widget, NULL);
 
+	widget = nmt_newt_checkbox_new (_("Ignore automatically obtained DNS parameters"));
+	g_object_bind_property (s_ip4, NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS,
+	                        widget, "active",
+	                        G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+	nmt_editor_grid_append (grid, NULL, widget, NULL);
+
 	nmt_editor_grid_append (grid, NULL, nmt_newt_separator_new (), NULL);
 
 	widget = nmt_newt_checkbox_new (_("Require IPv4 addressing for this connection"));
diff --git a/clients/tui/nmt-page-ip6.c b/clients/tui/nmt-page-ip6.c
index 14802ace..2444a93d 100644
--- a/clients/tui/nmt-page-ip6.c
+++ b/clients/tui/nmt-page-ip6.c
@@ -180,6 +180,12 @@ nmt_page_ip6_constructed (GObject *object)
 	                        G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
 	nmt_editor_grid_append (grid, NULL, widget, NULL);
 
+	widget = nmt_newt_checkbox_new (_("Ignore automatically obtained DNS parameters"));
+	g_object_bind_property (s_ip6, NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS,
+	                        widget, "active",
+	                        G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+	nmt_editor_grid_append (grid, NULL, widget, NULL);
+
 	nmt_editor_grid_append (grid, NULL, nmt_newt_separator_new (), NULL);
 
 	widget = nmt_newt_checkbox_new (_("Require IPv6 addressing for this connection"));
diff --git a/clients/tui/nmt-page-vlan.c b/clients/tui/nmt-page-vlan.c
index 9cd65421..5ff3fa58 100644
--- a/clients/tui/nmt-page-vlan.c
+++ b/clients/tui/nmt-page-vlan.c
@@ -32,13 +32,6 @@
 
 G_DEFINE_TYPE (NmtPageVlan, nmt_page_vlan, NMT_TYPE_EDITOR_PAGE_DEVICE)
 
-#define NMT_PAGE_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_PAGE_VLAN, NmtPageVlanPrivate))
-
-typedef struct {
-	NMSettingWired *s_wired;
-
-} NmtPageVlanPrivate;
-
 NmtEditorPage *
 nmt_page_vlan_new (NMConnection   *conn,
                    NmtDeviceEntry *deventry)
@@ -67,7 +60,6 @@ static void
 nmt_page_vlan_constructed (GObject *object)
 {
 	NmtPageVlan *vlan = NMT_PAGE_VLAN (object);
-	NmtPageVlanPrivate *priv = NMT_PAGE_VLAN_GET_PRIVATE (vlan);
 	NmtEditorSection *section;
 	NmtEditorGrid *grid;
 	NMSettingWired *s_wired;
@@ -83,13 +75,9 @@ nmt_page_vlan_constructed (GObject *object)
 	}
 	s_wired = nm_connection_get_setting_wired (conn);
 	if (!s_wired) {
-		/* It makes things simpler if we always have a NMSettingWired;
-		 * we'll hold a ref on one, and add it to and remove it from
-		 * the connection as needed.
-		 */
-		s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
+		nm_connection_add_setting (conn, nm_setting_wired_new ());
+		s_wired = nm_connection_get_setting_wired (conn);
 	}
-	priv->s_wired = g_object_ref_sink (s_wired);
 
 	section = nmt_editor_section_new (_("VLAN"), NULL, TRUE);
 	grid = nmt_editor_section_get_body (section);
@@ -133,23 +121,10 @@ nmt_page_vlan_constructed (GObject *object)
 }
 
 static void
-nmt_page_vlan_finalize (GObject *object)
-{
-	NmtPageVlanPrivate *priv = NMT_PAGE_VLAN_GET_PRIVATE (object);
-
-	g_clear_object (&priv->s_wired);
-
-	G_OBJECT_CLASS (nmt_page_vlan_parent_class)->finalize (object);
-}
-
-static void
 nmt_page_vlan_class_init (NmtPageVlanClass *vlan_class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (vlan_class);
 
-	g_type_class_add_private (vlan_class, sizeof (NmtPageVlanPrivate));
-
 	/* virtual methods */
 	object_class->constructed = nmt_page_vlan_constructed;
-	object_class->finalize    = nmt_page_vlan_finalize;
 }
diff --git a/clients/tui/nmt-page-wifi.c b/clients/tui/nmt-page-wifi.c
index 35625fe4..f846345c 100644
--- a/clients/tui/nmt-page-wifi.c
+++ b/clients/tui/nmt-page-wifi.c
@@ -38,13 +38,6 @@
 
 G_DEFINE_TYPE (NmtPageWifi, nmt_page_wifi, NMT_TYPE_EDITOR_PAGE_DEVICE)
 
-#define NMT_PAGE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_PAGE_WIFI, NmtPageWifiPrivate))
-
-typedef struct {
-	NMSettingWirelessSecurity *s_wsec;
-
-} NmtPageWifiPrivate;
-
 NmtEditorPage *
 nmt_page_wifi_new (NMConnection   *conn,
                    NmtDeviceEntry *deventry)
@@ -177,7 +170,6 @@ ssid_transform_from_entry (GBinding     *binding,
 static void
 nmt_page_wifi_constructed (GObject *object)
 {
-	NmtPageWifiPrivate *priv = NMT_PAGE_WIFI_GET_PRIVATE (object);
 	NmtPageWifi *wifi = NMT_PAGE_WIFI (object);
 	NmtDeviceEntry *deventry;
 	NmtEditorSection *section;
@@ -198,13 +190,9 @@ nmt_page_wifi_constructed (GObject *object)
 
 	s_wsec = nm_connection_get_setting_wireless_security (conn);
 	if (!s_wsec) {
-		/* It makes things simpler if we always have a
-		 * NMSettingWirelessSecurity; we'll hold a ref on one, and add
-		 * it to and remove it from the connection as needed.
-		 */
-		s_wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
+		nm_connection_add_setting (conn, nm_setting_wireless_security_new ());
+		s_wsec = nm_connection_get_setting_wireless_security (conn);
 	}
-	priv->s_wsec = g_object_ref_sink (s_wsec);
 
 	deventry = nmt_editor_page_device_get_device_entry (NMT_EDITOR_PAGE_DEVICE (object));
 	g_object_bind_property (s_wireless, NM_SETTING_WIRELESS_MAC_ADDRESS,
@@ -375,23 +363,9 @@ nmt_page_wifi_constructed (GObject *object)
 }
 
 static void
-nmt_page_wifi_finalize (GObject *object)
-{
-	NmtPageWifiPrivate *priv = NMT_PAGE_WIFI_GET_PRIVATE (object);
-
-	g_clear_object (&priv->s_wsec);
-
-	G_OBJECT_CLASS (nmt_page_wifi_parent_class)->finalize (object);
-}
-
-
-static void
 nmt_page_wifi_class_init (NmtPageWifiClass *wifi_class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (wifi_class);
 
-	g_type_class_add_private (wifi_class, sizeof (NmtPageWifiPrivate));
-
 	object_class->constructed = nmt_page_wifi_constructed;
-	object_class->finalize    = nmt_page_wifi_finalize;
 }
diff --git a/clients/tui/nmt-route-entry.c b/clients/tui/nmt-route-entry.c
index f7c75e0a..1b37389f 100644
--- a/clients/tui/nmt-route-entry.c
+++ b/clients/tui/nmt-route-entry.c
@@ -126,7 +126,7 @@ nmt_route_entry_constructed (GObject *object)
 
 	priv->dest = nmt_ip_entry_new (priv->ip_entry_width, priv->family, TRUE, FALSE);
 	priv->next_hop = nmt_ip_entry_new (priv->ip_entry_width, priv->family, FALSE, TRUE);
-	priv->metric = nmt_newt_entry_numeric_new (priv->metric_entry_width, 0, 65535);
+	priv->metric = nmt_newt_entry_numeric_new_full (priv->metric_entry_width, 0, G_MAXUINT32, TRUE);
 
 	nmt_newt_grid_add (grid, priv->dest, 0, 0);
 	warning_label = create_warning_label (priv->dest);
diff --git a/clients/tui/nmt-route-table.c b/clients/tui/nmt-route-table.c
index 7005e8ad..a63f5205 100644
--- a/clients/tui/nmt-route-table.c
+++ b/clients/tui/nmt-route-table.c
@@ -149,9 +149,9 @@ add_route (NmtWidgetList *list,
 	NMIPRoute *route;
 
 	if (priv->family == AF_INET)
-		route = nm_ip_route_new (AF_INET, "0.0.0.0", 32, NULL, 0, NULL);
+		route = nm_ip_route_new (AF_INET, "0.0.0.0", 32, NULL, -1, NULL);
 	else
-		route = nm_ip_route_new (AF_INET6, "::", 128, NULL, 0, NULL);
+		route = nm_ip_route_new (AF_INET6, "::", 128, NULL, -1, NULL);
 	g_ptr_array_add (priv->routes, route);
 	nmt_widget_list_set_length (list, priv->routes->len);
 	g_object_notify (table, "routes");
diff --git a/clients/tui/nmtui-connect.c b/clients/tui/nmtui-connect.c
index ddabcd72..086e4bd3 100644
--- a/clients/tui/nmtui-connect.c
+++ b/clients/tui/nmtui-connect.c
@@ -36,6 +36,7 @@
 #include "nmt-password-dialog.h"
 #include "nm-secret-agent-simple.h"
 #include "nm-vpn-helpers.h"
+#include "nm-client-utils.h"
 #include "nmt-utils.h"
 
 /**
@@ -148,38 +149,60 @@ secrets_requested (NMSecretAgentSimple *agent,
 	g_object_unref (form);
 }
 
+typedef struct {
+	NMDevice *device;
+	NMActiveConnection *active;
+	NmtSyncOp *op;
+} ActivateConnectionInfo;
+
 static void
 connect_cancelled (NmtNewtForm *form,
                    gpointer     user_data)
 {
-	NmtSyncOp *op = user_data;
+	ActivateConnectionInfo *info = user_data;
 	GError *error = NULL;
 
 	error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
-	nmt_sync_op_complete_boolean (op, FALSE, error);
+	nmt_sync_op_complete_boolean (info->op, FALSE, error);
 	g_clear_error (&error);
 }
 
 static void
-activate_ac_state_changed (GObject    *object,
-                           GParamSpec *pspec,
-                           gpointer    user_data)
+check_activated (ActivateConnectionInfo *info)
 {
-	NmtSyncOp *op = user_data;
-	NMActiveConnectionState state;
-	GError *error = NULL;
-
-	state = nm_active_connection_get_state (NM_ACTIVE_CONNECTION (object));
-	if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
+	NMActiveConnectionState ac_state;
+	const char *reason = NULL;
+	gs_free_error GError *error = NULL;
+
+	ac_state = nmc_activation_get_effective_state (info->active, info->device, &reason);
+	if (!NM_IN_SET (ac_state,
+	                NM_ACTIVE_CONNECTION_STATE_ACTIVATED,
+	                NM_ACTIVE_CONNECTION_STATE_DEACTIVATED))
 		return;
 
-	if (state != NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
-		error = g_error_new_literal (NM_CLIENT_ERROR, NM_CLIENT_ERROR_FAILED,
-		                             _("Activation failed"));
+	if (ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
+		nm_assert (reason);
+		error = g_error_new (NM_CLIENT_ERROR, NM_CLIENT_ERROR_FAILED,
+		                     _("Activation failed: %s"), reason);
 	}
 
-	nmt_sync_op_complete_boolean (op, error == NULL, error);
-	g_clear_error (&error);
+	nmt_sync_op_complete_boolean (info->op, error == NULL, error);
+}
+
+static void
+activate_ac_state_changed (GObject    *object,
+                           GParamSpec *pspec,
+                           gpointer    user_data)
+{
+	check_activated (user_data);
+}
+
+static void
+activate_device_state_changed (GObject    *object,
+                               GParamSpec *pspec,
+                               gpointer    user_data)
+{
+	check_activated (user_data);
 }
 
 static void
@@ -226,6 +249,7 @@ activate_connection (NMConnection *connection,
 	const char *specific_object_path;
 	NMActiveConnection *ac;
 	GError *error = NULL;
+	ActivateConnectionInfo info = { };
 
 	form = g_object_new (NMT_TYPE_NEWT_FORM,
 	                     "escape-exits", TRUE,
@@ -290,12 +314,18 @@ activate_connection (NMConnection *connection,
 	/* Now wait for the connection to actually reach the ACTIVATED state,
 	 * allowing the user to cancel if it takes too long.
 	 */
-
 	nmt_sync_op_init (&op);
+	info.active = ac;
+	info.device = device;
+	info.op = &op;
 
-	g_signal_connect (form, "quit", G_CALLBACK (connect_cancelled), &op);
+	g_signal_connect (form, "quit", G_CALLBACK (connect_cancelled), &info);
 	g_signal_connect (ac, "notify::" NM_ACTIVE_CONNECTION_STATE,
-	                  G_CALLBACK (activate_ac_state_changed), &op);
+	                  G_CALLBACK (activate_ac_state_changed), &info);
+	if (device) {
+		g_signal_connect (device, "notify::" NM_DEVICE_STATE,
+		                  G_CALLBACK (activate_device_state_changed), &info);
+	}
 
 	if (!nmt_sync_op_wait_boolean (&op, &error)) {
 		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
@@ -303,8 +333,10 @@ activate_connection (NMConnection *connection,
 		g_clear_error (&error);
 	}
 
-	g_signal_handlers_disconnect_by_func (form, G_CALLBACK (connect_cancelled), &op);
-	g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (activate_ac_state_changed), &op);
+	g_signal_handlers_disconnect_by_func (form, G_CALLBACK (connect_cancelled), &info);
+	g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (activate_ac_state_changed), &info);
+	if (device)
+		g_signal_handlers_disconnect_by_func (device, G_CALLBACK (activate_device_state_changed), &info);
 
  done:
 	if (nmt_newt_widget_get_realized (NMT_NEWT_WIDGET (form)))