about summary refs log tree commit diff
path: root/cli/src/settings.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2014-07-06 02:16:10 +0200
committerMichael Biebl <biebl@debian.org>2014-07-06 02:16:10 +0200
commit33491bc4279481db8ae47213e34a6d695a0e8830 (patch)
tree097d2b0fdff3fae6885381ae5e57a182cd8cbbba /cli/src/settings.c
parent59c3714a494c3b3765657c0551ad82842d98a7d2 (diff)
Imported Upstream version 0.9.10.0 upstream/0.9.10.0
Diffstat (limited to 'cli/src/settings.c')
-rw-r--r--cli/src/settings.c7434
1 files changed, 6338 insertions, 1096 deletions
diff --git a/cli/src/settings.c b/cli/src/settings.c
index 1b3d0fd0..0fc708b3 100644
--- a/cli/src/settings.c
+++ b/cli/src/settings.c
@@ -14,43 +14,50 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2010 - 2012 Red Hat, Inc.
+ * (C) Copyright 2010 - 2014 Red Hat, Inc.
  */
 
 #include "config.h"
 
-#include "net/if_arp.h"
+#include <net/if_arp.h>
+#include <stdio.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <libnm-util/nm-utils.h>
 
 #include "utils.h"
+#include "common.h"
 #include "settings.h"
 
+/* Forward declarations */
+static char *wep_key_type_to_string (NMWepKeyType type);
 
 /* Helper macro to define fields */
-#define SETTING_FIELD(setting, width) { setting, N_(setting), width, NULL, 0 }
+#define SETTING_FIELD(setting, width) { setting, N_(setting), width, NULL, FALSE, FALSE, 0 }
 
 /* Available fields for NM_SETTING_CONNECTION_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_connection[] = {
-	SETTING_FIELD ("name",  15),                            /* 0 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_ID, 25),           /* 1 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_UUID, 38),         /* 2 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_TYPE, 17),         /* 3 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT, 13),  /* 4 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_TIMESTAMP, 10),    /* 5 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_READ_ONLY, 10),    /* 6 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_PERMISSIONS, 30),  /* 7 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_ZONE, 10),         /* 8 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_MASTER, 20),       /* 9 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_SLAVE_TYPE, 20),   /* 10 */
-	SETTING_FIELD (NM_SETTING_CONNECTION_SECONDARIES, 40),  /* 11 */
-	{NULL, NULL, 0, NULL, 0}
+NmcOutputField nmc_fields_setting_connection[] = {
+	SETTING_FIELD ("name",  15),                                     /* 0 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_ID, 25),                    /* 1 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_UUID, 38),                  /* 2 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_INTERFACE_NAME, 20),        /* 3 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_TYPE, 17),                  /* 4 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT, 13),           /* 5 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_TIMESTAMP, 10),             /* 6 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_READ_ONLY, 10),             /* 7 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_PERMISSIONS, 30),           /* 8 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_ZONE, 10),                  /* 9 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_MASTER, 20),                /* 10 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_SLAVE_TYPE, 20),            /* 11 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_SECONDARIES, 40),           /* 12 */
+	SETTING_FIELD (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, 30),  /* 13 */
+	{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_INTERFACE_NAME","\
                                               NM_SETTING_CONNECTION_TYPE","\
                                               NM_SETTING_CONNECTION_AUTOCONNECT","\
                                               NM_SETTING_CONNECTION_TIMESTAMP","\
@@ -59,11 +66,12 @@ static NmcOutputField nmc_fields_setting_connection[] = {
                                               NM_SETTING_CONNECTION_ZONE","\
                                               NM_SETTING_CONNECTION_MASTER","\
                                               NM_SETTING_CONNECTION_SLAVE_TYPE","\
-                                              NM_SETTING_CONNECTION_SECONDARIES
+                                              NM_SETTING_CONNECTION_SECONDARIES","\
+                                              NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT
 #define NMC_FIELDS_SETTING_CONNECTION_COMMON  NMC_FIELDS_SETTING_CONNECTION_ALL
 
 /* Available fields for NM_SETTING_WIRED_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_wired[] = {
+NmcOutputField nmc_fields_setting_wired[] = {
 	SETTING_FIELD ("name",  17),                                  /* 0 */
 	SETTING_FIELD (NM_SETTING_WIRED_PORT, 8),                     /* 1 */
 	SETTING_FIELD (NM_SETTING_WIRED_SPEED, 10),                   /* 2 */
@@ -76,7 +84,7 @@ static NmcOutputField nmc_fields_setting_wired[] = {
 	SETTING_FIELD (NM_SETTING_WIRED_S390_SUBCHANNELS, 20),        /* 9 */
 	SETTING_FIELD (NM_SETTING_WIRED_S390_NETTYPE, 15),            /* 10 */
 	SETTING_FIELD (NM_SETTING_WIRED_S390_OPTIONS, 20),            /* 11 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_WIRED_ALL     "name"","\
                                          NM_SETTING_WIRED_PORT","\
@@ -93,7 +101,7 @@ static NmcOutputField nmc_fields_setting_wired[] = {
 #define NMC_FIELDS_SETTING_WIRED_COMMON  NMC_FIELDS_SETTING_WIRED_ALL
 
 /* Available fields for NM_SETTING_802_1X_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_8021X[] = {
+NmcOutputField nmc_fields_setting_8021X[] = {
 	SETTING_FIELD ("name", 10),                                              /* 0 */
 	SETTING_FIELD (NM_SETTING_802_1X_EAP, 10),                               /* 1 */
 	SETTING_FIELD (NM_SETTING_802_1X_IDENTITY, 15),                          /* 2 */
@@ -127,7 +135,7 @@ static NmcOutputField nmc_fields_setting_8021X[] = {
 	SETTING_FIELD (NM_SETTING_802_1X_PIN, 8),                                /* 30 */
 	SETTING_FIELD (NM_SETTING_802_1X_PIN_FLAGS, 20),                         /* 31 */
 	SETTING_FIELD (NM_SETTING_802_1X_SYSTEM_CA_CERTS, 17),                   /* 32 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_802_1X_ALL     "name"","\
                                           NM_SETTING_802_1X_EAP","\
@@ -165,7 +173,7 @@ static NmcOutputField nmc_fields_setting_8021X[] = {
 #define NMC_FIELDS_SETTING_802_1X_COMMON  NMC_FIELDS_SETTING_802_1X_ALL
 
 /* Available fields for NM_SETTING_WIRELESS_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_wireless[] = {
+NmcOutputField nmc_fields_setting_wireless[] = {
 	SETTING_FIELD ("name", 17),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_WIRELESS_SSID, 34),                      /* 1 */
 	SETTING_FIELD (NM_SETTING_WIRELESS_MODE, 15),                      /* 2 */
@@ -179,9 +187,8 @@ static NmcOutputField nmc_fields_setting_wireless[] = {
 	SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST, 39),     /* 10 */
 	SETTING_FIELD (NM_SETTING_WIRELESS_MTU, 6),                        /* 11 */
 	SETTING_FIELD (NM_SETTING_WIRELESS_SEEN_BSSIDS, 35),               /* 12 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_SEC, 25),                       /* 13 */
-	SETTING_FIELD (NM_SETTING_WIRELESS_HIDDEN, 10),                    /* 14 */
-	{NULL, NULL, 0, NULL, 0}
+	SETTING_FIELD (NM_SETTING_WIRELESS_HIDDEN, 10),                    /* 13 */
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_WIRELESS_ALL     "name"","\
                                             NM_SETTING_WIRELESS_SSID","\
@@ -196,12 +203,11 @@ static NmcOutputField nmc_fields_setting_wireless[] = {
                                             NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST","\
                                             NM_SETTING_WIRELESS_MTU","\
                                             NM_SETTING_WIRELESS_SEEN_BSSIDS","\
-                                            NM_SETTING_WIRELESS_SEC","\
                                             NM_SETTING_WIRELESS_HIDDEN
 #define NMC_FIELDS_SETTING_WIRELESS_COMMON  NMC_FIELDS_SETTING_WIRELESS_ALL
 
 /* Available fields for NM_SETTING_WIRELESS_SECURITY_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_wireless_security[] = {
+NmcOutputField nmc_fields_setting_wireless_security[] = {
 	SETTING_FIELD ("name", 25),                                           /* 0 */
 	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, 10),            /* 1 */
 	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, 15),       /* 2 */
@@ -220,7 +226,7 @@ static NmcOutputField nmc_fields_setting_wireless_security[] = {
 	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, 20),           /* 15 */
 	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, 15),       /* 16 */
 	SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, 20), /* 17 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_WIRELESS_SECURITY_ALL     "name"","\
                                                      NM_SETTING_WIRELESS_SECURITY_KEY_MGMT","\
@@ -243,7 +249,7 @@ static NmcOutputField nmc_fields_setting_wireless_security[] = {
 #define NMC_FIELDS_SETTING_WIRELESS_SECURITY_COMMON  NMC_FIELDS_SETTING_WIRELESS_SECURITY_ALL
 
 /* Available fields for NM_SETTING_IP4_CONFIG_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_ip4_config[] = {
+NmcOutputField nmc_fields_setting_ip4_config[] = {
 	SETTING_FIELD ("name", 8),                                         /* 0 */
 	SETTING_FIELD (NM_SETTING_IP4_CONFIG_METHOD, 10),                  /* 1 */
 	SETTING_FIELD (NM_SETTING_IP4_CONFIG_DNS, 20),                     /* 2 */
@@ -257,7 +263,7 @@ static NmcOutputField nmc_fields_setting_ip4_config[] = {
 	SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, 14),           /* 10 */
 	SETTING_FIELD (NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, 15),           /* 11 */
 	SETTING_FIELD (NM_SETTING_IP4_CONFIG_MAY_FAIL, 12),                /* 12 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_IP4_CONFIG_ALL     "name"","\
                                               NM_SETTING_IP4_CONFIG_METHOD","\
@@ -275,7 +281,7 @@ static NmcOutputField nmc_fields_setting_ip4_config[] = {
 #define NMC_FIELDS_SETTING_IP4_CONFIG_COMMON  NMC_FIELDS_SETTING_IP4_CONFIG_ALL
 
 /* Available fields for NM_SETTING_IP6_CONFIG_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_ip6_config[] = {
+NmcOutputField nmc_fields_setting_ip6_config[] = {
 	SETTING_FIELD ("name", 8),                                         /* 0 */
 	SETTING_FIELD (NM_SETTING_IP6_CONFIG_METHOD, 10),                  /* 1 */
 	SETTING_FIELD (NM_SETTING_IP6_CONFIG_DNS, 20),                     /* 2 */
@@ -288,7 +294,7 @@ static NmcOutputField nmc_fields_setting_ip6_config[] = {
 	SETTING_FIELD (NM_SETTING_IP6_CONFIG_MAY_FAIL, 12),                /* 9 */
 	SETTING_FIELD (NM_SETTING_IP6_CONFIG_IP6_PRIVACY, 15),             /* 10 */
 	SETTING_FIELD (NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME, 14),           /* 11 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_IP6_CONFIG_ALL     "name"","\
                                               NM_SETTING_IP6_CONFIG_METHOD","\
@@ -305,14 +311,14 @@ static NmcOutputField nmc_fields_setting_ip6_config[] = {
 #define NMC_FIELDS_SETTING_IP6_CONFIG_COMMON  NMC_FIELDS_SETTING_IP4_CONFIG_ALL
 
 /* Available fields for NM_SETTING_SERIAL_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_serial[] = {
+NmcOutputField nmc_fields_setting_serial[] = {
 	SETTING_FIELD ("name", 10),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_SERIAL_BAUD, 10),                        /* 1 */
 	SETTING_FIELD (NM_SETTING_SERIAL_BITS, 10),                        /* 2 */
 	SETTING_FIELD (NM_SETTING_SERIAL_PARITY, 10),                      /* 3 */
 	SETTING_FIELD (NM_SETTING_SERIAL_STOPBITS, 10),                    /* 4 */
 	SETTING_FIELD (NM_SETTING_SERIAL_SEND_DELAY, 12),                  /* 5 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_SERIAL_ALL     "name"","\
                                           NM_SETTING_SERIAL_BAUD","\
@@ -323,7 +329,7 @@ static NmcOutputField nmc_fields_setting_serial[] = {
 #define NMC_FIELDS_SETTING_SERIAL_COMMON  NMC_FIELDS_SETTING_SERIAL_ALL
 
 /* Available fields for NM_SETTING_PPP_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_ppp[] = {
+NmcOutputField nmc_fields_setting_ppp[] = {
 	SETTING_FIELD ("name", 10),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_PPP_NOAUTH, 10),                         /* 1 */
 	SETTING_FIELD (NM_SETTING_PPP_REFUSE_EAP, 10),                     /* 2 */
@@ -343,7 +349,7 @@ static NmcOutputField nmc_fields_setting_ppp[] = {
 	SETTING_FIELD (NM_SETTING_PPP_MTU, 10),                            /* 16 */
 	SETTING_FIELD (NM_SETTING_PPP_LCP_ECHO_FAILURE, 17),               /* 17 */
 	SETTING_FIELD (NM_SETTING_PPP_LCP_ECHO_INTERVAL, 18),              /* 18 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_PPP_ALL     "name"","\
                                        NM_SETTING_PPP_NOAUTH","\
@@ -367,13 +373,13 @@ static NmcOutputField nmc_fields_setting_ppp[] = {
 #define NMC_FIELDS_SETTING_PPP_COMMON  NMC_FIELDS_SETTING_PPP_ALL
 
 /* Available fields for NM_SETTING_PPPOE_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_pppoe[] = {
+NmcOutputField nmc_fields_setting_pppoe[] = {
 	SETTING_FIELD ("name", 10),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_PPPOE_SERVICE, 12),                      /* 1 */
 	SETTING_FIELD (NM_SETTING_PPPOE_USERNAME, 15),                     /* 2 */
 	SETTING_FIELD (NM_SETTING_PPPOE_PASSWORD, 15),                     /* 3 */
 	SETTING_FIELD (NM_SETTING_PPPOE_PASSWORD_FLAGS, 20),               /* 4 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_PPPOE_ALL     "name"","\
                                          NM_SETTING_PPPOE_SERVICE","\
@@ -383,7 +389,7 @@ static NmcOutputField nmc_fields_setting_pppoe[] = {
 #define NMC_FIELDS_SETTING_PPPOE_COMMON  NMC_FIELDS_SETTING_PPPOE_ALL
 
 /* Available fields for NM_SETTING_ADSL_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_adsl[] = {
+NmcOutputField nmc_fields_setting_adsl[] = {
 	SETTING_FIELD ("name", 10),                                /* 0 */
 	SETTING_FIELD (NM_SETTING_ADSL_USERNAME, 15),              /* 1 */
 	SETTING_FIELD (NM_SETTING_ADSL_PASSWORD, 15),              /* 2 */
@@ -392,7 +398,7 @@ static NmcOutputField nmc_fields_setting_adsl[] = {
 	SETTING_FIELD (NM_SETTING_ADSL_ENCAPSULATION, 10),         /* 5 */
 	SETTING_FIELD (NM_SETTING_ADSL_VPI, 10),                   /* 6 */
 	SETTING_FIELD (NM_SETTING_ADSL_VCI, 10),                   /* 7 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_ADSL_ALL     "name"","\
                                         NM_SETTING_ADSL_USERNAME","\
@@ -405,7 +411,7 @@ static NmcOutputField nmc_fields_setting_adsl[] = {
 #define NMC_FIELDS_SETTING_ADSL_COMMON  NMC_FIELDS_SETTING_ADSL_ALL
 
 /* Available fields for NM_SETTING_GSM_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_gsm[] = {
+NmcOutputField nmc_fields_setting_gsm[] = {
 	SETTING_FIELD ("name", 10),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_GSM_NUMBER, 10),                         /* 1 */
 	SETTING_FIELD (NM_SETTING_GSM_USERNAME, 15),                       /* 2 */
@@ -418,7 +424,7 @@ static NmcOutputField nmc_fields_setting_gsm[] = {
 	SETTING_FIELD (NM_SETTING_GSM_PIN, 10),                            /* 9 */
 	SETTING_FIELD (NM_SETTING_GSM_PIN_FLAGS, 20),                      /* 10 */
 	SETTING_FIELD (NM_SETTING_GSM_HOME_ONLY, 10),                      /* 11 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_GSM_ALL     "name"","\
                                        NM_SETTING_GSM_NUMBER","\
@@ -435,13 +441,13 @@ static NmcOutputField nmc_fields_setting_gsm[] = {
 #define NMC_FIELDS_SETTING_GSM_COMMON  NMC_FIELDS_SETTING_GSM_ALL
 
 /* Available fields for NM_SETTING_CDMA_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_cdma[] = {
+NmcOutputField nmc_fields_setting_cdma[] = {
 	SETTING_FIELD ("name", 10),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_CDMA_NUMBER, 15),                        /* 1 */
 	SETTING_FIELD (NM_SETTING_CDMA_USERNAME, 15),                      /* 2 */
 	SETTING_FIELD (NM_SETTING_CDMA_PASSWORD, 15),                      /* 3 */
 	SETTING_FIELD (NM_SETTING_CDMA_PASSWORD_FLAGS, 20),                /* 4 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_CDMA_ALL     "name"","\
                                         NM_SETTING_CDMA_NUMBER","\
@@ -451,11 +457,11 @@ static NmcOutputField nmc_fields_setting_cdma[] = {
 #define NMC_FIELDS_SETTING_CDMA_COMMON  NMC_FIELDS_SETTING_CDMA_ALL
 
 /* Available fields for NM_SETTING_BLUETOOTH_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_bluetooth[] = {
+NmcOutputField nmc_fields_setting_bluetooth[] = {
 	SETTING_FIELD ("name", 11),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_BLUETOOTH_BDADDR, 19),                   /* 1 */
 	SETTING_FIELD (NM_SETTING_BLUETOOTH_TYPE, 10),                     /* 2 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_BLUETOOTH_ALL     "name"","\
                                              NM_SETTING_BLUETOOTH_BDADDR","\
@@ -463,12 +469,12 @@ static NmcOutputField nmc_fields_setting_bluetooth[] = {
 #define NMC_FIELDS_SETTING_BLUETOOTH_COMMON  NMC_FIELDS_SETTING_BLUETOOTH_ALL
 
 /* Available fields for NM_SETTING_OLPC_MESH_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_olpc_mesh[] = {
+NmcOutputField nmc_fields_setting_olpc_mesh[] = {
 	SETTING_FIELD ("name", 18),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_OLPC_MESH_SSID, 34),                     /* 1 */
 	SETTING_FIELD (NM_SETTING_OLPC_MESH_CHANNEL, 12),                  /* 2 */
 	SETTING_FIELD (NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, 17),     /* 3 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_OLPC_MESH_ALL     "name"","\
                                              NM_SETTING_OLPC_MESH_SSID","\
@@ -477,13 +483,13 @@ static NmcOutputField nmc_fields_setting_olpc_mesh[] = {
 #define NMC_FIELDS_SETTING_OLPC_MESH_COMMON  NMC_FIELDS_SETTING_OLPC_MESH_ALL
 
 /* Available fields for NM_SETTING_VPN_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_vpn[] = {
+NmcOutputField nmc_fields_setting_vpn[] = {
 	SETTING_FIELD ("name", 6),                                         /* 0 */
 	SETTING_FIELD (NM_SETTING_VPN_SERVICE_TYPE, 40),                   /* 1 */
 	SETTING_FIELD (NM_SETTING_VPN_USER_NAME, 12),                      /* 2 */
 	SETTING_FIELD (NM_SETTING_VPN_DATA, 30),                           /* 3 */
 	SETTING_FIELD (NM_SETTING_VPN_SECRETS, 15),                        /* 4 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_VPN_ALL     "name"","\
                                        NM_SETTING_VPN_SERVICE_TYPE","\
@@ -493,11 +499,11 @@ static NmcOutputField nmc_fields_setting_vpn[] = {
 #define NMC_FIELDS_SETTING_VPN_COMMON  NMC_FIELDS_SETTING_VPN_ALL
 
 /* Available fields for NM_SETTING_WIMAX_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_wimax[] = {
+NmcOutputField nmc_fields_setting_wimax[] = {
 	SETTING_FIELD ("name", 6),                                         /* 0 */
 	SETTING_FIELD (NM_SETTING_WIMAX_MAC_ADDRESS, 19),                  /* 1 */
 	SETTING_FIELD (NM_SETTING_WIMAX_NETWORK_NAME, 40),                 /* 2 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_WIMAX_ALL     "name"","\
                                          NM_SETTING_WIMAX_MAC_ADDRESS","\
@@ -505,25 +511,29 @@ static NmcOutputField nmc_fields_setting_wimax[] = {
 #define NMC_FIELDS_SETTING_WIMAX_COMMON  NMC_FIELDS_SETTING_WIMAX_ALL
 
 /* Available fields for NM_SETTING_INFINIBAND_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_infiniband[] = {
+NmcOutputField nmc_fields_setting_infiniband[] = {
 	SETTING_FIELD ("name",  12),                                       /* 0 */
 	SETTING_FIELD (NM_SETTING_INFINIBAND_MAC_ADDRESS, 61),             /* 1 */
 	SETTING_FIELD (NM_SETTING_INFINIBAND_MTU, 6),                      /* 2 */
 	SETTING_FIELD (NM_SETTING_INFINIBAND_TRANSPORT_MODE, 12),          /* 3 */
-	{NULL, NULL, 0, NULL, 0}
+	SETTING_FIELD (NM_SETTING_INFINIBAND_P_KEY, 6),                    /* 4 */
+	SETTING_FIELD (NM_SETTING_INFINIBAND_PARENT, 16),                  /* 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
-#define NMC_FIELDS_SETTING_INFINIBAND_COMMON  NMC_FIELDS_SETTING_INFINIBAND_ALL
+                                              NM_SETTING_INFINIBAND_MTU"," \
+                                              NM_SETTING_INFINIBAND_TRANSPORT_MODE"," \
+                                              NM_SETTING_INFINIBAND_P_KEY"," \
+                                              NM_SETTING_INFINIBAND_PARENT
+#define NMC_FIELDS_SETTING_INFINIBAND_COMMON  NMC_FIELDS_SETTING_INFINIBAND_ALL \
 
 /* Available fields for NM_SETTING_BOND_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_bond[] = {
+NmcOutputField nmc_fields_setting_bond[] = {
 	SETTING_FIELD ("name",  8),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_BOND_INTERFACE_NAME, 15),                /* 1 */
 	SETTING_FIELD (NM_SETTING_BOND_OPTIONS, 30),                       /* 2 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_BOND_ALL     "name"","\
                                         NM_SETTING_BOND_INTERFACE_NAME","\
@@ -531,7 +541,7 @@ static NmcOutputField nmc_fields_setting_bond[] = {
 #define NMC_FIELDS_SETTING_BOND_COMMON  NMC_FIELDS_SETTING_BOND_ALL
 
 /* Available fields for NM_SETTING_VLAN_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_vlan[] = {
+NmcOutputField nmc_fields_setting_vlan[] = {
 	SETTING_FIELD ("name",  6),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_VLAN_INTERFACE_NAME, 15),                /* 1 */
 	SETTING_FIELD (NM_SETTING_VLAN_PARENT, 8),                         /* 2 */
@@ -539,7 +549,7 @@ static NmcOutputField nmc_fields_setting_vlan[] = {
 	SETTING_FIELD (NM_SETTING_VLAN_FLAGS, 45),                         /* 4 */
 	SETTING_FIELD (NM_SETTING_VLAN_INGRESS_PRIORITY_MAP, 22),          /* 5 */
 	SETTING_FIELD (NM_SETTING_VLAN_EGRESS_PRIORITY_MAP, 22),           /* 6 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_VLAN_ALL     "name"","\
                                         NM_SETTING_VLAN_INTERFACE_NAME","\
@@ -551,19 +561,21 @@ static NmcOutputField nmc_fields_setting_vlan[] = {
 #define NMC_FIELDS_SETTING_VLAN_COMMON  NMC_FIELDS_SETTING_VLAN_ALL
 
 /* Available fields for NM_SETTING_BRIDGE_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_bridge[] = {
+NmcOutputField nmc_fields_setting_bridge[] = {
 	SETTING_FIELD ("name",  8),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_BRIDGE_INTERFACE_NAME, 15),              /* 1 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_STP, 5),                          /* 2 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_PRIORITY, 6),                     /* 3 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_FORWARD_DELAY, 6),                /* 4 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_HELLO_TIME, 6),                   /* 5 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_MAX_AGE, 6),                      /* 6 */
-	SETTING_FIELD (NM_SETTING_BRIDGE_AGEING_TIME, 6),                  /* 7 */
-	{NULL, NULL, 0, NULL, 0}
+	SETTING_FIELD (NM_SETTING_BRIDGE_MAC_ADDRESS, 19),                 /* 2 */
+	SETTING_FIELD (NM_SETTING_BRIDGE_STP, 5),                          /* 3 */
+	SETTING_FIELD (NM_SETTING_BRIDGE_PRIORITY, 6),                     /* 4 */
+	SETTING_FIELD (NM_SETTING_BRIDGE_FORWARD_DELAY, 6),                /* 5 */
+	SETTING_FIELD (NM_SETTING_BRIDGE_HELLO_TIME, 6),                   /* 6 */
+	SETTING_FIELD (NM_SETTING_BRIDGE_MAX_AGE, 6),                      /* 7 */
+	SETTING_FIELD (NM_SETTING_BRIDGE_AGEING_TIME, 6),                  /* 8 */
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_BRIDGE_ALL    "name"","\
                                          NM_SETTING_BRIDGE_INTERFACE_NAME","\
+                                         NM_SETTING_BRIDGE_MAC_ADDRESS","\
                                          NM_SETTING_BRIDGE_STP","\
                                          NM_SETTING_BRIDGE_PRIORITY","\
                                          NM_SETTING_BRIDGE_FORWARD_DELAY","\
@@ -573,12 +585,12 @@ static NmcOutputField nmc_fields_setting_bridge[] = {
 #define NMC_FIELDS_SETTING_BRIDGE_COMMON NMC_FIELDS_SETTING_BRIDGE_ALL
 
 /* Available fields for NM_SETTING_BRIDGE_PORT_SETTING_NAME */
-static NmcOutputField nmc_fields_setting_bridge_port[] = {
+NmcOutputField nmc_fields_setting_bridge_port[] = {
 	SETTING_FIELD ("name",  8),                                        /* 0 */
 	SETTING_FIELD (NM_SETTING_BRIDGE_PORT_PRIORITY, 10),               /* 1 */
 	SETTING_FIELD (NM_SETTING_BRIDGE_PORT_PATH_COST, 12),              /* 2 */
 	SETTING_FIELD (NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, 15),           /* 3 */
-	{NULL, NULL, 0, NULL, 0}
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
 };
 #define NMC_FIELDS_SETTING_BRIDGE_PORT_ALL    "name"","\
                                               NM_SETTING_BRIDGE_PORT_PRIORITY","\
@@ -586,15 +598,76 @@ static NmcOutputField nmc_fields_setting_bridge_port[] = {
                                               NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE
 #define NMC_FIELDS_SETTING_BRIDGE_PORT_COMMON NMC_FIELDS_SETTING_BRIDGE_PORT_ALL
 
+/* Available fields for NM_SETTING_TEAM_SETTING_NAME */
+NmcOutputField nmc_fields_setting_team[] = {
+	SETTING_FIELD ("name",  8),                                        /* 0 */
+	SETTING_FIELD (NM_SETTING_TEAM_INTERFACE_NAME, 15),                /* 1 */
+	SETTING_FIELD (NM_SETTING_TEAM_CONFIG, 30),                        /* 2 */
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
+};
+#define NMC_FIELDS_SETTING_TEAM_ALL     "name"","\
+                                        NM_SETTING_TEAM_INTERFACE_NAME","\
+                                        NM_SETTING_TEAM_CONFIG
+#define NMC_FIELDS_SETTING_TEAM_COMMON  NMC_FIELDS_SETTING_TEAM_ALL
+
+/* Available fields for NM_SETTING_TEAM_PORT_SETTING_NAME */
+NmcOutputField nmc_fields_setting_team_port[] = {
+	SETTING_FIELD ("name",  8),                                        /* 0 */
+	SETTING_FIELD (NM_SETTING_TEAM_PORT_CONFIG, 30),                   /* 1 */
+	{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
+};
+#define NMC_FIELDS_SETTING_TEAM_PORT_ALL     "name"","\
+                                             NM_SETTING_TEAM_PORT_CONFIG
+#define NMC_FIELDS_SETTING_TEAM_PORT_COMMON  NMC_FIELDS_SETTING_TEAM_PORT_ALL
+
+/* Available fields for NM_SETTING_DCB_SETTING_NAME */
+NmcOutputField nmc_fields_setting_dcb[] = {
+	SETTING_FIELD ("name",  8),                                        /* 0 */
+	SETTING_FIELD (NM_SETTING_DCB_APP_FCOE_FLAGS, 5),                  /* 1 */
+	SETTING_FIELD (NM_SETTING_DCB_APP_FCOE_PRIORITY, 5),               /* 2 */
+	SETTING_FIELD (NM_SETTING_DCB_APP_FCOE_MODE, 8),                   /* 3 */
+	SETTING_FIELD (NM_SETTING_DCB_APP_ISCSI_FLAGS, 5),                 /* 4 */
+	SETTING_FIELD (NM_SETTING_DCB_APP_ISCSI_PRIORITY, 5),              /* 5 */
+	SETTING_FIELD (NM_SETTING_DCB_APP_FIP_FLAGS, 5),                   /* 6 */
+	SETTING_FIELD (NM_SETTING_DCB_APP_FIP_PRIORITY, 5),                /* 7 */
+	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, 5),     /* 8 */
+	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, 10),          /* 9 */
+	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, 5),            /* 10 */
+	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_GROUP_ID, 10),              /* 11 */
+	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH, 30),       /* 12 */
+	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_BANDWIDTH, 30),             /* 13 */
+	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH, 10),      /* 14 */
+	SETTING_FIELD (NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS, 30),         /* 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
+#define NMC_FIELDS_SETTING_DCB_COMMON  NMC_FIELDS_SETTING_DCB_ALL
+
+/*----------------------------------------------------------------------------*/
 
 static char *
 wep_key_type_to_string (NMWepKeyType type)
 {
 	switch (type) {
 	case NM_WEP_KEY_TYPE_KEY:
-		return g_strdup_printf (_("%d (hex-ascii-key)"), type);
+		return g_strdup_printf (_("%d (key)"), type);
 	case NM_WEP_KEY_TYPE_PASSPHRASE:
-		return g_strdup_printf (_("%d (104/128-bit passphrase)"), type);
+		return g_strdup_printf (_("%d (passphrase)"), type);
 	case NM_WEP_KEY_TYPE_UNKNOWN:
 	default:
 		return g_strdup_printf (_("%d (unknown)"), type);
@@ -658,7 +731,7 @@ allowed_bands_to_string (guint32 bands)
 		g_string_append (band_str, _("WCDMA 3GPP UMTS 2600 MHz, "));
 
 	if (band_str->str[band_str->len-1] == '(')
-		g_string_assign (band_str, _("unknown"));
+		g_string_append (band_str, _("unknown"));
 	else
 		g_string_truncate (band_str, band_str->len-2);  /* chop off trailing ', ' */
 
@@ -686,7 +759,7 @@ vlan_flags_to_string (guint32 flags)
 		g_string_append (flag_str, _("LOOSE_BINDING, "));
 
 	if (flag_str->str[flag_str->len-1] == '(')
-		g_string_assign (flag_str, _("unknown"));
+		g_string_append (flag_str, _("unknown"));
 	else
 		g_string_truncate (flag_str, flag_str->len-2);  /* chop off trailing ', ' */
 
@@ -748,7 +821,7 @@ secret_flags_to_string (guint32 flags)
 		g_string_append (flag_str, _("not required, "));
 
 	if (flag_str->str[flag_str->len-1] == '(')
-		g_string_assign (flag_str, _("unknown"));
+		g_string_append (flag_str, _("unknown"));
 	else
 		g_string_truncate (flag_str, flag_str->len-2);  /* chop off trailing ', ' */
 
@@ -757,1335 +830,6504 @@ secret_flags_to_string (guint32 flags)
 	return g_string_free (flag_str, FALSE);
 }
 
-/*----------------------------------------------------------------------------*/
-
-gboolean
-setting_details (NMSetting *setting, NmCli *nmc)
+static void
+vpn_data_item (const char *key, const char *value, gpointer user_data)
 {
-	GType setting_type;
+	GString *ret_str = (GString *) user_data;
 
-	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+	if (ret_str->len != 0)
+		g_string_append (ret_str, ", ");
 
-	setting_type = G_OBJECT_TYPE (setting);
-
-	if (setting_type == NM_TYPE_SETTING_CONNECTION)
-		return setting_connection_details (NM_SETTING_CONNECTION (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_WIRED)
-		return setting_wired_details (NM_SETTING_WIRED (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_802_1X)
-		return setting_802_1X_details (NM_SETTING_802_1X (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_WIRELESS)
-		return setting_wireless_details (NM_SETTING_WIRELESS (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_WIRELESS_SECURITY)
-		return setting_wireless_security_details (NM_SETTING_WIRELESS_SECURITY (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_IP4_CONFIG)
-		return setting_ip4_config_details (NM_SETTING_IP4_CONFIG (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_IP6_CONFIG)
-		return setting_ip6_config_details (NM_SETTING_IP6_CONFIG (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_SERIAL)
-		return setting_serial_details (NM_SETTING_SERIAL (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_PPP)
-		return setting_ppp_details (NM_SETTING_PPP (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_PPPOE)
-		return setting_pppoe_details (NM_SETTING_PPPOE (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_GSM)
-		return setting_gsm_details (NM_SETTING_GSM (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_CDMA)
-		return setting_cdma_details (NM_SETTING_CDMA (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_BLUETOOTH)
-		return setting_bluetooth_details (NM_SETTING_BLUETOOTH (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_OLPC_MESH)
-		return setting_olpc_mesh_details (NM_SETTING_OLPC_MESH (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_VPN)
-		return setting_vpn_details (NM_SETTING_VPN (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_WIMAX)
-		return setting_wimax_details (NM_SETTING_WIMAX (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_INFINIBAND)
-		return setting_infiniband_details (NM_SETTING_INFINIBAND (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_BOND)
-		return setting_bond_details (NM_SETTING_BOND (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_VLAN)
-		return setting_vlan_details (NM_SETTING_VLAN (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_ADSL)
-		return setting_adsl_details (NM_SETTING_ADSL (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_BRIDGE)
-		return setting_bridge_details (NM_SETTING_BRIDGE (setting), nmc);
-	else if (setting_type == NM_TYPE_SETTING_BRIDGE_PORT)
-		return setting_bridge_port_details (NM_SETTING_BRIDGE_PORT (setting), nmc);
-	else
-		/* should not be reached */
-		return FALSE;
+	g_string_append_printf (ret_str, "%s = %s", key, value);
 }
 
-gboolean
-setting_connection_details (NMSettingConnection *s_con, NmCli *nmc)
-{
-	guint64 timestamp;
-	char *timestamp_str;
-	const char *perm_item;
-	const char *perm_type;
-	GString *perm = NULL;
-	GString *secondaries = NULL;
-	int i;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
-
-	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (s_con), FALSE);
 
-	nmc->allowed_fields = nmc_fields_setting_connection;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_CONNECTION_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
-
-	timestamp = nm_setting_connection_get_timestamp (s_con);
-	timestamp_str = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp);
-
-	/* get permissions */
-	perm = g_string_new (NULL);
-	for (i = 0; i < nm_setting_connection_get_num_permissions (s_con); i++) {
-		nm_setting_connection_get_permission (s_con, i, &perm_type, &perm_item, NULL);
-		g_string_append_printf (perm, "%s:%s,", perm_type, perm_item);
+/* === property get functions === */
+#define DEFINE_GETTER(func_name, property_name) \
+	static char * \
+	func_name (NMSetting *setting) \
+	{ \
+		char *s; \
+		GValue val = G_VALUE_INIT; \
+		g_value_init (&val, G_TYPE_STRING); \
+		g_object_get_property (G_OBJECT (setting), property_name, &val); \
+		/* Getters return allocated values, and returning the string \
+		 * the GValue copied from the object without unsetting the \
+		 * GValue fulfills that requirement. */ \
+		s = g_value_dup_string (&val); \
+		g_value_unset (&val); \
+		return s; \
 	}
-	if (perm->len > 0)
-		g_string_truncate (perm, perm->len-1); /* remove trailing , */
 
-	/* get secondaries */
-	secondaries = g_string_new (NULL);
-	for (i = 0; i < nm_setting_connection_get_num_secondaries (s_con); i++) {
-		const char *sec_uuid = nm_setting_connection_get_secondary (s_con, i);
-		g_string_append_printf (secondaries, "%s,", sec_uuid);
+#define DEFINE_SECRET_FLAGS_GETTER(func_name, property_name) \
+	static char * \
+	func_name (NMSetting *setting) \
+	{ \
+		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); \
 	}
-	if (secondaries->len > 0)
-		g_string_truncate (secondaries, secondaries->len-1); /* remove trailing , */
-
-	nmc->allowed_fields[0].value = NM_SETTING_CONNECTION_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_connection_get_id (s_con);
-	nmc->allowed_fields[2].value = nm_setting_connection_get_uuid (s_con);
-	nmc->allowed_fields[3].value = nm_setting_connection_get_connection_type (s_con);
-	nmc->allowed_fields[4].value = nm_setting_connection_get_autoconnect (s_con) ? _("yes") : _("no");
-	nmc->allowed_fields[5].value = timestamp_str;
-	nmc->allowed_fields[6].value = nm_setting_connection_get_read_only (s_con) ? ("yes") : _("no");
-	nmc->allowed_fields[7].value = perm->str;
-	nmc->allowed_fields[8].value = nm_setting_connection_get_zone (s_con);
-	nmc->allowed_fields[9].value = nm_setting_connection_get_master (s_con);
-	nmc->allowed_fields[10].value = nm_setting_connection_get_slave_type (s_con);
-	nmc->allowed_fields[11].value = secondaries->str;
-
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
-
-	g_free (timestamp_str);
-	g_string_free (perm, TRUE);
-	g_string_free (secondaries, TRUE);
 
-	return TRUE;
-}
-
-gboolean
-setting_wired_details (NMSettingWired *s_wired, NmCli *nmc)
-{
-	const GByteArray *mac;
-	const GSList *iter;
-	const GPtrArray *s390_channels;
-	int i;
-	char *speed_str, *mtu_str, *device_mac_str = NULL, *cloned_mac_str = NULL;
-	GString *mac_blacklist_s, *s390_channels_s, *s390_options_s;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
-
-	g_return_val_if_fail (NM_IS_SETTING_WIRED (s_wired), FALSE);
-
-	nmc->allowed_fields = nmc_fields_setting_wired;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_WIRED_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
-
-	speed_str = g_strdup_printf ("%d", nm_setting_wired_get_speed (s_wired));
-	mtu_str = g_strdup_printf ("%d", nm_setting_wired_get_mtu (s_wired));
-	mac = nm_setting_wired_get_mac_address (s_wired);
-	if (mac)
-		device_mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER);
-	mac = nm_setting_wired_get_cloned_mac_address (s_wired);
-	if (mac)
-		cloned_mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER);
-
-	mac_blacklist_s = g_string_new (NULL);
-	iter = nm_setting_wired_get_mac_address_blacklist (s_wired);
-	while (iter) {
-		g_string_append_printf (mac_blacklist_s, "%s,", (char *) iter->data);
-		iter = iter->next;
-	}
-	g_string_truncate (mac_blacklist_s, mac_blacklist_s->len-1);  /* chop off trailing ',' */
-
-	s390_channels_s = g_string_new (NULL);
-	s390_channels = nm_setting_wired_get_s390_subchannels (s_wired);
-	for (i = 0; s390_channels && i < s390_channels->len; i++)
-		g_string_append_printf (s390_channels_s, "%s,", (char *) g_ptr_array_index (s390_channels, i));
-	g_string_truncate (s390_channels_s, s390_channels_s->len-1);  /* chop off trailing ',' */
-
-	s390_options_s = g_string_new (NULL);
-	for (i = 0; i < nm_setting_wired_get_num_s390_options (s_wired); i++) {
-		const char *key, *value;
-
-		nm_setting_wired_get_s390_option (s_wired, i, &key, &value);
-		g_string_append_printf (s390_options_s, "%s=%s,", key, value);
+#define DEFINE_HWADDR_GETTER(func_name, property_name) \
+	static char * \
+	func_name (NMSetting *setting) \
+	{ \
+		GValue val = G_VALUE_INIT; \
+		GArray *array; \
+		char *hwaddr = NULL; \
+		g_value_init (&val, DBUS_TYPE_G_UCHAR_ARRAY); \
+		g_object_get_property (G_OBJECT (setting), property_name, &val); \
+		array = g_value_get_boxed (&val); \
+		if (array && array->len) \
+			hwaddr = nm_utils_hwaddr_ntoa_len (array->data, array->len); \
+		g_value_unset (&val); \
+		return hwaddr; \
 	}
-	g_string_truncate (s390_options_s, s390_options_s->len-1);  /* chop off trailing ',' */
-
-	nmc->allowed_fields[0].value = NM_SETTING_WIRED_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_wired_get_port (s_wired);
-	nmc->allowed_fields[2].value = speed_str;
-	nmc->allowed_fields[3].value = nm_setting_wired_get_duplex (s_wired);
-	nmc->allowed_fields[4].value = nm_setting_wired_get_auto_negotiate (s_wired) ? _("yes") : _("no");
-	nmc->allowed_fields[5].value = device_mac_str;
-	nmc->allowed_fields[6].value = cloned_mac_str;
-	nmc->allowed_fields[7].value = mac_blacklist_s->str;
-	nmc->allowed_fields[8].value = strcmp (mtu_str, "0") ? mtu_str : _("auto");
-	nmc->allowed_fields[9].value = s390_channels_s->str;
-	nmc->allowed_fields[10].value = nm_setting_wired_get_s390_nettype (s_wired);
-	nmc->allowed_fields[11].value = s390_options_s->str;
-
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
 
-	g_free (speed_str);
-	g_free (device_mac_str);
-	g_free (cloned_mac_str);
-	g_free (mtu_str);
-	g_string_free (mac_blacklist_s, TRUE);
-	g_string_free (s390_channels_s, TRUE);
-	g_string_free (s390_options_s, TRUE);
-
-	return TRUE;
-}
+/* --- NM_SETTING_802_1X_SETTING_NAME property get 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_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_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_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_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)
 
-gboolean
-setting_802_1X_details (NMSetting8021x *s_8021X, NmCli *nmc)
+static char *
+nmc_property_802_1X_get_ca_cert (NMSetting *setting)
 {
+	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
 	NMSetting8021xCKScheme scheme;
-	GString *eap_str, *alt_sub_match, *phase2_alt_sub_match;
-	char *ca_cert_str = NULL, *client_cert_str = NULL, *phase2_ca_cert_str = NULL;
-	char *phase2_client_cert_str = NULL, *private_key_str = NULL, *phase2_private_key_str = NULL, *pswd_raw_str = NULL;
-	char *pswd_flags, *pswd_raw_flags, *priv_key_pswd_flags, *phase2_priv_key_pswd_flags, *pin_flags;
-	int i;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
-
-	g_return_val_if_fail (NM_IS_SETTING_802_1X (s_8021X), FALSE);
+	char *ca_cert_str = NULL;
 
-	nmc->allowed_fields = nmc_fields_setting_8021X;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_802_1X_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
-
-	eap_str = g_string_new (NULL);
-	for (i = 0; i < nm_setting_802_1x_get_num_eap_methods (s_8021X); i++) {
-		if (i > 0)
-			g_string_append_c (eap_str, ',');
-		g_string_append (eap_str, nm_setting_802_1x_get_eap_method (s_8021X, i));
-	}
 	scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021X);
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
 		ca_cert_str = byte_array_to_string (nm_setting_802_1x_get_ca_cert_blob (s_8021X));
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
 		ca_cert_str = g_strdup (nm_setting_802_1x_get_ca_cert_path (s_8021X));
 
+	return ca_cert_str;
+}
+
+static char *
+nmc_property_802_1X_get_client_cert (NMSetting *setting)
+{
+	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
+	NMSetting8021xCKScheme scheme;
+	char *client_cert_str = NULL;
+
 	scheme = nm_setting_802_1x_get_client_cert_scheme (s_8021X);
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
 		client_cert_str = byte_array_to_string (nm_setting_802_1x_get_client_cert_blob (s_8021X));
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
 		client_cert_str = g_strdup (nm_setting_802_1x_get_client_cert_path (s_8021X));
 
+	return client_cert_str;
+}
+
+static char *
+nmc_property_802_1X_get_phase2_ca_cert (NMSetting *setting)
+{
+	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
+	NMSetting8021xCKScheme scheme;
+	char *phase2_ca_cert_str = NULL;
+
 	scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (s_8021X);
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
 		phase2_ca_cert_str = byte_array_to_string (nm_setting_802_1x_get_phase2_ca_cert_blob (s_8021X));
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
 		phase2_ca_cert_str = g_strdup (nm_setting_802_1x_get_phase2_ca_cert_path (s_8021X));
 
+	return phase2_ca_cert_str;
+}
+
+static char *
+nmc_property_802_1X_get_phase2_client_cert (NMSetting *setting)
+{
+	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
+	NMSetting8021xCKScheme scheme;
+	char *phase2_client_cert_str = NULL;
+
 	scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (s_8021X);
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
 		phase2_client_cert_str = byte_array_to_string (nm_setting_802_1x_get_phase2_client_cert_blob (s_8021X));
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
 		phase2_client_cert_str = g_strdup (nm_setting_802_1x_get_phase2_client_cert_path (s_8021X));
 
+	return phase2_client_cert_str;
+}
+
+static char *
+nmc_property_802_1X_get_password_raw (NMSetting *setting)
+{
+	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
+	return byte_array_to_string (nm_setting_802_1x_get_password_raw (s_8021X));
+}
+
+static char *
+nmc_property_802_1X_get_private_key (NMSetting *setting)
+{
+	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
+	NMSetting8021xCKScheme scheme;
+	char *private_key_str = NULL;
+
 	scheme = nm_setting_802_1x_get_private_key_scheme (s_8021X);
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
 		private_key_str = byte_array_to_string (nm_setting_802_1x_get_private_key_blob (s_8021X));
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
 		private_key_str = g_strdup (nm_setting_802_1x_get_private_key_path (s_8021X));
 
+	return private_key_str;
+}
+
+static char *
+nmc_property_802_1X_get_phase2_private_key (NMSetting *setting)
+{
+	NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting);
+	NMSetting8021xCKScheme scheme;
+	char *phase2_private_key_str = NULL;
+
 	scheme = nm_setting_802_1x_get_phase2_private_key_scheme (s_8021X);
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
 		phase2_private_key_str = byte_array_to_string (nm_setting_802_1x_get_phase2_private_key_blob (s_8021X));
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
 		phase2_private_key_str = g_strdup (nm_setting_802_1x_get_phase2_private_key_path (s_8021X));
 
-	alt_sub_match = g_string_new (NULL);
-	for (i = 0; i < nm_setting_802_1x_get_num_altsubject_matches (s_8021X); i++)
-		g_string_append_printf (alt_sub_match, "%s,", nm_setting_802_1x_get_altsubject_match (s_8021X, i));
-	g_string_truncate (alt_sub_match, alt_sub_match->len-1);  /* chop off trailing ',' */
-
-	phase2_alt_sub_match = g_string_new (NULL);
-	for (i = 0; i < nm_setting_802_1x_get_num_phase2_altsubject_matches (s_8021X); i++)
-		g_string_append_printf (phase2_alt_sub_match, "%s,", nm_setting_802_1x_get_phase2_altsubject_match (s_8021X, i));
-	g_string_truncate (phase2_alt_sub_match, phase2_alt_sub_match->len-1);  /* chop off trailing ',' */
-
-	pswd_raw_str = byte_array_to_string (nm_setting_802_1x_get_password_raw (s_8021X));
-
-	pswd_flags = secret_flags_to_string (nm_setting_802_1x_get_password_flags (s_8021X));
-	pswd_raw_flags = secret_flags_to_string (nm_setting_802_1x_get_password_raw_flags (s_8021X));
-	priv_key_pswd_flags = secret_flags_to_string (nm_setting_802_1x_get_private_key_password_flags (s_8021X));
-	phase2_priv_key_pswd_flags = secret_flags_to_string (nm_setting_802_1x_get_phase2_private_key_password_flags (s_8021X));
-	pin_flags = secret_flags_to_string (nm_setting_802_1x_get_pin_flags (s_8021X));
-
-	nmc->allowed_fields[0].value = NM_SETTING_802_1X_SETTING_NAME;
-	nmc->allowed_fields[1].value = eap_str->str;
-	nmc->allowed_fields[2].value = nm_setting_802_1x_get_identity (s_8021X);
-	nmc->allowed_fields[3].value = nm_setting_802_1x_get_anonymous_identity (s_8021X);
-	nmc->allowed_fields[4].value = nm_setting_802_1x_get_pac_file (s_8021X);
-	nmc->allowed_fields[5].value = ca_cert_str;
-	nmc->allowed_fields[6].value = nm_setting_802_1x_get_ca_path (s_8021X);
-	nmc->allowed_fields[7].value = nm_setting_802_1x_get_subject_match (s_8021X);
-	nmc->allowed_fields[8].value = alt_sub_match->str;
-	nmc->allowed_fields[9].value = client_cert_str;
-	nmc->allowed_fields[10].value = nm_setting_802_1x_get_phase1_peapver (s_8021X);
-	nmc->allowed_fields[11].value = nm_setting_802_1x_get_phase1_peaplabel (s_8021X);
-	nmc->allowed_fields[12].value = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021X);
-	nmc->allowed_fields[13].value = nm_setting_802_1x_get_phase2_auth (s_8021X);
-	nmc->allowed_fields[14].value = nm_setting_802_1x_get_phase2_autheap (s_8021X);
-	nmc->allowed_fields[15].value = phase2_ca_cert_str;
-	nmc->allowed_fields[16].value = nm_setting_802_1x_get_phase2_ca_path (s_8021X);
-	nmc->allowed_fields[17].value = nm_setting_802_1x_get_phase2_subject_match (s_8021X);
-	nmc->allowed_fields[18].value = phase2_alt_sub_match->str;
-	nmc->allowed_fields[19].value = phase2_client_cert_str;
-	nmc->allowed_fields[20].value = nm_setting_802_1x_get_password (s_8021X);
-	nmc->allowed_fields[21].value = pswd_flags;
-	nmc->allowed_fields[22].value = pswd_raw_str;
-	nmc->allowed_fields[23].value = pswd_raw_flags;
-	nmc->allowed_fields[24].value = private_key_str;
-	nmc->allowed_fields[25].value = nm_setting_802_1x_get_private_key_password (s_8021X);
-	nmc->allowed_fields[26].value = priv_key_pswd_flags;
-	nmc->allowed_fields[27].value = phase2_private_key_str;
-	nmc->allowed_fields[28].value = nm_setting_802_1x_get_phase2_private_key_password (s_8021X);
-	nmc->allowed_fields[29].value = phase2_priv_key_pswd_flags;
-	nmc->allowed_fields[30].value = nm_setting_802_1x_get_pin (s_8021X);
-	nmc->allowed_fields[31].value = pin_flags;
-	nmc->allowed_fields[32].value = nm_setting_802_1x_get_system_ca_certs (s_8021X) ? _("yes") : _("no");
-
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
-
-	g_free (ca_cert_str);
-	g_free (client_cert_str);
-	g_free (phase2_ca_cert_str);
-	g_free (phase2_client_cert_str);
-	g_free (private_key_str);
-	g_free (phase2_private_key_str);
-	g_free (pswd_flags);
-	g_free (pswd_raw_str);
-	g_free (pswd_raw_flags);
-	g_free (priv_key_pswd_flags);
-	g_free (phase2_priv_key_pswd_flags);
-	g_free (pin_flags);
-	g_string_free (eap_str, TRUE);
-	g_string_free (alt_sub_match, TRUE);
-	g_string_free (phase2_alt_sub_match, TRUE);
+	return phase2_private_key_str;
+}
 
-	return TRUE;
+/* --- NM_SETTING_ADSL_SETTING_NAME property get 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)
+
+/* --- NM_SETTING_BLUETOOTH_SETTING_NAME property get functions --- */
+DEFINE_HWADDR_GETTER (nmc_property_bluetooth_get_bdaddr, NM_SETTING_BLUETOOTH_BDADDR)
+DEFINE_GETTER (nmc_property_bluetooth_get_type, NM_SETTING_BLUETOOTH_TYPE)
+
+/* --- NM_SETTING_BOND_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_bond_get_interface_name, NM_SETTING_BOND_INTERFACE_NAME)
+
+static char *
+nmc_property_bond_get_options (NMSetting *setting)
+{
+	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;
+
+		nm_setting_bond_get_option (s_bond, i, &key, &value);
+		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);
 }
 
-gboolean
-setting_wireless_details (NMSettingWireless *s_wireless, NmCli *nmc)
+/* --- NM_SETTING_BRIDGE_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_bridge_get_interface_name, NM_SETTING_BRIDGE_INTERFACE_NAME)
+DEFINE_HWADDR_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)
+
+/* --- NM_SETTING_BRIDGE_PORT_SETTING_NAME property get 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_TEAM_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_team_get_interface_name, NM_SETTING_TEAM_INTERFACE_NAME)
+DEFINE_GETTER (nmc_property_team_get_config, NM_SETTING_TEAM_CONFIG)
+
+/* --- NM_SETTING_TEAM_PORT_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_team_port_get_config, NM_SETTING_TEAM_PORT_CONFIG)
+
+/* --- NM_SETTING_CDMA_SETTING_NAME property get 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_SECRET_FLAGS_GETTER (nmc_property_cdma_get_password_flags, NM_SETTING_CDMA_PASSWORD_FLAGS)
+
+/* --- NM_SETTING_CONNECTION_SETTING_NAME property get 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_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_timestamp, NM_SETTING_CONNECTION_TIMESTAMP)
+DEFINE_GETTER (nmc_property_connection_get_read_only, NM_SETTING_CONNECTION_READ_ONLY)
+
+static char *
+nmc_property_connection_get_permissions (NMSetting *setting)
 {
+	NMSettingConnection *s_con = NM_SETTING_CONNECTION (setting);
+	GString *perm = NULL;
+	const char *perm_item;
+	const char *perm_type;
 	int i;
-	const GByteArray *ssid, *bssid, *mac;
-	char *channel_str, *rate_str, *tx_power_str, *mtu_str;
-	char *device_mac_str = NULL, *cloned_mac_str = NULL, *ssid_str = NULL, *bssid_str = NULL;
-	GString *mac_blacklist, *seen_bssids;
-	const GSList *iter;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
 
-	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (s_wireless), FALSE);
+	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);
+}
+
+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)
+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)
+
+/* --- NM_SETTING_DCB_SETTING_NAME property get 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) \
+	{ \
+		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) \
+	{ \
+		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); \
+	}
 
-	nmc->allowed_fields = nmc_fields_setting_wireless;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_WIRELESS_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+#define DEFINE_DCB_BOOL_GETTER(func_name, getter_func_name) \
+	static char * \
+	func_name (NMSetting *setting) \
+	{ \
+		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) \
+	{ \
+		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)
+
+/* --- NM_SETTING_GSM_SETTING_NAME property get 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_network_type, NM_SETTING_GSM_NETWORK_TYPE)
+
+static char *
+nmc_property_gsm_get_allowed_bands (NMSetting *setting)
+{
+	NMSettingGsm *s_gsm = NM_SETTING_GSM (setting);
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+	return allowed_bands_to_string (nm_setting_gsm_get_allowed_bands (s_gsm));
+G_GNUC_END_IGNORE_DEPRECATIONS
+}
+
+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)
+
+/* --- NM_SETTING_INFINIBAND_SETTING_NAME property get functions --- */
+DEFINE_HWADDR_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)
+
+static char *
+nmc_property_ib_get_mtu (NMSetting *setting)
+{
+	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)
+{
+	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_IP4_CONFIG_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_ipv4_get_method, NM_SETTING_IP4_CONFIG_METHOD)
+DEFINE_GETTER (nmc_property_ipv4_get_dns, NM_SETTING_IP4_CONFIG_DNS)
+DEFINE_GETTER (nmc_property_ipv4_get_dns_search, NM_SETTING_IP4_CONFIG_DNS_SEARCH)
+DEFINE_GETTER (nmc_property_ipv4_get_addresses, NM_SETTING_IP4_CONFIG_ADDRESSES)
+DEFINE_GETTER (nmc_property_ipv4_get_routes, NM_SETTING_IP4_CONFIG_ROUTES)
+DEFINE_GETTER (nmc_property_ipv4_get_ignore_auto_routes, NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES)
+DEFINE_GETTER (nmc_property_ipv4_get_ignore_auto_dns, NM_SETTING_IP4_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_send_hostname, NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME)
+DEFINE_GETTER (nmc_property_ipv4_get_dhcp_hostname, NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME)
+DEFINE_GETTER (nmc_property_ipv4_get_never_default, NM_SETTING_IP4_CONFIG_NEVER_DEFAULT)
+DEFINE_GETTER (nmc_property_ipv4_get_may_fail, NM_SETTING_IP4_CONFIG_MAY_FAIL)
+
+/* --- NM_SETTING_IP6_CONFIG_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_ipv6_get_method, NM_SETTING_IP6_CONFIG_METHOD)
+DEFINE_GETTER (nmc_property_ipv6_get_dns, NM_SETTING_IP6_CONFIG_DNS)
+DEFINE_GETTER (nmc_property_ipv6_get_dns_search, NM_SETTING_IP6_CONFIG_DNS_SEARCH)
+DEFINE_GETTER (nmc_property_ipv6_get_addresses, NM_SETTING_IP6_CONFIG_ADDRESSES)
+DEFINE_GETTER (nmc_property_ipv6_get_routes, NM_SETTING_IP6_CONFIG_ROUTES)
+DEFINE_GETTER (nmc_property_ipv6_get_ignore_auto_routes, NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES)
+DEFINE_GETTER (nmc_property_ipv6_get_ignore_auto_dns, NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS)
+DEFINE_GETTER (nmc_property_ipv6_get_never_default, NM_SETTING_IP6_CONFIG_NEVER_DEFAULT)
+DEFINE_GETTER (nmc_property_ipv6_get_may_fail, NM_SETTING_IP6_CONFIG_MAY_FAIL)
+DEFINE_GETTER (nmc_property_ipv6_get_dhcp_hostname, NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME)
+
+static char *
+nmc_property_ipv6_get_ip6_privacy (NMSetting *setting)
+{
+	NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG (setting);
+	return ip6_privacy_to_string (nm_setting_ip6_config_get_ip6_privacy (s_ip6));
+}
+
+/* --- NM_SETTING_OLPC_MESH_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_olpc_get_channel, NM_SETTING_OLPC_MESH_CHANNEL)
+DEFINE_HWADDR_GETTER (nmc_property_olpc_get_anycast_address, NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS)
+
+static char *
+nmc_property_olpc_get_ssid (NMSetting *setting)
+{
+	NMSettingOlpcMesh *s_olpc_mesh = NM_SETTING_OLPC_MESH (setting);
+	const GByteArray *ssid;
+	char *ssid_str = NULL;
+
+	ssid = nm_setting_olpc_mesh_get_ssid (s_olpc_mesh);
+	if (ssid)
+		ssid_str = nm_utils_ssid_to_utf8 (ssid);
+
+	return ssid_str;
+}
+
+/* --- NM_SETTING_PPP_SETTING_NAME property get 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 get 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_SERIAL_SETTING_NAME property get 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_parity, NM_SETTING_SERIAL_PARITY)
+DEFINE_GETTER (nmc_property_serial_get_stopbits, NM_SETTING_SERIAL_STOPBITS)
+DEFINE_GETTER (nmc_property_serial_get_send_delay, NM_SETTING_SERIAL_SEND_DELAY)
+
+/* --- NM_SETTING_VLAN_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_vlan_get_interface_name, NM_SETTING_VLAN_INTERFACE_NAME)
+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)
+{
+	NMSettingVlan *s_vlan = NM_SETTING_VLAN (setting);
+	return vlan_flags_to_string (nm_setting_vlan_get_flags (s_vlan));
+}
+
+static char *
+nmc_property_vlan_get_ingress_priority_map (NMSetting *setting)
+{
+	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)
+{
+	NMSettingVlan *s_vlan = NM_SETTING_VLAN (setting);
+	return vlan_priorities_to_string (s_vlan, NM_VLAN_EGRESS_MAP);
+}
+
+/* --- NM_SETTING_VPN_SETTING_NAME property get 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)
+{
+	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)
+{
+	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);
+}
+
+/* --- NM_SETTING_WIMAX_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_wimax_get_network_name, NM_SETTING_WIMAX_NETWORK_NAME)
+DEFINE_HWADDR_GETTER (nmc_property_wimax_get_mac_address, NM_SETTING_WIMAX_MAC_ADDRESS)
+
+/* --- NM_SETTING_WIRED_SETTING_NAME property get functions --- */
+DEFINE_GETTER (nmc_property_wired_get_port, NM_SETTING_WIRED_PORT)
+DEFINE_GETTER (nmc_property_wired_get_speed, NM_SETTING_WIRED_SPEED)
+DEFINE_GETTER (nmc_property_wired_get_duplex, NM_SETTING_WIRED_DUPLEX)
+DEFINE_GETTER (nmc_property_wired_get_auto_negotiate, NM_SETTING_WIRED_AUTO_NEGOTIATE)
+DEFINE_HWADDR_GETTER (nmc_property_wired_get_mac_address, NM_SETTING_WIRED_MAC_ADDRESS)
+DEFINE_HWADDR_GETTER (nmc_property_wired_get_cloned_mac_address, NM_SETTING_WIRED_CLONED_MAC_ADDRESS)
+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)
+
+static char *
+nmc_property_wired_get_mtu (NMSetting *setting)
+{
+	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);
+}
+
+/* --- NM_SETTING_WIRELESS_SETTING_NAME property get 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_HWADDR_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_HWADDR_GETTER (nmc_property_wireless_get_mac_address, NM_SETTING_WIRELESS_MAC_ADDRESS)
+DEFINE_HWADDR_GETTER (nmc_property_wireless_get_cloned_mac_address, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)
+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)
+{
+	NMSettingWireless *s_wireless = NM_SETTING_WIRELESS (setting);
+	const GByteArray *ssid;
+	char *ssid_str = NULL;
 
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
 	if (ssid)
-		ssid_str = ssid_to_printable ((const char *) ssid->data, ssid->len);
-	channel_str = g_strdup_printf ("%d", nm_setting_wireless_get_channel (s_wireless));
-	rate_str = g_strdup_printf ("%d", nm_setting_wireless_get_rate (s_wireless));
-	bssid = nm_setting_wireless_get_bssid (s_wireless);
-	if (bssid)
-		bssid_str = nm_utils_hwaddr_ntoa (bssid->data, ARPHRD_ETHER);
-	tx_power_str = g_strdup_printf ("%d", nm_setting_wireless_get_tx_power (s_wireless));
-	mtu_str = g_strdup_printf ("%d", nm_setting_wireless_get_mtu (s_wireless));
-	mac = nm_setting_wireless_get_mac_address (s_wireless);
-	if (mac)
-		device_mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER);
-	mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
-	if (mac)
-		cloned_mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER);
-
-	mac_blacklist = g_string_new (NULL);
-	iter = nm_setting_wireless_get_mac_address_blacklist (s_wireless);
-	while (iter) {
-		g_string_append_printf (mac_blacklist, "%s,", (char *) iter->data);
-		iter = iter->next;
-	}
-	g_string_truncate (mac_blacklist, mac_blacklist->len-1);  /* chop off trailing ',' */
-
-	seen_bssids = g_string_new (NULL);
-	for (i = 0; i < nm_setting_wireless_get_num_seen_bssids (s_wireless); i++) {
-		if (i > 0)
-			g_string_append_c (seen_bssids, ',');
-		g_string_append (seen_bssids, nm_setting_wireless_get_seen_bssid (s_wireless, i));
-	}
-
-	nmc->allowed_fields[0].value = NM_SETTING_WIRELESS_SETTING_NAME;
-	nmc->allowed_fields[1].value = ssid_str;
-	nmc->allowed_fields[2].value = nm_setting_wireless_get_mode (s_wireless);
-	nmc->allowed_fields[3].value = nm_setting_wireless_get_band (s_wireless);
-	nmc->allowed_fields[4].value = channel_str;
-	nmc->allowed_fields[5].value = bssid_str;
-	nmc->allowed_fields[6].value = rate_str;
-	nmc->allowed_fields[7].value = tx_power_str;
-	nmc->allowed_fields[8].value = device_mac_str;
-	nmc->allowed_fields[9].value = cloned_mac_str;
-	nmc->allowed_fields[10].value = mac_blacklist->str;
-	nmc->allowed_fields[11].value = strcmp (mtu_str, "0") ?  mtu_str : _("auto");
-	nmc->allowed_fields[12].value = seen_bssids->str;
-	nmc->allowed_fields[13].value = nm_setting_wireless_get_security (s_wireless);
-	nmc->allowed_fields[14].value = nm_setting_wireless_get_hidden (s_wireless) ? _("yes") : _("no");
-
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
-
-	g_free (ssid_str);
-	g_free (channel_str);
-	g_free (bssid_str);
-	g_free (rate_str);
-	g_free (tx_power_str);
-	g_free (device_mac_str);
-	g_free (cloned_mac_str);
-	g_free (mtu_str);
-	g_string_free (seen_bssids, TRUE);
-	g_string_free (mac_blacklist, TRUE);
+		ssid_str = nm_utils_ssid_to_utf8 (ssid);
+
+	return ssid_str;
+}
+
+static char *
+nmc_property_wireless_get_mtu (NMSetting *setting)
+{
+	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);
+}
+
+/* --- NM_SETTING_WIRELESS_SECURITY_SETTING_NAME property get 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)
+{
+	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)
+{
+	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)
+{
+	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)
+{
+	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)
+{
+	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));
+}
+
+/*----------------------------------------------------------------------------*/
+
+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 *);
+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 *);
+typedef	      char * (*NmcPropertyOut2InFunc)   (const char *);
+
+typedef struct {
+	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 */
+	NmcPropertyOut2InFunc out2in_func;     /* func converting property values from output to input format */
+} NmcPropertyFuncs;
+
+/*
+ * We need NmCli in some _set_property functions, and they aren't passed NmCli.
+ * So use the global variable.
+ */
+/* Global variable defined in nmcli.c */
+extern NmCli nm_cli;
+
+NMSetting *
+nmc_setting_new_for_name (const char *name)
+{
+	GType stype;
+	NMSetting *setting = NULL;
+
+	if (name) {
+		stype = nm_connection_lookup_setting_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)
+{
+	char *tmp_str;
+	char *question;
+	gboolean answer = FALSE;
+
+	if (value)
+		question = g_strdup_printf (_("Do you also want to set '%s' to '%s'? [yes]: "), prop, value);
+	else
+		question = g_strdup_printf (_("Do you also want to clear '%s'? [yes]: "), prop);
+	tmp_str = nmc_get_user_input (question);
+	if (!tmp_str || matches (tmp_str, "yes") == 0)
+		answer = TRUE;
+	g_free (tmp_str);
+	g_free (question);
+	return answer;
+}
+
+static void ipv4_method_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data);
+static void ipv6_method_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data);
+
+static void
+ipv4_addresses_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+	static gboolean answered = FALSE;
+	static gboolean answer = FALSE;
+
+	g_signal_handlers_block_by_func (object, G_CALLBACK (ipv4_method_changed_cb), NULL);
+
+	/* If we have some IP addresses set method to 'manual'.
+	 * Else if the method was 'manual', change it back to 'auto'.
+	 */
+	if (nm_setting_ip4_config_get_num_addresses (NM_SETTING_IP4_CONFIG (object))) {
+		if (g_strcmp0 (nm_setting_ip4_config_get_method (NM_SETTING_IP4_CONFIG (object)), NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
+			if (!answered) {
+				answered = TRUE;
+				answer = get_answer ("ipv4.method", "manual");
+			}
+			if (answer)
+				g_object_set (object, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
+		}
+	} else {
+		answered = FALSE;
+		if (!g_strcmp0 (nm_setting_ip4_config_get_method (NM_SETTING_IP4_CONFIG (object)), NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
+			g_object_set (object, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+	}
+
+	g_signal_handlers_unblock_by_func (object, G_CALLBACK (ipv4_method_changed_cb), NULL);
+}
+
+static void
+ipv4_method_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+	static GValue value = G_VALUE_INIT;
+	static gboolean answered = FALSE;
+	static gboolean answer = FALSE;
+
+	g_signal_handlers_block_by_func (object, G_CALLBACK (ipv4_addresses_changed_cb), NULL);
+
+	/* If method != manual, remove addresses (save them for restoring them later when method becomes 'manual' */
+	if (g_strcmp0 (nm_setting_ip4_config_get_method (NM_SETTING_IP4_CONFIG (object)), NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
+		if (nm_setting_ip4_config_get_num_addresses (NM_SETTING_IP4_CONFIG (object))) {
+			if (!answered) {
+				answered = TRUE;
+				answer = get_answer ("ipv4.addresses", NULL);
+			}
+			if (answer) {
+				if (G_IS_VALUE (&value))
+					g_value_unset (&value);
+				nmc_property_get_gvalue (NM_SETTING (object), NM_SETTING_IP4_CONFIG_ADDRESSES, &value);
+				g_object_set (object, NM_SETTING_IP4_CONFIG_ADDRESSES, NULL, NULL);
+			}
+		}
+	} else {
+		answered = FALSE;
+		if (G_IS_VALUE (&value)) {
+			nmc_property_set_gvalue (NM_SETTING (object), NM_SETTING_IP4_CONFIG_ADDRESSES, &value);
+			g_value_unset (&value);
+		}
+	}
+
+	g_signal_handlers_unblock_by_func (object, G_CALLBACK (ipv4_addresses_changed_cb), NULL);
+}
+
+static void
+ipv6_addresses_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+	static gboolean answered = FALSE;
+	static gboolean answer = FALSE;
+
+	g_signal_handlers_block_by_func (object, G_CALLBACK (ipv6_method_changed_cb), NULL);
+
+	/* If we have some IP addresses set method to 'manual'.
+	 * Else if the method was 'manual', change it back to 'auto'.
+	 */
+	if (nm_setting_ip6_config_get_num_addresses (NM_SETTING_IP6_CONFIG (object))) {
+		if (g_strcmp0 (nm_setting_ip6_config_get_method (NM_SETTING_IP6_CONFIG (object)), NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+			if (!answered) {
+				answered = TRUE;
+				answer = get_answer ("ipv6.method", "manual");
+			}
+			if (answer)
+				g_object_set (object, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, NULL);
+		}
+	} else {
+		answered = FALSE;
+		if (!g_strcmp0 (nm_setting_ip6_config_get_method (NM_SETTING_IP6_CONFIG (object)), NM_SETTING_IP6_CONFIG_METHOD_MANUAL))
+			g_object_set (object, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
+	}
+
+	g_signal_handlers_unblock_by_func (object, G_CALLBACK (ipv6_method_changed_cb), NULL);
+}
+
+static void
+ipv6_method_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+	static GValue value = G_VALUE_INIT;
+	static gboolean answered = FALSE;
+	static gboolean answer = FALSE;
+
+	g_signal_handlers_block_by_func (object, G_CALLBACK (ipv6_addresses_changed_cb), NULL);
+
+	/* If method != manual, remove addresses (save them for restoring them later when method becomes 'manual' */
+	if (g_strcmp0 (nm_setting_ip6_config_get_method (NM_SETTING_IP6_CONFIG (object)), NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+		if (nm_setting_ip6_config_get_num_addresses (NM_SETTING_IP6_CONFIG (object))) {
+			if (!answered) {
+				answered = TRUE;
+				answer = get_answer ("ipv6.addresses", NULL);
+			}
+			if (answer) {
+				if (G_IS_VALUE (&value))
+					g_value_unset (&value);
+				nmc_property_get_gvalue (NM_SETTING (object), NM_SETTING_IP6_CONFIG_ADDRESSES, &value);
+				g_object_set (object, NM_SETTING_IP6_CONFIG_ADDRESSES, NULL, NULL);
+			}
+		}
+	} else {
+		answered = FALSE;
+		if (G_IS_VALUE (&value)) {
+			nmc_property_set_gvalue (NM_SETTING (object), NM_SETTING_IP6_CONFIG_ADDRESSES, &value);
+			g_value_unset (&value);
+		}
+	}
 
+	g_signal_handlers_unblock_by_func (object, G_CALLBACK (ipv6_addresses_changed_cb), NULL);
+}
+
+static void
+wireless_band_channel_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+	const char *value = NULL, *mode;
+	char str[16];
+	NMSettingWireless *s_wireless = NM_SETTING_WIRELESS (object);
+
+	if (strcmp (g_param_spec_get_name (pspec), NM_SETTING_WIRELESS_BAND) == 0) {
+		value = nm_setting_wireless_get_band (s_wireless);
+		if (!value)
+			return;
+	} else {
+		guint32 channel = nm_setting_wireless_get_channel (s_wireless);
+
+		if (channel == 0)
+			return;
+
+		g_snprintf (str, sizeof (str), "%d", nm_setting_wireless_get_channel (s_wireless));
+		value = str;
+	}
+
+	mode = nm_setting_wireless_get_mode (NM_SETTING_WIRELESS (object));
+	if (!mode || !*mode || strcmp (mode, NM_SETTING_WIRELESS_MODE_INFRA) == 0) {
+		printf (_("Warning: %s.%s set to '%s', but it might be ignored in infrastructure mode\n"),
+		        nm_setting_get_name (NM_SETTING (s_wireless)), g_param_spec_get_name (pspec),
+		        value);
+	}
+}
+
+void
+nmc_setting_ip4_connect_handlers (NMSettingIP4Config *setting)
+{
+	g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting));
+
+	g_signal_connect (setting, "notify::" NM_SETTING_IP4_CONFIG_ADDRESSES,
+	                  G_CALLBACK (ipv4_addresses_changed_cb), NULL);
+	g_signal_connect (setting, "notify::" NM_SETTING_IP4_CONFIG_METHOD,
+	                  G_CALLBACK (ipv4_method_changed_cb), NULL);
+}
+
+void
+nmc_setting_ip6_connect_handlers (NMSettingIP6Config *setting)
+{
+	g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
+
+	g_signal_connect (setting, "notify::" NM_SETTING_IP6_CONFIG_ADDRESSES,
+	                  G_CALLBACK (ipv6_addresses_changed_cb), NULL);
+	g_signal_connect (setting, "notify::" NM_SETTING_IP6_CONFIG_METHOD,
+	                  G_CALLBACK (ipv6_method_changed_cb), NULL);
+}
+
+void
+nmc_setting_wireless_connect_handlers (NMSettingWireless *setting)
+{
+	g_return_if_fail (NM_IS_SETTING_WIRELESS (setting));
+
+	g_signal_connect (setting, "notify::" NM_SETTING_WIRELESS_BAND,
+	                  G_CALLBACK (wireless_band_channel_changed_cb), NULL);
+	g_signal_connect (setting, "notify::" NM_SETTING_WIRELESS_CHANNEL,
+	                  G_CALLBACK (wireless_band_channel_changed_cb), NULL);
+}
+
+/*
+ * 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_IP4_CONFIG (setting)) {
+		g_object_set (NM_SETTING_IP4_CONFIG (setting),
+		              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+		              NULL);
+		nmc_setting_ip4_connect_handlers (NM_SETTING_IP4_CONFIG (setting));
+	} else if (NM_IS_SETTING_IP6_CONFIG (setting)) {
+		g_object_set (NM_SETTING_IP6_CONFIG (setting),
+		              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
+		              NULL);
+		nmc_setting_ip6_connect_handlers (NM_SETTING_IP6_CONFIG (setting));
+	} else if (NM_IS_SETTING_WIRELESS (setting)) {
+		g_object_set (NM_SETTING_WIRELESS (setting),
+		              NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
+		              NULL);
+		nmc_setting_wireless_connect_handlers (NM_SETTING_WIRELESS (setting));
+	}
+}
+
+/* === SetFunc, RemoveFunc, DescribeFunc, ValuesFunc functions === */
+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;
 }
 
-gboolean
-setting_wireless_security_details (NMSettingWirelessSecurity *s_wireless_sec, NmCli *nmc)
+/* Validate 'val' number against to int property spec */
+static gboolean
+validate_int (NMSetting *setting, const char* prop, gint val, GError **error)
 {
-	int i;
-	char *wep_tx_keyidx_str, *wep_key_type_str, *wep_flags, *psk_flags, *leap_flags;
-	GString *protos, *pairwises, *groups;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	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;
+}
 
-	g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (s_wireless_sec), FALSE);
+/* 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 <%d-%d>"),
+		             val, pspec_uint->minimum, pspec_uint->maximum);
+		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);
 
-	nmc->allowed_fields = nmc_fields_setting_wireless_security;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_WIRELESS_SECURITY_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
-
-	wep_tx_keyidx_str = g_strdup_printf ("%d", nm_setting_wireless_security_get_wep_tx_keyidx (s_wireless_sec));
-	protos = g_string_new (NULL);
-	for (i = 0; i < nm_setting_wireless_security_get_num_protos (s_wireless_sec); i++) {
-		if (i > 0)
-		g_string_append_c (protos, ',');
-		g_string_append (protos, nm_setting_wireless_security_get_proto (s_wireless_sec, i));
-	}
-	pairwises = g_string_new (NULL);
-	for (i = 0; i < nm_setting_wireless_security_get_num_pairwise (s_wireless_sec); i++) {
-		if (i > 0)
-		g_string_append_c (pairwises, ',');
-		g_string_append (pairwises, nm_setting_wireless_security_get_pairwise (s_wireless_sec, i));
-	}
-	groups = g_string_new (NULL);
-	for (i = 0; i < nm_setting_wireless_security_get_num_groups (s_wireless_sec); i++) {
-		if (i > 0)
-		g_string_append_c (groups, ',');
-		g_string_append (groups, nm_setting_wireless_security_get_group (s_wireless_sec, i));
-	}
-	wep_key_type_str = wep_key_type_to_string (nm_setting_wireless_security_get_wep_key_type (s_wireless_sec));
-
-	wep_flags = secret_flags_to_string (nm_setting_wireless_security_get_wep_key_flags (s_wireless_sec));
-	psk_flags = secret_flags_to_string (nm_setting_wireless_security_get_psk_flags (s_wireless_sec));
-	leap_flags = secret_flags_to_string (nm_setting_wireless_security_get_leap_password_flags (s_wireless_sec));
-
-	nmc->allowed_fields[0].value = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec);
-	nmc->allowed_fields[2].value = wep_tx_keyidx_str;
-	nmc->allowed_fields[3].value = nm_setting_wireless_security_get_auth_alg (s_wireless_sec);
-	nmc->allowed_fields[4].value = protos->str;
-	nmc->allowed_fields[5].value = pairwises->str;
-	nmc->allowed_fields[6].value = groups->str;
-	nmc->allowed_fields[7].value = nm_setting_wireless_security_get_leap_username (s_wireless_sec);
-	nmc->allowed_fields[8].value = nm_setting_wireless_security_get_wep_key (s_wireless_sec, 0);
-	nmc->allowed_fields[9].value = nm_setting_wireless_security_get_wep_key (s_wireless_sec, 1);
-	nmc->allowed_fields[10].value = nm_setting_wireless_security_get_wep_key (s_wireless_sec, 2);
-	nmc->allowed_fields[11].value = nm_setting_wireless_security_get_wep_key (s_wireless_sec, 3);
-	nmc->allowed_fields[12].value = wep_flags;
-	nmc->allowed_fields[13].value = wep_key_type_str;
-	nmc->allowed_fields[14].value = nm_setting_wireless_security_get_psk (s_wireless_sec);
-	nmc->allowed_fields[15].value = psk_flags;
-	nmc->allowed_fields[16].value = nm_setting_wireless_security_get_leap_password (s_wireless_sec);
-	nmc->allowed_fields[17].value = leap_flags;
-
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
-
-	g_free (wep_tx_keyidx_str);
-	g_free (wep_key_type_str);
-	g_free (wep_flags);
-	g_free (psk_flags);
-	g_free (leap_flags);
-	g_string_free (protos, TRUE);
-	g_string_free (pairwises, TRUE);
-	g_string_free (groups, TRUE);
+	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;
 }
 
-gboolean
-setting_ip4_config_details (NMSettingIP4Config *s_ip4, NmCli *nmc)
+#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) \
+	{ \
+		static char *values = NULL; \
+		if (G_UNLIKELY (values == NULL)) \
+			values = g_strjoinv (", ", (char **) valid_values); \
+		return values; \
+	}
+
+/* --- generic property setter functions --- */
+static gboolean
+nmc_property_set_string (NMSetting *setting, const char *prop, const char *val, GError **error)
 {
-	GString *dns_str, *dns_search_str, *addr_str, *route_str;
-	int i, num;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	g_object_set (setting, prop, val, NULL);
+	return TRUE;
+}
 
-	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (s_ip4), FALSE);
+static gboolean
+nmc_property_set_int (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	long val_int;
 
-	nmc->allowed_fields = nmc_fields_setting_ip4_config;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_IP4_CONFIG_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	dns_str = g_string_new (NULL);
-	num = nm_setting_ip4_config_get_num_dns (s_ip4);
-	for (i = 0; i < num; i++) {
-		char buf[INET_ADDRSTRLEN];
-		guint32 ip;
-
-		ip = nm_setting_ip4_config_get_dns (s_ip4, i);
-		memset (buf, 0, sizeof (buf));
-		inet_ntop (AF_INET, (const void *) &ip, buf, sizeof (buf));
-		if (i > 0)
-			g_string_append (dns_str, ", ");
-		g_string_append (dns_str, buf);
+	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;
 	}
 
-	dns_search_str = g_string_new (NULL);
-	num = nm_setting_ip4_config_get_num_dns_searches (s_ip4);
-	for (i = 0; i < num; i++) {
-		const char *domain;
-
-		domain = nm_setting_ip4_config_get_dns_search (s_ip4, i);
-		if (i > 0)
-			g_string_append (dns_search_str, ", ");
-		g_string_append (dns_search_str, domain);
+	/* Validate the number according to the property spec */
+	if (!validate_int (setting, prop, (gint) val_int, error))
+		return FALSE;
+
+	g_object_set (setting, prop, val_int, 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, 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_ssid (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	GByteArray *ssid_arr;
+
+	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;
 	}
 
-	addr_str = g_string_new (NULL);
-	num = nm_setting_ip4_config_get_num_addresses (s_ip4);
-	for (i = 0; i < num; i++) {
-		char buf[INET_ADDRSTRLEN];
-		char *tmp;
-		NMIP4Address *addr;
-		guint32 ip;
+	ssid_arr = g_byte_array_sized_new (strlen (val));
+	g_byte_array_append (ssid_arr, (const guint8 *) val, strlen (val));
+	g_object_set (setting, prop, ssid_arr, NULL);
+
+	return TRUE;
+}
+
+static gboolean
+nmc_property_set_mac (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	GByteArray *array;
 
-		if (i > 0)
-			g_string_append (addr_str, "; ");
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-		g_string_append (addr_str, "{ ");
+	array = nm_utils_hwaddr_atoba (val, ARPHRD_ETHER);
+	if (!array) {
+		g_set_error (error, 1, 0, _("'%s' is not a valid Ethernet MAC"), val);
+		return FALSE;
+	}
 
-		addr = nm_setting_ip4_config_get_address (s_ip4, i);
+	g_object_set (setting, prop, array, NULL);
+	g_byte_array_free (array, TRUE);
+	return TRUE;
+}
 
-		memset (buf, 0, sizeof (buf));
-		ip = nm_ip4_address_get_address (addr);
-		inet_ntop (AF_INET, (const void *) &ip, buf, sizeof (buf));
-		g_string_append_printf (addr_str, "ip = %s", buf);
+static gboolean
+nmc_property_set_mtu (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	const char *mtu = val;
 
-		tmp = g_strdup_printf ("/%u", nm_ip4_address_get_prefix (addr));
-		g_string_append (addr_str, tmp);
-		g_free (tmp);
+	if (strcmp (mtu, "auto") == 0)
+		mtu = "0";
 
-		memset (buf, 0, sizeof (buf));
-		ip = nm_ip4_address_get_gateway (addr);
-		inet_ntop (AF_INET, (const void *) &ip, buf, sizeof (buf));
-		g_string_append_printf (addr_str, ", gw = %s", buf);
+	return nmc_property_set_uint (setting, prop, mtu, error);
+}
 
-		g_string_append (addr_str, " }");
+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_iface_valid_name (val)) {
+		g_set_error (error, 1, 0, _("'%s' is not a valid interface name"), val);
+		return FALSE;
+	}
+	g_object_set (setting, prop, val, NULL);
+	return TRUE;
+}
+
+static gboolean
+nmc_property_set_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, G_MAXUINT32, &val_int)) {
+			g_set_error (error, 1, 0, _("'%s' is not a number"), *iter);
+			g_strfreev (strv);
+			return FALSE;
+		}
+		flags += val_int;
 	}
+	g_strfreev (strv);
 
-	route_str = g_string_new (NULL);
-	num = nm_setting_ip4_config_get_num_routes (s_ip4);
-	for (i = 0; i < num; i++) {
-		char buf[INET_ADDRSTRLEN];
-		char *tmp;
-		NMIP4Route *route;
-		guint32 ip;
+	/* Validate the number according to the property spec */
+	if (!validate_uint (setting, prop, (guint) flags, error))
+		return FALSE;
 
-		if (i > 0)
-			g_string_append (route_str, "; ");
+	g_object_set (setting, prop, (guint) flags, NULL);
+	return TRUE;
+}
+
+static gboolean
+nmc_util_is_domain (const char *domain)
+{
+	//FIXME: implement
+	return TRUE;
+}
+
+static gboolean
+nmc_property_set_byte_array (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	char **strv = NULL, **iter;
+	char *val_strip;
+	const char *delimiters = " \t,";
+	long int val_int;
+	char *bin;
+	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 */
+	bin = nm_utils_hexstr2bin (val_strip, strlen (val_strip));
+	if (bin) {
+		array = g_byte_array_sized_new (strlen (val_strip)/2);
+		g_byte_array_append (array, (const guint8 *) bin, strlen (val_strip)/2);
+		g_free (bin);
+		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++) {
+		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);
+			success = FALSE;
+			goto done;
+		}
+		g_byte_array_append (array, (const guint8 *) &val_int, 1);
+	}
 
-		g_string_append (route_str, "{ ");
+done:
+	if (success)
+		g_object_set (setting, prop, array, NULL);
 
-		route = nm_setting_ip4_config_get_route (s_ip4, i);
+	g_strfreev (strv);
+	if (array)
+		g_byte_array_free (array, TRUE);
+	return success;
+}
 
-		memset (buf, 0, sizeof (buf));
-		ip = nm_ip4_route_get_dest (route);
-		inet_ntop (AF_INET, (const void *) &ip, buf, sizeof (buf));
-		g_string_append_printf (route_str, "dst = %s", buf);
+#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, ARPHRD_ETHER, buf)) { \
+				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; \
+	}
 
-		tmp = g_strdup_printf ("/%u", nm_ip4_route_get_prefix (route));
-		g_string_append (route_str, tmp);
-		g_free (tmp);
+static char *
+nmc_property_out2in_cut_paren (const char *out_format)
+{
+	const char *p;
+	size_t n;
 
-		memset (buf, 0, sizeof (buf));
-		ip = nm_ip4_route_get_next_hop (route);
-		inet_ntop (AF_INET, (const void *) &ip, buf, sizeof (buf));
-		g_string_append_printf (route_str, ", nh = %s", buf);
+	p = strstr (out_format, " (");
+	n = p ? p - out_format : strlen (out_format);
+	return g_strndup (out_format, n);
+}
 
-		tmp = g_strdup_printf (", mt = %u", nm_ip4_route_get_metric (route));
-		g_string_append (route_str, tmp);
-		g_free (tmp);
+/* --- NM_SETTING_CONNECTION_SETTING_NAME property setter functions --- */
+#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);
 
-		g_string_append (route_str, " }");
+	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
 
-	nmc->allowed_fields[0].value = NM_SETTING_IP4_CONFIG_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_ip4_config_get_method (s_ip4);
-	nmc->allowed_fields[2].value = dns_str->str;
-	nmc->allowed_fields[3].value = dns_search_str->str;
-	nmc->allowed_fields[4].value = addr_str->str;
-	nmc->allowed_fields[5].value = route_str->str;
-	nmc->allowed_fields[6].value = nm_setting_ip4_config_get_ignore_auto_routes (s_ip4) ? _("yes") : _("no");
-	nmc->allowed_fields[7].value = nm_setting_ip4_config_get_ignore_auto_dns (s_ip4) ? _("yes") : _("no");
-	nmc->allowed_fields[8].value = nm_setting_ip4_config_get_dhcp_client_id (s_ip4);
-	nmc->allowed_fields[9].value = nm_setting_ip4_config_get_dhcp_send_hostname (s_ip4) ? _("yes") : _("no");
-	nmc->allowed_fields[10].value = nm_setting_ip4_config_get_dhcp_hostname (s_ip4);
-	nmc->allowed_fields[11].value = nm_setting_ip4_config_get_never_default (s_ip4) ? _("yes") : _("no");
-	nmc->allowed_fields[12].value = nm_setting_ip4_config_get_may_fail (s_ip4) ? _("yes") : _("no");
+/* 'permissions' */
+/* define from libnm-util/nm-setting-connection.c */
+#define PERM_USER_PREFIX  "user:"
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+static gboolean
+permissions_valid (const char *perm)
+{
+	if (!perm || perm[0] == '\0')
+		return FALSE;
 
-	g_string_free (dns_str, TRUE);
-	g_string_free (dns_search_str, TRUE);
-	g_string_free (addr_str, TRUE);
-	g_string_free (route_str, TRUE);
+	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;
 }
 
-gboolean
-setting_ip6_config_details (NMSettingIP6Config *s_ip6, NmCli *nmc)
+static gboolean
+nmc_property_connection_set_permissions (NMSetting *setting, const char *prop, const char *val, GError **error)
 {
-	GString *dns_str, *dns_search_str, *addr_str, *route_str;
-	char *ip6_privacy_str;
-	int i, num;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	char **strv = NULL;
+	guint i = 0;
 
-	g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (s_ip6), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	nmc->allowed_fields = nmc_fields_setting_ip6_config;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_IP6_CONFIG_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	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;
 
-	dns_str = g_string_new (NULL);
-	num = nm_setting_ip6_config_get_num_dns (s_ip6);
-	for (i = 0; i < num; i++) {
-		char buf[INET6_ADDRSTRLEN];
-		const struct in6_addr *ip;
+		if (strncmp (strv[i], PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0)
+			user = strv[i]+strlen (PERM_USER_PREFIX);
+		else
+			user = strv[i];
 
-		ip = nm_setting_ip6_config_get_dns (s_ip6, i);
-		memset (buf, 0, sizeof (buf));
-		inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf));
-		if (i > 0)
-			g_string_append (dns_str, ", ");
-		g_string_append (dns_str, buf);
+		nm_setting_connection_add_permission (NM_SETTING_CONNECTION (setting), "user", user, NULL);
 	}
 
-	dns_search_str = g_string_new (NULL);
-	num = nm_setting_ip6_config_get_num_dns_searches (s_ip6);
-	for (i = 0; i < num; i++) {
-		const char *domain;
+	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_iface_valid_name (val)
+	         && !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_VLAN_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)
 
-		domain = nm_setting_ip6_config_get_dns_search (s_ip6, i);
-		if (i > 0)
-			g_string_append (dns_search_str, ", ");
-		g_string_append (dns_search_str, domain);
+/* 'secondaries' */
+static gboolean
+nmc_property_connection_set_secondaries (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	NMConnection *con;
+	char **strv = NULL, **iter;
+	guint i = 0;
+
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	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 (nm_cli.system_connections,
+			                           "uuid", *iter, NULL);
+			if (!con)
+				printf (_("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 (nm_cli.system_connections,
+			                           "id", *iter, NULL);
+			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));
+		}
 	}
 
-	addr_str = g_string_new (NULL);
-	num = nm_setting_ip6_config_get_num_addresses (s_ip6);
-	for (i = 0; i < num; i++) {
-		char buf[INET6_ADDRSTRLEN];
-		char *tmp;
-		NMIP6Address *addr;
-		const struct in6_addr *ip;
+	while (strv && strv[i])
+		nm_setting_connection_add_secondary (NM_SETTING_CONNECTION (setting), strv[i++]);
+	g_strfreev (strv);
 
-		if (i > 0)
-			g_string_append (addr_str, "; ");
+	return TRUE;
+}
 
-		g_string_append (addr_str, "{ ");
+static gboolean
+_validate_and_remove_connection_secondary (NMSettingConnection *setting,
+                                           const char *secondary_uuid,
+                                           GError **error)
+{
+	gboolean ret;
 
-		addr = nm_setting_ip6_config_get_address (s_ip6, i);
+	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;
+	}
 
-		memset (buf, 0, sizeof (buf));
-		ip = nm_ip6_address_get_address (addr);
-		inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf));
-		g_string_append_printf (addr_str, "ip = %s", buf);
+	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");
+}
 
-		tmp = g_strdup_printf ("/%u", nm_ip6_address_get_prefix (addr));
-		g_string_append (addr_str, tmp);
-		g_free (tmp);
+/* --- NM_SETTING_802_1X_SETTING_NAME property setter functions --- */
+#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; \
+	}
 
-		memset (buf, 0, sizeof (buf));
-		ip = nm_ip6_address_get_gateway (addr);
-		inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf));
-		g_string_append_printf (addr_str, ", gw = %s", buf);
+#define DEFINE_SETTER_CERT(def_func, set_func) \
+	static gboolean \
+	def_func (NMSetting *setting, const char *prop, const char *val, GError **error) \
+	{ \
+		const char *SCHEME_PATH = "file://"; \
+		char *val_strip = g_strstrip (g_strdup (val)); \
+		char *p = val_strip; \
+		gboolean success; \
+		\
+		if (strncmp (val_strip, SCHEME_PATH, strlen (SCHEME_PATH)) == 0) \
+			p += strlen (SCHEME_PATH); \
+		\
+		success = set_func (NM_SETTING_802_1X (setting), \
+		                    p, \
+		                    NM_SETTING_802_1X_CK_SCHEME_PATH, \
+		                    NULL, \
+		                    error); \
+		g_free (val_strip); \
+		return success; \
+	}
 
-		g_string_append (addr_str, " }");
+#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; \
+		const char *SCHEME_PATH = "file://"; \
+		char *val_strip = g_strstrip (g_strdup (val)); \
+		char *p = val_strip; \
+		const char *path, *password; \
+		gboolean success; \
+		\
+		if (strncmp (val_strip, SCHEME_PATH, strlen (SCHEME_PATH)) == 0) \
+			p += strlen (SCHEME_PATH); \
+		\
+		strv = nmc_strsplit_set (p, " \t,", 2); \
+		path = strv[0]; \
+		if (g_strv_length (strv) == 2) \
+			password = strv[1]; \
+		else \
+			password = pwd_func (NM_SETTING_802_1X (setting)); \
+		if (password) { \
+			char *tmp_pwd = g_strdup (password); \
+			success = set_func (NM_SETTING_802_1X (setting), \
+			                    path, \
+			                    tmp_pwd, \
+			                    NM_SETTING_802_1X_CK_SCHEME_PATH, \
+			                    NULL, \
+			                    error); \
+			g_free (tmp_pwd); \
+		} else { \
+			success = FALSE; \
+			g_set_error_literal  (error, 1, 0, _("private key password not provided")); \
+		} \
+		g_free (val_strip); \
+		g_strfreev (strv); \
+		return success; \
 	}
 
-	route_str = g_string_new (NULL);
-	num = nm_setting_ip6_config_get_num_routes (s_ip6);
-	for (i = 0; i < num; i++) {
-		char buf[INET6_ADDRSTRLEN];
-		char *tmp;
-		NMIP6Route *route;
-		const struct in6_addr *ip;
+/* 'eap' */
+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)
+{
+	const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", NULL };
+	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)
+
+/* 'ca-cert' */
+DEFINE_SETTER_CERT (nmc_property_802_1X_set_ca_cert, nm_setting_802_1x_set_ca_cert)
+
+/* '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)
+
+/* 'phase2-ca-cert' */
+DEFINE_SETTER_CERT (nmc_property_802_1X_set_phase2_ca_cert, nm_setting_802_1x_set_phase2_ca_cert)
+
+/* '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)
+
+/* '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 path> [<password>]\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);
+}
 
-		if (i > 0)
-			g_string_append (route_str, "; ");
+DEFINE_ALLOWED_VAL_FUNC (nmc_property_802_1X_allowed_phase2_autheap, _802_1X_valid_phase2_autheaps)
 
-		g_string_append (route_str, "{ ");
+/* '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_byte_array (setting, prop, val, error);
+}
 
-		route = nm_setting_ip6_config_get_route (s_ip6, i);
+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");
+}
 
-		memset (buf, 0, sizeof (buf));
-		ip = nm_ip6_route_get_dest (route);
-		inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf));
-		g_string_append_printf (route_str, "dst = %s", buf);
+/* --- NM_SETTING_ADSL_SETTING_NAME property setter functions --- */
+/* 'protocol' */
+static const char *adsl_valid_protocols[] = {
+	NM_SETTING_ADSL_PROTOCOL_PPPOA,
+	NM_SETTING_ADSL_PROTOCOL_PPPOE,
+	NM_SETTING_ADSL_PROTOCOL_IPOATM,
+	NULL
+};
 
-		tmp = g_strdup_printf ("/%u", nm_ip6_route_get_prefix (route));
-		g_string_append (route_str, tmp);
-		g_free (tmp);
+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);
+}
 
-		memset (buf, 0, sizeof (buf));
-		ip = nm_ip6_route_get_next_hop (route);
-		inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf));
-		g_string_append_printf (route_str, ", nh = %s", buf);
+DEFINE_ALLOWED_VAL_FUNC (nmc_property_adsl_allowed_protocol, adsl_valid_protocols)
 
-		tmp = g_strdup_printf (", mt = %u", nm_ip6_route_get_metric (route));
-		g_string_append (route_str, tmp);
-		g_free (tmp);
+/* 'encapsulation' */
+static const char *adsl_valid_encapsulations[] = {
+	NM_SETTING_ADSL_ENCAPSULATION_VCMUX,
+	NM_SETTING_ADSL_ENCAPSULATION_LLC,
+	NULL
+};
 
-		g_string_append (route_str, " }");
+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 setter functions --- */
+/* '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 setter functions --- */
+/* 'options' */
+/*  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;
+}
+
+DEFINE_SETTER_OPTIONS (nmc_property_bond_set_options,
+                       NM_SETTING_BOND,
+                       NMSettingBond,
+                       nm_setting_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)
+{
+	const char **valid_options;
+	static char *allowed_vals = NULL;
 
-	ip6_privacy_str = ip6_privacy_to_string (nm_setting_ip6_config_get_ip6_privacy (s_ip6));
+	if (G_UNLIKELY (allowed_vals == NULL)) {
+		valid_options = nm_setting_bond_get_valid_options (NM_SETTING_BOND (setting));
+		allowed_vals = g_strjoinv (", ", (char **) valid_options);
+	}
+	return allowed_vals;
+}
 
-	nmc->allowed_fields[0].value = NM_SETTING_IP6_CONFIG_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_ip6_config_get_method (s_ip6);
-	nmc->allowed_fields[2].value = dns_str->str;
-	nmc->allowed_fields[3].value = dns_search_str->str;
-	nmc->allowed_fields[4].value = addr_str->str;
-	nmc->allowed_fields[5].value = route_str->str;
-	nmc->allowed_fields[6].value = nm_setting_ip6_config_get_ignore_auto_routes (s_ip6) ? _("yes") : _("no");
-	nmc->allowed_fields[7].value = nm_setting_ip6_config_get_ignore_auto_dns (s_ip6) ? _("yes") : _("no");
-	nmc->allowed_fields[8].value = nm_setting_ip6_config_get_never_default (s_ip6) ? _("yes") : _("no");
-	nmc->allowed_fields[9].value = nm_setting_ip6_config_get_may_fail (s_ip6) ? _("yes") : _("no");
-	nmc->allowed_fields[10].value = ip6_privacy_str;
-	nmc->allowed_fields[11].value = nm_setting_ip6_config_get_dhcp_hostname (s_ip6);
+/* --- NM_SETTING_INFINIBAND_SETTING_NAME property setter functions --- */
+/* 'mac-addresss' */
+static gboolean
+nmc_property_ib_set_mac (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	GByteArray *array;
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	g_string_free (dns_str, TRUE);
-	g_string_free (dns_search_str, TRUE);
-	g_string_free (addr_str, TRUE);
-	g_string_free (route_str, TRUE);
-	g_free (ip6_privacy_str);
+	array = nm_utils_hwaddr_atoba (val, ARPHRD_INFINIBAND);
+	if (!array) {
+		g_set_error (error, 1, 0, _("'%s' is not a valid InfiniBand MAC"), val);
+		return FALSE;
+	}
 
+	g_object_set (setting, prop, array, NULL);
+	g_byte_array_free (array, TRUE);
 	return TRUE;
 }
 
-gboolean
-setting_serial_details (NMSettingSerial *s_serial, NmCli *nmc)
+/* '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)
 {
-	char *baud_str, *bits_str, *parity_str, *stopbits_str, *send_delay_str;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	return check_and_set_string (setting, prop, val, ib_valid_transport_modes, error);
+}
 
-	g_return_val_if_fail (NM_IS_SETTING_SERIAL (s_serial), FALSE);
+DEFINE_ALLOWED_VAL_FUNC (nmc_property_ib_allowed_transport_mode, ib_valid_transport_modes)
 
-	nmc->allowed_fields = nmc_fields_setting_serial;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_SERIAL_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+/* '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;
 
-	baud_str = g_strdup_printf ("%d", nm_setting_serial_get_baud (s_serial));
-	bits_str = g_strdup_printf ("%d", nm_setting_serial_get_bits (s_serial));
-	parity_str = g_strdup_printf ("%c", nm_setting_serial_get_parity (s_serial));
-	stopbits_str = g_strdup_printf ("%d", nm_setting_serial_get_stopbits (s_serial));
-	send_delay_str = g_strdup_printf ("%" G_GUINT64_FORMAT, nm_setting_serial_get_send_delay (s_serial));
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	nmc->allowed_fields[0].value = NM_SETTING_SERIAL_SETTING_NAME;
-	nmc->allowed_fields[1].value = baud_str;
-	nmc->allowed_fields[2].value = bits_str;
-	nmc->allowed_fields[3].value = parity_str;
-	nmc->allowed_fields[4].value = stopbits_str;
-	nmc->allowed_fields[5].value = send_delay_str;
+	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;
+}
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+/* --- NM_SETTING_IP4_CONFIG_SETTING_NAME property setter functions --- */
+/* '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
+};
 
-	g_free (baud_str);
-	g_free (bits_str);
-	g_free (parity_str);
-	g_free (stopbits_str);
-	g_free (send_delay_str);
+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") == 0)
+		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;
+	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++) {
+		if (inet_pton (AF_INET, g_strstrip (*iter), &ip4_addr) < 1) {
+			g_set_error (error, 1, 0, _("invalid IPv4 address '%s'"), *iter);
+			g_strfreev (strv);
+			return FALSE;
+		}
+		nm_setting_ip4_config_add_dns (NM_SETTING_IP4_CONFIG (setting), ip4_addr);
+	}
+	g_strfreev (strv);
 	return TRUE;
 }
 
-gboolean
-setting_ppp_details (NMSettingPPP *s_ppp, NmCli *nmc)
+static gboolean
+_validate_and_remove_ipv4_dns (NMSettingIP4Config *setting,
+                               const char *dns,
+                               GError **error)
 {
-	char *baud_str, *mru_str, *mtu_str, *lcp_echo_failure_str, *lcp_echo_interval_str;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	guint32 ip4_addr;
+	gboolean ret;
 
-	g_return_val_if_fail (NM_IS_SETTING_PPP (s_ppp), FALSE);
+	if (inet_pton (AF_INET, dns, &ip4_addr) < 1) {
+		g_set_error (error, 1, 0, _("invalid IPv4 address '%s'"), dns);
+		return FALSE;
+	}
 
-	nmc->allowed_fields = nmc_fields_setting_ppp;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_PPP_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
-
-	baud_str = g_strdup_printf ("%d", nm_setting_ppp_get_baud (s_ppp));
-	mru_str = g_strdup_printf ("%d", nm_setting_ppp_get_mru (s_ppp));
-	mtu_str = g_strdup_printf ("%d", nm_setting_ppp_get_mtu (s_ppp));
-	lcp_echo_failure_str = g_strdup_printf ("%d", nm_setting_ppp_get_lcp_echo_failure (s_ppp));
-	lcp_echo_interval_str = g_strdup_printf ("%d", nm_setting_ppp_get_lcp_echo_interval (s_ppp));
-
-	nmc->allowed_fields[0].value = NM_SETTING_PPP_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_ppp_get_noauth (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[2].value = nm_setting_ppp_get_refuse_eap (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[3].value = nm_setting_ppp_get_refuse_pap (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[4].value = nm_setting_ppp_get_refuse_chap (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[5].value = nm_setting_ppp_get_refuse_mschap (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[6].value = nm_setting_ppp_get_refuse_mschapv2 (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[7].value = nm_setting_ppp_get_nobsdcomp (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[8].value = nm_setting_ppp_get_nodeflate (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[9].value = nm_setting_ppp_get_no_vj_comp (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[10].value = nm_setting_ppp_get_require_mppe (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[11].value = nm_setting_ppp_get_require_mppe_128 (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[12].value = nm_setting_ppp_get_mppe_stateful (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[13].value = nm_setting_ppp_get_crtscts (s_ppp) ? _("yes") : _("no");
-	nmc->allowed_fields[14].value = baud_str;
-	nmc->allowed_fields[15].value = mru_str;
-	nmc->allowed_fields[16].value = mtu_str;
-	nmc->allowed_fields[17].value = lcp_echo_failure_str;
-	nmc->allowed_fields[18].value = lcp_echo_interval_str;
-
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
-
-	g_free (baud_str);
-	g_free (mru_str);
-	g_free (mtu_str);
-	g_free (lcp_echo_failure_str);
-	g_free (lcp_echo_interval_str);
+	ret = nm_setting_ip4_config_remove_dns_by_value (setting, ip4_addr);
+	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_IP4_CONFIG,
+                               nm_setting_ip4_config_get_num_dns,
+                               nm_setting_ip4_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_ip4_config_add_dns_search (NM_SETTING_IP4_CONFIG (setting), strv[i++]);
+	g_strfreev (strv);
 
 	return TRUE;
 }
 
-gboolean
-setting_pppoe_details (NMSettingPPPOE *s_pppoe, NmCli *nmc)
+static gboolean
+_validate_and_remove_ipv4_dns_search (NMSettingIP4Config *setting,
+                                      const char *dns_search,
+                                      GError **error)
 {
-	char *pswd_flags;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	gboolean ret;
+
+	ret = nm_setting_ip4_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_IP4_CONFIG,
+                               nm_setting_ip4_config_get_num_dns_searches,
+                               nm_setting_ip4_config_remove_dns_search,
+                               _validate_and_remove_ipv4_dns_search)
+
+/* 'addresses' */
+static NMIP4Address *
+_parse_ipv4_address (const char *address, GError **error)
+{
+	char *value = g_strdup (address);
+	char **addrv;
+	NMIP4Address *ip4addr;
+
+	addrv = nmc_strsplit_set (g_strstrip (value), " \t", 0);
+	if (addrv[0] == NULL || g_strv_length (addrv) > 2) {
+		g_set_error (error, 1, 0, _("'%s' is not valid (use ip[/prefix] [gateway])"),
+		             address);
+		g_free (value);
+		g_strfreev (addrv);
+		return NULL;
+	}
+	ip4addr = nmc_parse_and_build_ip4_address (addrv[0], addrv[1], error);
+	g_free (value);
+	g_strfreev (addrv);
+	return ip4addr;
+}
 
-	g_return_val_if_fail (NM_IS_SETTING_PPPOE (s_pppoe), FALSE);
+static gboolean
+nmc_property_ipv4_set_addresses (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	char **strv = NULL, **iter;
+	NMIP4Address *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_ip4_config_add_address (NM_SETTING_IP4_CONFIG (setting), ip4addr);
+		nm_ip4_address_unref (ip4addr);
+	}
+	g_strfreev (strv);
+	return TRUE;
+}
+
+static gboolean
+_validate_and_remove_ipv4_address (NMSettingIP4Config *setting,
+                                   const char *address,
+                                   GError **error)
+{
+	NMIP4Address *ip4addr;
+	gboolean ret;
 
-	nmc->allowed_fields = nmc_fields_setting_pppoe;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_PPPOE_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	ip4addr = _parse_ipv4_address (address, error);
+	if (!ip4addr)
+		return FALSE;
 
-	pswd_flags = secret_flags_to_string (nm_setting_pppoe_get_password_flags (s_pppoe));
+	ret = nm_setting_ip4_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_ip4_address_unref (ip4addr);
+	return ret;
+}
+DEFINE_REMOVER_INDEX_OR_VALUE (nmc_property_ipv4_remove_addresses,
+                               NM_SETTING_IP4_CONFIG,
+                               nm_setting_ip4_config_get_num_addresses,
+                               nm_setting_ip4_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] [gateway], ip[/prefix] [gateway],...\n"
+	         "Missing prefix is regarded as prefix of 32.\n\n"
+	         "Example: 192.168.1.5/24 192.168.1.1, 10.0.0.11/24\n");
+}
 
-	nmc->allowed_fields[0].value = NM_SETTING_PPPOE_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_pppoe_get_service (s_pppoe);
-	nmc->allowed_fields[2].value = nm_setting_pppoe_get_username (s_pppoe);
-	nmc->allowed_fields[3].value = nm_setting_pppoe_get_password (s_pppoe);
-	nmc->allowed_fields[4].value = pswd_flags;
+/*
+ * from: { ip = 1.2.3.4/24, gw = 1.2.3.254 }; { ip = 2.2.2.2/16, gw = 5.5.5.5 }
+ * to:   1.2.3.4/24 1.2.3.254, 2.2.2.2/16 5.5.5.5
+ * from: { ip = 11::22/64, gw = 22::33 }; { ip = ab::cd/64, gw = ab::1 }
+ * to:   11::22/64 22:33, ab::cd/64 ab::1
+*/
+static char *
+nmc_property_out2in_addresses (const char *out_format)
+{
+        GRegex *regex;
+	GString *str;
+        char **strv;
+	int i;
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	str = g_string_sized_new (128);
+	regex = g_regex_new ("\\{ ip = ([^/]+)/([^,]+), gw = ([^ ]+) \\}", 0, 0, NULL);
+
+	strv = g_regex_split (regex, out_format, 0);
+	for (i = 1; strv && strv[i] && strv[i+1] && strv[i+2]; i=i+4) {
+		g_string_append (str, strv[i]); /* IP */
+		g_string_append_c (str, '/');
+		g_string_append (str, strv[i+1]); /* prefix */
+		g_string_append_c (str, ' ');
+		g_string_append (str, strv[i+2]); /* gateway */
+		g_string_append (str, ", ");
+	}
+	if (str->len > 0)
+		g_string_truncate (str, str->len - 2);
 
-	g_free (pswd_flags);
+	g_strfreev (strv);
+	g_regex_unref (regex);
 
+	return g_string_free (str, FALSE);
+}
+
+/* 'routes' */
+static NMIP4Route *
+_parse_ipv4_route (const char *route, GError **error)
+{
+	char *value = g_strdup (route);
+	char **routev;
+	guint len;
+	NMIP4Route *ip4route = NULL;
+
+	routev = nmc_strsplit_set (g_strstrip (value), " \t", 0);
+	len = g_strv_length (routev);
+	if (len < 1 || len > 3) {
+		g_set_error (error, 1, 0, _("'%s' is not valid (the format is: ip[/prefix] [next-hop] [metric])"),
+		             route);
+		goto finish;
+	}
+	ip4route = nmc_parse_and_build_ip4_route (routev[0], routev[1], len >= 2 ? routev[2] : NULL, error);
+
+finish:
+	g_free (value);
+	g_strfreev (routev);
+	return ip4route;
+}
+
+static gboolean
+nmc_property_ipv4_set_routes (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	char **strv = NULL, **iter;
+	NMIP4Route *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_ip4_config_add_route (NM_SETTING_IP4_CONFIG (setting), ip4route);
+		nm_ip4_route_unref (ip4route);
+	}
+	g_strfreev (strv);
 	return TRUE;
 }
 
-gboolean
-setting_gsm_details (NMSettingGsm *s_gsm, NmCli *nmc)
+static gboolean
+_validate_and_remove_ipv4_route (NMSettingIP4Config *setting,
+                                 const char *route,
+                                 GError **error)
 {
-	char *network_type_str, *allowed_bands_str, *pswd_flags, *pin_flags;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	NMIP4Route *ip4route;
+	gboolean ret;
 
-	g_return_val_if_fail (NM_IS_SETTING_GSM (s_gsm), FALSE);
+	ip4route = _parse_ipv4_route (route, error);
+	if (!ip4route)
+		return FALSE;
+
+	ret = nm_setting_ip4_config_remove_route_by_value (setting, ip4route);
+	if (!ret)
+		g_set_error (error, 1, 0, _("the property doesn't contain route '%s'"), route);
+	nm_ip4_route_unref (ip4route);
+	return ret;
+}
+DEFINE_REMOVER_INDEX_OR_VALUE (nmc_property_ipv4_remove_routes,
+                               NM_SETTING_IP4_CONFIG,
+                               nm_setting_ip4_config_get_num_routes,
+                               nm_setting_ip4_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 or 0 means a default metric (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");
+}
+
+static char *
+nmc_property_out2in_routes (const char *out_format)
+{
+        GRegex *regex;
+	GString *str;
+        char **strv;
+	int i;
 
-	nmc->allowed_fields = nmc_fields_setting_gsm;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_GSM_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	str = g_string_sized_new (128);
+	regex = g_regex_new ("\\{ dst = ([^/]+)/([^,]+), nh = ([^,]+), mt = ([^ ]+) \\}", 0, 0, NULL);
+
+	strv = g_regex_split (regex, out_format, 0);
+	for (i = 1; strv && strv[i] && strv[i+1] && strv[i+2] && strv[i+3]; i=i+5) {
+		g_string_append (str, strv[i]); /* IP */
+		g_string_append_c (str, '/');
+		g_string_append (str, strv[i+1]); /* prefix */
+		g_string_append_c (str, ' ');
+		g_string_append (str, strv[i+2]); /* next hop */
+		g_string_append_c (str, ' ');
+		g_string_append (str, strv[i+3]); /* metric */
+		g_string_append (str, ", ");
+	}
+	if (str->len > 0)
+		g_string_truncate (str, str->len - 2);
 
-	network_type_str = g_strdup_printf ("%d", nm_setting_gsm_get_network_type (s_gsm));
-	allowed_bands_str = allowed_bands_to_string (nm_setting_gsm_get_allowed_bands (s_gsm));
+	g_strfreev (strv);
+	g_regex_unref (regex);
 
-	pswd_flags = secret_flags_to_string (nm_setting_gsm_get_password_flags (s_gsm));
-	pin_flags = secret_flags_to_string (nm_setting_gsm_get_pin_flags (s_gsm));
+	return g_string_free (str, FALSE);
+}
 
-	nmc->allowed_fields[0].value = NM_SETTING_GSM_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_gsm_get_number (s_gsm);
-	nmc->allowed_fields[2].value = nm_setting_gsm_get_username (s_gsm);
-	nmc->allowed_fields[3].value = nm_setting_gsm_get_password (s_gsm);
-	nmc->allowed_fields[4].value = pswd_flags;
-	nmc->allowed_fields[5].value = nm_setting_gsm_get_apn (s_gsm);
-	nmc->allowed_fields[6].value = nm_setting_gsm_get_network_id (s_gsm);
-	nmc->allowed_fields[7].value = network_type_str;
-	nmc->allowed_fields[8].value = allowed_bands_str;
-	nmc->allowed_fields[9].value = nm_setting_gsm_get_pin (s_gsm);
-	nmc->allowed_fields[10].value = pin_flags;
-	nmc->allowed_fields[11].value = nm_setting_gsm_get_home_only (s_gsm) ? _("yes") : _("no");
+/* --- NM_SETTING_IP6_CONFIG_SETTING_NAME property setter functions --- */
+/* '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") == 0)
+		val = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	return check_and_set_string (setting, prop, val, ipv6_valid_methods, error);
+}
 
-	g_free (network_type_str);
-	g_free (allowed_bands_str);
-	g_free (pswd_flags);
-	g_free (pin_flags);
+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;
+	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++) {
+		if (inet_pton (AF_INET6, g_strstrip (*iter), &ip6_addr) < 1) {
+			g_set_error (error, 1, 0, _("invalid IPv6 address '%s'"), *iter);
+			g_strfreev (strv);
+			return FALSE;
+		}
+		nm_setting_ip6_config_add_dns (NM_SETTING_IP6_CONFIG (setting), &ip6_addr);
+	}
+	g_strfreev (strv);
 	return TRUE;
 }
 
-gboolean
-setting_cdma_details (NMSettingCdma *s_cdma, NmCli *nmc)
+static gboolean
+_validate_and_remove_ipv6_dns (NMSettingIP6Config *setting,
+                               const char *dns,
+                               GError **error)
 {
-	char *pswd_flags;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	struct in6_addr ip6_addr;
+	gboolean ret;
 
-	g_return_val_if_fail (NM_IS_SETTING_CDMA (s_cdma), FALSE);
+	if (inet_pton (AF_INET6, dns, &ip6_addr) < 1) {
+		g_set_error (error, 1, 0, _("invalid IPv6 address '%s'"), dns);
+		return FALSE;
+	}
 
-	nmc->allowed_fields = nmc_fields_setting_cdma;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_CDMA_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	ret = nm_setting_ip6_config_remove_dns_by_value (setting, &ip6_addr);
+	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_IP6_CONFIG,
+                               nm_setting_ip6_config_get_num_dns,
+                               nm_setting_ip6_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");
+}
 
-	pswd_flags = secret_flags_to_string (nm_setting_cdma_get_password_flags (s_cdma));
+/* '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;
 
-	nmc->allowed_fields[0].value = NM_SETTING_CDMA_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_cdma_get_number (s_cdma);
-	nmc->allowed_fields[2].value = nm_setting_cdma_get_username (s_cdma);
-	nmc->allowed_fields[3].value = nm_setting_cdma_get_password (s_cdma);
-	nmc->allowed_fields[4].value = pswd_flags;
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	strv = nmc_strsplit_set (val, " \t,", 0);
+	if (!verify_string_list (strv, prop, nmc_util_is_domain, error)) {
+		g_strfreev (strv);
+		return FALSE;
+	}
 
-	g_free (pswd_flags);
+	while (strv && strv[i])
+		nm_setting_ip6_config_add_dns_search (NM_SETTING_IP6_CONFIG (setting), strv[i++]);
+	g_strfreev (strv);
 
 	return TRUE;
 }
 
-gboolean
-setting_bluetooth_details (NMSettingBluetooth *s_bluetooth, NmCli *nmc)
+static gboolean
+_validate_and_remove_ipv6_dns_search (NMSettingIP6Config *setting,
+                                      const char *dns_search,
+                                      GError **error)
 {
-	const GByteArray *bdaddr;
-	char *bdaddr_str = NULL;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	gboolean ret;
+
+	ret = nm_setting_ip6_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_IP6_CONFIG,
+                               nm_setting_ip6_config_get_num_dns_searches,
+                               nm_setting_ip6_config_remove_dns_search,
+                               _validate_and_remove_ipv6_dns_search)
+
+/* 'addresses' */
+static NMIP6Address *
+_parse_ipv6_address (const char *address, GError **error)
+{
+	char *value = g_strstrip (g_strdup (address));
+	char **addrv;
+	NMIP6Address *ip6addr;
+
+	addrv = nmc_strsplit_set (g_strstrip (value), " \t", 0);
+	if (addrv[0] == NULL || g_strv_length (addrv) > 2) {
+		g_set_error (error, 1, 0, _("'%s' is not valid (use ip[/prefix] [gateway])"),
+		             address);
+		g_free (value);
+		g_strfreev (addrv);
+		return NULL;
+	}
+	ip6addr = nmc_parse_and_build_ip6_address (addrv[0], addrv[1], error);
+	g_free (value);
+	g_strfreev (addrv);
+	return ip6addr;
+}
 
-	g_return_val_if_fail (NM_IS_SETTING_BLUETOOTH (s_bluetooth), FALSE);
+static gboolean
+nmc_property_ipv6_set_addresses (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	char **strv = NULL, **iter;
+	NMIP6Address *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_ip6_config_add_address (NM_SETTING_IP6_CONFIG (setting), ip6addr);
+		nm_ip6_address_unref (ip6addr);
+	}
+	g_strfreev (strv);
+	return TRUE;
+}
 
-	nmc->allowed_fields = nmc_fields_setting_bluetooth;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_BLUETOOTH_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+static gboolean
+_validate_and_remove_ipv6_address (NMSettingIP6Config *setting,
+                                   const char *address,
+                                   GError **error)
+{
+	NMIP6Address *ip6addr;
+	gboolean ret;
 
-	bdaddr = nm_setting_bluetooth_get_bdaddr (s_bluetooth);
-	if (bdaddr)
-		bdaddr_str = nm_utils_hwaddr_ntoa (bdaddr->data, ARPHRD_ETHER);
+	ip6addr = _parse_ipv6_address (address, error);
+	if (!ip6addr)
+		return FALSE;
 
-	nmc->allowed_fields[0].value = NM_SETTING_BLUETOOTH_SETTING_NAME;
-	nmc->allowed_fields[1].value = bdaddr_str;
-	nmc->allowed_fields[2].value = nm_setting_bluetooth_get_connection_type (s_bluetooth);
+	ret = nm_setting_ip6_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_ip6_address_unref (ip6addr);
+	return ret;
+}
+DEFINE_REMOVER_INDEX_OR_VALUE (nmc_property_ipv6_remove_addresses,
+                               NM_SETTING_IP6_CONFIG,
+                               nm_setting_ip6_config_get_num_addresses,
+                               nm_setting_ip6_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] [gateway], ip[/prefix] [gateway],...\n"
+	         "Missing prefix is regarded as prefix of 128.\n\n"
+	         "Example: 2607:f0d0:1002:51::4/64 2607:f0d0:1002:51::1, 1050:0:0:0:5:600:300c:326b\n");
+}
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+/* 'routes' */
+static NMIP6Route *
+_parse_ipv6_route (const char *route, GError **error)
+{
+	char *value = g_strdup (route);
+	char **routev;
+	guint len;
+	NMIP6Route *ip6route = NULL;
+
+	routev = nmc_strsplit_set (g_strstrip (value), " \t", 0);
+	len = g_strv_length (routev);
+	if (len < 1 || len > 3) {
+		g_set_error (error, 1, 0, _("'%s' is not valid (the format is: ip[/prefix] [next-hop] [metric])"),
+		             route);
+		goto finish;
+	}
+	ip6route = nmc_parse_and_build_ip6_route (routev[0], routev[1], len >= 2 ? routev[2] : NULL, error);
 
-	g_free (bdaddr_str);
+finish:
+	g_free (value);
+	g_strfreev (routev);
+	return ip6route;
+}
 
+static gboolean
+nmc_property_ipv6_set_routes (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	char **strv = NULL, **iter;
+	NMIP6Route *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_ip6_config_add_route (NM_SETTING_IP6_CONFIG (setting), ip6route);
+		nm_ip6_route_unref (ip6route);
+	}
+	g_strfreev (strv);
 	return TRUE;
 }
 
-gboolean
-setting_olpc_mesh_details (NMSettingOlpcMesh *s_olpc_mesh, NmCli *nmc)
+static gboolean
+_validate_and_remove_ipv6_route (NMSettingIP6Config *setting,
+                                 const char *route,
+                                 GError **error)
 {
-	const GByteArray *ssid, *dhcp_anycast;
-	char *channel_str, *ssid_str = NULL, *dhcp_anycast_str = NULL;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	NMIP6Route *ip6route;
+	gboolean ret;
 
-	g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (s_olpc_mesh), FALSE);
+	ip6route = _parse_ipv6_route (route, error);
+	if (!ip6route)
+		return FALSE;
+
+	ret = nm_setting_ip6_config_remove_route_by_value (setting, ip6route);
+	if (!ret)
+		g_set_error (error, 1, 0, _("the property doesn't contain route '%s'"), route);
+	nm_ip6_route_unref (ip6route);
+	return ret;
+}
+DEFINE_REMOVER_INDEX_OR_VALUE (nmc_property_ipv6_remove_routes,
+                               NM_SETTING_IP6_CONFIG,
+                               nm_setting_ip6_config_get_num_routes,
+                               nm_setting_ip6_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 or 0 means a default metric (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");
+}
 
-	nmc->allowed_fields = nmc_fields_setting_olpc_mesh;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_OLPC_MESH_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+static gboolean
+nmc_property_ipv6_set_ip6_privacy (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	unsigned long val_int;
 
-	ssid = nm_setting_olpc_mesh_get_ssid (s_olpc_mesh);
-	if (ssid)
-		ssid_str = ssid_to_printable ((const char *) ssid->data, ssid->len);
-	channel_str = g_strdup_printf ("%d", nm_setting_olpc_mesh_get_channel (s_olpc_mesh));
-	dhcp_anycast = nm_setting_olpc_mesh_get_dhcp_anycast_address (s_olpc_mesh);
-	if (dhcp_anycast)
-		dhcp_anycast_str = nm_utils_hwaddr_ntoa (dhcp_anycast->data, ARPHRD_ETHER);
+	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;
+}
+
+/* --- NM_SETTING_OLPC_MESH_SETTING_NAME property setter functions --- */
+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_SERIAL_SETTING_NAME property setter functions --- */
+static gboolean
+nmc_property_serial_set_parity (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+	char parity;
+
+	if (val[0] == 'E' || val[0] == 'e')
+		parity = 'E';
+	else if (val[0] == 'O' || val[0] == 'o')
+		parity = 'o';
+	else if (val[0] == 'N' || val[0] == 'n')
+		parity = 'n';
+	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 --- */
+/* --- NM_SETTING_TEAM_PORT_SETTING_NAME property functions --- */
+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_VLAN_SETTING_NAME property setter functions --- */
+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])
+			printf (_("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 setter functions --- */
+/* 'data' */
+DEFINE_SETTER_OPTIONS (nmc_property_vpn_set_data,
+                       NM_SETTING_VPN,
+                       NMSettingVPN,
+                       nm_setting_vpn_add_data_item,
+                       NULL,
+                       NULL)
+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,
+                       NULL)
+DEFINE_REMOVER_OPTION (nmc_property_vpn_remove_option_secret,
+                       NM_SETTING_VPN,
+                       nm_setting_vpn_remove_secret)
+
+/* --- NM_SETTING_WIMAX_SETTING_NAME property setter functions --- */
+/* No specific functions */
+
+/* --- NM_SETTING_WIRED_SETTING_NAME property setter functions --- */
+#if 0
+/*
+ * Do not allow setting 'port' and 'duplex' for now. They are 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)
+
+/* '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)
+#endif
+
+/* '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, ARPHRD_ETHER, buf)) {
+		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, **iter;
+	GPtrArray *s390_subchannels;
+
+	//FIXME: both libnm-util and ifcfg-rh also allow two strings (3rd is optional)
+	strv = nmc_strsplit_set (val, " ,\t", 0);
+	if (g_strv_length (strv) != 3) {
+		g_set_error (error, 1, 0, _("'%s' is not valid; 3 strings should be provided"),
+		             val);
+		g_strfreev (strv);
+		return FALSE;
+	}
+
+	s390_subchannels = g_ptr_array_sized_new (3);
+	for (iter = strv; iter && *iter; iter++)
+		g_ptr_array_add (s390_subchannels, *iter);
+
+	g_object_set (setting, prop, s390_subchannels, NULL);
+	g_strfreev (strv);
+	g_ptr_array_free (s390_subchannels, TRUE);
+	return TRUE;
+}
+
+static const char *
+nmc_property_wired_describe_s390_subchannels (NMSetting *setting, const char *prop)
+{
+	return _("Enter a list of three channels (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' */
+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,
+                       NULL)
+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)
+{
+	const char **valid_options;
+	static char *allowed_vals = NULL;
+
+	if (G_UNLIKELY (allowed_vals == NULL)) {
+		valid_options = nm_setting_wired_get_valid_s390_options (NM_SETTING_WIRED (setting));
+		allowed_vals = g_strjoinv (", ", (char **) valid_options);
+	}
+	return allowed_vals;
+}
 
-	nmc->allowed_fields[0].value = NM_SETTING_OLPC_MESH_SETTING_NAME;
-	nmc->allowed_fields[1].value = ssid_str;
-	nmc->allowed_fields[2].value = channel_str;
-	nmc->allowed_fields[3].value = dhcp_anycast_str;
+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 setter functions --- */
+/* '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, ARPHRD_ETHER, buf)) {
+		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)
+
+/* --- NM_SETTING_WIRELESS_SECURITY_SETTING_NAME property setter functions --- */
+/* '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_SETTER_STR_LIST_MULTI (check_and_add_wifi_sec_proto,
+                              NM_SETTING_WIRELESS_SECURITY,
+                              nm_setting_wireless_security_add_proto)
+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 };
+
+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_SETTER_STR_LIST_MULTI (check_and_add_wifi_sec_pairwise,
+                              NM_SETTING_WIRELESS_SECURITY,
+                              nm_setting_wireless_security_add_pairwise)
+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 };
+
+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_SETTER_STR_LIST_MULTI (check_and_add_wifi_sec_group,
+                              NM_SETTING_WIRELESS_SECURITY,
+                              nm_setting_wireless_security_add_group)
+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 };
+
+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';
+	printf (_("WEP key is guessed to be of '%s'\n"), wep_key_type_to_string (guessed_type));
+	if (idx != prev_idx)
+		printf (_("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;
+}
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+/* '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))
+		printf (_("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))
+		printf (_("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))
+		printf (_("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))
+		printf (_("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;
+}
+
+#define DCB_ALL_FLAGS (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING)
+
+/* DCB stuff */
+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 number according to the property spec */
+	if (!validate_uint (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;
+	}
 
-	g_free (ssid_str);
-	g_free (channel_str);
-	g_free (dhcp_anycast_str);
+	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
-vpn_data_item (const char *key, const char *value, gpointer user_data)
+dcb_check_feature_enabled (NMSettingDcb *s_dcb, const char *flags_prop)
 {
-	GString *ret_str = (GString *) user_data;
+	NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE;
 
-	if (ret_str->len != 0)
-		g_string_append (ret_str, ", ");
+	g_object_get (s_dcb, flags_prop, &flags, NULL);
+	if (!(flags & NM_SETTING_DCB_FLAG_ENABLE))
+		printf (_("Warning: changes will have no effect until '%s' includes 1 (enabled)\n\n"), flags_prop);
+}
 
-	g_string_append_printf (ret_str, "%s = %s", key, value);
+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;
 }
 
-gboolean
-setting_vpn_details (NMSettingVPN *s_vpn, NmCli *nmc)
+static gboolean
+nmc_property_dcb_set_pg_group_id (NMSetting *setting, const char *prop, const char *val, GError **error)
 {
-	GString *data_item_str, *secret_str;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	guint i = 0;
+	guint nums[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
-	g_return_val_if_fail (NM_IS_SETTING_VPN (s_vpn), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	nmc->allowed_fields = nmc_fields_setting_vpn;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_VPN_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	if (!dcb_parse_uint_array (val, 7, 15, nums, error))
+		return FALSE;
 
-	data_item_str = g_string_new (NULL);
-	secret_str = g_string_new (NULL);
-	nm_setting_vpn_foreach_data_item (s_vpn, &vpn_data_item, data_item_str);
-	nm_setting_vpn_foreach_secret (s_vpn, &vpn_data_item, secret_str);
+	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;
+}
 
-	nmc->allowed_fields[0].value = NM_SETTING_VPN_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_vpn_get_service_type (s_vpn);
-	nmc->allowed_fields[2].value = nm_setting_vpn_get_user_name (s_vpn);
-	nmc->allowed_fields[3].value = data_item_str->str;
-	nmc->allowed_fields[4].value = secret_str->str;
+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 };
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	g_string_free (data_item_str, TRUE);
-	g_string_free (secret_str, TRUE);
+	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;
 }
 
-gboolean
-setting_wimax_details (NMSettingWimax *s_wimax, NmCli *nmc)
+static gboolean
+nmc_property_dcb_set_pg_bandwidth (NMSetting *setting, const char *prop, const char *val, GError **error)
 {
-	const GByteArray *mac;
-	char *device_mac_str = NULL;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	guint i = 0;
+	guint nums[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
-	g_return_val_if_fail (NM_IS_SETTING_WIMAX (s_wimax), FALSE);
+	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;
 
-	nmc->allowed_fields = nmc_fields_setting_wimax;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_WIMAX_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	for (i = 0; i < 8; i++)
+		nm_setting_dcb_set_priority_strict_bandwidth (NM_SETTING_DCB (setting), i, !!nums[i]);
 
-	mac = nm_setting_wimax_get_mac_address (s_wimax);
-	if (mac)
-		device_mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER);
+	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 };
 
-	nmc->allowed_fields[0].value = NM_SETTING_WIMAX_SETTING_NAME;
-	nmc->allowed_fields[1].value = device_mac_str;
-	nmc->allowed_fields[2].value = nm_setting_wimax_get_network_name (s_wimax);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	if (!dcb_parse_uint_array (val, 7, 0, nums, error))
+		return FALSE;
 
-	g_free (device_mac_str);
+	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)
+
+/*----------------------------------------------------------------------------*/
+
+static void
+nmc_add_prop_funcs (char *key,
+                    NmcPropertyGetFunc get_func,
+                    NmcPropertySetFunc set_func,
+                    NmcPropertyRemoveFunc remove_func,
+                    NmcPropertyDescribeFunc describe_func,
+                    NmcPropertyValuesFunc values_func,
+                    NmcPropertyOut2InFunc out2in_func)
+{
+	NmcPropertyFuncs *item = g_malloc0 (sizeof (NmcPropertyFuncs));
+	item->get_func = get_func;
+	item->set_func = set_func;
+	item->remove_func = remove_func;
+	item->describe_func = describe_func;
+	item->values_func = values_func;
+	item->out2in_func = out2in_func;
+
+	g_hash_table_insert (nmc_properties, key, item);
+}
+
+/* concatenate setting name and property name */
+#define GLUE(A,B) (g_strconcat ((NM_SETTING_##A##_SETTING_NAME),(NM_SETTING_##A##_##B), NULL))
+void
+nmc_properties_init (void)
+{
+	if (G_LIKELY (nmc_properties))
+		return;
+
+	/* create properties hash table */
+	nmc_properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 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,
+	                    NULL,
+	                    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,
+	                    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, CLIENT_CERT),
+	                    nmc_property_802_1X_get_client_cert,
+	                    nmc_property_802_1X_set_client_cert,
+	                    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, 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,
+	                    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_CLIENT_CERT),
+	                    nmc_property_802_1X_get_phase2_client_cert,
+	                    nmc_property_802_1X_set_phase2_client_cert,
+	                    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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	nmc_add_prop_funcs (GLUE (802_1X, PRIVATE_KEY),
+	                    nmc_property_802_1X_get_private_key,
+	                    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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	nmc_add_prop_funcs (GLUE (802_1X, PHASE2_PRIVATE_KEY),
+	                    nmc_property_802_1X_get_phase2_private_key,
+	                    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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	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);
+
+	/* 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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	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, INTERFACE_NAME),
+	                    nmc_property_bond_get_interface_name,
+	                    nmc_property_set_ifname,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	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, INTERFACE_NAME),
+	                    nmc_property_bridge_get_interface_name,
+	                    nmc_property_set_ifname,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	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);
+
+	/* 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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+
+	/* 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, 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,
+	                    NULL, /* read-only */
+	                    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, 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, 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);
+
+	/* 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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	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, NETWORK_TYPE),
+	                    nmc_property_gsm_get_network_type,
+	                    nmc_property_set_int,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (GSM, ALLOWED_BANDS),
+	                    nmc_property_gsm_get_allowed_bands,
+	                    nmc_property_set_uint,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	nmc_add_prop_funcs (GLUE (GSM, HOME_ONLY),
+	                    nmc_property_gsm_get_home_only,
+	                    nmc_property_set_bool,
+	                    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 (IP4_CONFIG, METHOD),
+	                    nmc_property_ipv4_get_method,
+	                    nmc_property_ipv4_set_method,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_ipv4_allowed_method,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (IP4_CONFIG, 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 (IP4_CONFIG, 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 (IP4_CONFIG, ADDRESSES),
+	                    nmc_property_ipv4_get_addresses,
+	                    nmc_property_ipv4_set_addresses,
+	                    nmc_property_ipv4_remove_addresses,
+	                    nmc_property_ipv4_describe_addresses,
+	                    NULL,
+	                    nmc_property_out2in_addresses);
+	nmc_add_prop_funcs (GLUE (IP4_CONFIG, ROUTES),
+	                    nmc_property_ipv4_get_routes,
+	                    nmc_property_ipv4_set_routes,
+	                    nmc_property_ipv4_remove_routes,
+	                    nmc_property_ipv4_describe_routes,
+	                    NULL,
+	                    nmc_property_out2in_routes);
+	nmc_add_prop_funcs (GLUE (IP4_CONFIG, IGNORE_AUTO_ROUTES),
+	                    nmc_property_ipv4_get_ignore_auto_routes,
+	                    nmc_property_set_bool,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (IP4_CONFIG, 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 (IP4_CONFIG, DHCP_SEND_HOSTNAME),
+	                    nmc_property_ipv4_get_dhcp_send_hostname,
+	                    nmc_property_set_bool,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (IP4_CONFIG, DHCP_HOSTNAME),
+	                    nmc_property_ipv4_get_dhcp_hostname,
+	                    nmc_property_set_string,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (IP4_CONFIG, NEVER_DEFAULT),
+	                    nmc_property_ipv4_get_never_default,
+	                    nmc_property_set_bool,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (IP4_CONFIG, MAY_FAIL),
+	                    nmc_property_ipv4_get_may_fail,
+	                    nmc_property_set_bool,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+
+	/* Add editable properties for NM_SETTING_IP6_CONFIG_SETTING_NAME */
+	nmc_add_prop_funcs (GLUE (IP6_CONFIG, METHOD),
+	                    nmc_property_ipv6_get_method,
+	                    nmc_property_ipv6_set_method,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_ipv6_allowed_method,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (IP6_CONFIG, 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 (IP6_CONFIG, 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 (IP6_CONFIG, ADDRESSES),
+	                    nmc_property_ipv6_get_addresses,
+	                    nmc_property_ipv6_set_addresses,
+	                    nmc_property_ipv6_remove_addresses,
+	                    nmc_property_ipv6_describe_addresses,
+	                    NULL,
+	                    nmc_property_out2in_addresses);
+	nmc_add_prop_funcs (GLUE (IP6_CONFIG, ROUTES),
+	                    nmc_property_ipv6_get_routes,
+	                    nmc_property_ipv6_set_routes,
+	                    nmc_property_ipv6_remove_routes,
+	                    nmc_property_ipv6_describe_routes,
+	                    NULL,
+	                    nmc_property_out2in_routes);
+	nmc_add_prop_funcs (GLUE (IP6_CONFIG, IGNORE_AUTO_ROUTES),
+	                    nmc_property_ipv6_get_ignore_auto_routes,
+	                    nmc_property_set_bool,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (IP6_CONFIG, IGNORE_AUTO_DNS),
+	                    nmc_property_ipv6_get_ignore_auto_dns,
+	                    nmc_property_set_bool,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (IP6_CONFIG, NEVER_DEFAULT),
+	                    nmc_property_ipv6_get_never_default,
+	                    nmc_property_set_bool,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (IP6_CONFIG, 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,
+	                    nmc_property_out2in_cut_paren);
+	nmc_add_prop_funcs (GLUE (IP6_CONFIG, DHCP_HOSTNAME),
+	                    nmc_property_ipv6_get_dhcp_hostname,
+	                    nmc_property_set_string,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+
+	/* 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);
+
+	/* 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);
+
+	/* 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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+
+	/* 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);
+
+	/* Add editable properties for NM_SETTING_TEAM_SETTING_NAME */
+	nmc_add_prop_funcs (GLUE (TEAM, INTERFACE_NAME),
+	                    nmc_property_team_get_interface_name,
+	                    nmc_property_set_ifname,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	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);
+
+	/* 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);
+
+	/* Add editable properties for NM_SETTING_VLAN_SETTING_NAME */
+	nmc_add_prop_funcs (GLUE (VLAN, INTERFACE_NAME),
+	                    nmc_property_vlan_get_interface_name,
+	                    nmc_property_set_ifname,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	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_uint,
+	                    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_string,
+	                    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);
+
+	/* 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);
+
+	/* 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,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL);
+	nmc_add_prop_funcs (GLUE (WIRED, DUPLEX),
+	                    nmc_property_wired_get_duplex,
+	                    NULL, /*nmc_property_wired_set_duplex,*/
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL); /*nmc_property_wired_allowed_duplex);*/
+	nmc_add_prop_funcs (GLUE (WIRED, AUTO_NEGOTIATE),
+	                    nmc_property_wired_get_auto_negotiate,
+	                    NULL,
+	                    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,
+	                    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);
+
+	/* 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,
+	                    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);
+
+	/* 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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+	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_flags,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    nmc_property_out2in_cut_paren);
+}
+
+void
+nmc_properties_cleanup ()
+{
+	if (nmc_properties)
+		g_hash_table_destroy (nmc_properties);
+}
+
+static const NmcPropertyFuncs *
+nmc_properties_find (const char *s_name, const char *p_name)
+{
+	NmcPropertyFuncs *item = NULL;
+	char *key;
+
+	/* FIXME: maybe it's better to init it globally */
+	nmc_properties_init ();
+
+	key = g_strdup_printf ("%s%s", s_name, p_name);
+	item = (NmcPropertyFuncs *) g_hash_table_lookup (nmc_properties, key);
+	g_free (key);
+
+	return item;
+}
+
+static char *
+get_property_val (NMSetting *setting, const char *prop, gboolean convert, GError **error)
+{
+	const NmcPropertyFuncs *item;
+
+	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->get_func) {
+		char *prop_val = item->get_func (setting);
+		if (convert && item->out2in_func) {
+			char *converted = item->out2in_func (prop_val);
+			g_free (prop_val);
+			return converted;
+		} else
+			return prop_val;
+	}
+
+	g_set_error_literal (error, 1, 0, _("don't know how to get the property value"));
+	return NULL;
+}
+
+/*
+ * Generic function for getting property value.
+ *
+ * Gets property value as a string by calling specialized functions.
+ *
+ * Returns: current property value. The caller must free the returned string.
+ */
+char *
+nmc_setting_get_property (NMSetting *setting, const char *prop, GError **error)
+{
+	return get_property_val (setting, prop, FALSE, error);
+}
+
+/*
+ * The same as nmc_setting_get_property(), but in addition converts
+ * usual output format into a simpler one, used as input in the editor.
+ */
+char *
+nmc_setting_get_property_out2in (NMSetting *setting, const char *prop, GError **error)
+{
+	return get_property_val (setting, prop, TRUE, 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.
+ *
+ * Returns: TRUE on success; FALSE on failure and sets error
+ */
 gboolean
-setting_infiniband_details (NMSettingInfiniband *s_infiniband, NmCli *nmc)
+nmc_setting_set_property (NMSetting *setting, const char *prop, const char *val, GError **error)
 {
-	const GByteArray *mac;
-	char *mtu_str, *mac_str = NULL;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	const NmcPropertyFuncs *item;
 
-	g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (s_infiniband), FALSE);
+	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) {
+			/* No value argument sets default value */
+			nmc_property_set_default_value (setting, prop);
+			return TRUE;
+		}
+		return item->set_func (setting, prop, val, error);
+	}
 
-	nmc->allowed_fields = nmc_fields_setting_infiniband;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_INFINIBAND_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	g_set_error_literal (error, 1, 0, _("the property can't be changed"));
+	return FALSE;
+}
 
-	mac = nm_setting_infiniband_get_mac_address (s_infiniband);
-	if (mac)
-		mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_INFINIBAND);
-	mtu_str = g_strdup_printf ("%d", nm_setting_infiniband_get_mtu (s_infiniband));
+void
+nmc_property_set_default_value (NMSetting *setting, const char *prop)
+{
+	GValue value = G_VALUE_INIT;
+	GParamSpec *param_spec;
+
+	param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), prop);
+	if (param_spec) {
+		g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (param_spec));
+		g_param_value_set_default (param_spec, &value);
+		g_object_set_property (G_OBJECT (setting), prop, &value);
+	}
+}
+
+/*
+ * Generic function for reseting (single value) properties.
+ *
+ * The function resets the property value to the default one. It respects
+ * nmcli restrictions for changing properties. So if 'set_func' is NULL,
+ * reseting the value is denied.
+ *
+ * Returns: TRUE on success; FALSE on failure and sets error
+ */
+gboolean
+nmc_setting_reset_property (NMSetting *setting, const char *prop, GError **error)
+{
+	const NmcPropertyFuncs *item;
 
-	nmc->allowed_fields[0].value = NM_SETTING_INFINIBAND_SETTING_NAME;
-	nmc->allowed_fields[1].value = mac_str;
-	nmc->allowed_fields[2].value = strcmp (mtu_str, "0") ? mtu_str : _("auto");
-	nmc->allowed_fields[3].value = nm_setting_infiniband_get_transport_mode (s_infiniband);
+	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;
+	}
+	g_set_error_literal (error, 1, 0, _("the property can't be changed"));
+	return FALSE;
+}
+
+/*
+ * Generic function for removing items for collection-type properties.
+ *
+ * If 'option' is not NULL, it tries to remove it, otherwise 'idx' is used.
+ * For single-value properties (not having specialized remove function) this
+ * function does nothing and just returns TRUE.
+ *
+ * Returns: TRUE on success; FALSE on failure and sets error
+ */
+gboolean
+nmc_setting_remove_property_option (NMSetting *setting,
+                                    const char *prop,
+                                    const char *option,
+                                    guint32 idx,
+                                    GError **error)
+{
+	const NmcPropertyFuncs *item;
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-	g_free (mac_str);
-	g_free (mtu_str);
+	item = nmc_properties_find (nm_setting_get_name (setting), prop);
+	if (item && item->remove_func)
+		return item->remove_func (setting, prop, option, idx, error);
 
 	return TRUE;
 }
 
-gboolean
-setting_bond_details (NMSettingBond *s_bond, NmCli *nmc)
+/*
+ * Get valid property names for a setting.
+ *
+ * Returns: string array with the properties or NULL on failure.
+ *          The returned value should be freed with g_strfreev()
+ */
+char **
+nmc_setting_get_valid_properties (NMSetting *setting)
 {
-	GString *bond_options_s;
+	char **valid_props = NULL;
+	GParamSpec **props, **iter;
+	guint num;
 	int i;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
 
-	g_return_val_if_fail (NM_IS_SETTING_BOND (s_bond), FALSE);
+	/* Iterate through properties */
+	i = 0;
+	props = g_object_class_list_properties (G_OBJECT_GET_CLASS (G_OBJECT (setting)), &num);
+	valid_props = g_malloc0 (sizeof (char*) * (num + 1));
+	for (iter = props; iter && *iter; iter++) {
+		const char *key_name = g_param_spec_get_name (*iter);
 
-	nmc->allowed_fields = nmc_fields_setting_bond;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_BOND_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+		/* Add all properties except for "name" that is non-editable */
+		if (g_strcmp0 (key_name, "name") != 0)
+			valid_props[i++] = g_strdup (key_name);
+	}
+	valid_props[i] = NULL;
 
-	bond_options_s = g_string_new (NULL);
-	for (i = 0; i < nm_setting_bond_get_num_options (s_bond); i++) {
-		const char *key, *value;
+	return valid_props;
+}
 
-		nm_setting_bond_get_option (s_bond, i, &key, &value);
-		g_string_append_printf (bond_options_s, "%s=%s,", key, value);
+/*
+ * Return allowed values for 'prop' as a string.
+ */
+const char *
+nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop)
+{
+
+	const NmcPropertyFuncs *item;
+
+	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+
+	item = nmc_properties_find (nm_setting_get_name (setting), prop);
+	if (item && item->values_func)
+		return item->values_func (setting, prop);
+
+	return NULL;
+}
+
+/*
+ * Create a description string for a property.
+ *
+ * It returns a description got from properties blurb, concatenated with
+ * nmcli specific description (if it exists).
+ *
+ * Returns: property description or NULL on failure. The caller must free the string.
+ */
+char *
+nmc_setting_get_property_desc (NMSetting *setting, const char *prop)
+{
+	GParamSpec *spec;
+	const NmcPropertyFuncs *item;
+	const char *setting_desc = "";
+	const char *setting_desc_title = "";
+	const char *nmcli_desc = NULL;
+	const char *nmcli_desc_title = "";
+	const char *nmcli_nl = "";
+
+	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+
+	spec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), prop);
+	if (spec) {
+		setting_desc = g_param_spec_get_blurb (spec);
+		setting_desc_title = _("[NM property description]");
 	}
-	g_string_truncate (bond_options_s, bond_options_s->len-1);  /* chop off trailing ',' */
 
-	nmc->allowed_fields[0].value = NM_SETTING_BOND_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_bond_get_interface_name (s_bond);
-	nmc->allowed_fields[2].value = bond_options_s->str;
+	item = nmc_properties_find (nm_setting_get_name (setting), prop);
+	if (item && item->describe_func) {
+		nmcli_desc = item->describe_func (setting, prop);
+		nmcli_desc_title = _("[nmcli specific description]");
+		nmcli_nl = "\n";
+	}
+
+	return g_strdup_printf ("%s\n%s\n%s%s%s%s",
+	                        setting_desc_title, setting_desc,
+	                        nmcli_nl, nmcli_desc_title, nmcli_nl,
+	                        nmcli_desc ? nmcli_desc : "");
+}
+
+/*
+ * Gets setting:prop property value and returns it in 'value'.
+ * Caller is responsible for freeing the GValue resources using g_value_unset()
+ */
+gboolean
+nmc_property_get_gvalue (NMSetting *setting, const char *prop, GValue *value)
+{
+	GParamSpec *param_spec;
+
+	param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), prop);
+	if (param_spec) {
+		memset (value, 0, sizeof (GValue));
+		g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (param_spec));
+		g_object_get_property (G_OBJECT (setting), prop, value);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/*
+ * Sets setting:prop property value from 'value'.
+ */
+gboolean
+nmc_property_set_gvalue (NMSetting *setting, const char *prop, GValue *value)
+{
+	GParamSpec *param_spec;
+
+	param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), prop);
+	if (param_spec && G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (param_spec)) {
+		g_object_set_property (G_OBJECT (setting), prop, value);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static gboolean
+setting_connection_details (NMSetting *setting, NmCli *nmc, const char *one_prop)
+{
+	NMSettingConnection *s_con = NM_SETTING_CONNECTION (setting);
+	NmcOutputField *tmpl, *arr;
+	size_t tmpl_len;
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (s_con), FALSE);
 
-	g_string_free (bond_options_s, TRUE);
+	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));
+	set_val_str (arr, 2, nmc_property_connection_get_uuid (setting));
+	set_val_str (arr, 3, nmc_property_connection_get_interface_name (setting));
+	set_val_str (arr, 4, nmc_property_connection_get_type (setting));
+	set_val_str (arr, 5, nmc_property_connection_get_autoconnect (setting));
+	set_val_str (arr, 6, nmc_property_connection_get_timestamp (setting));
+	set_val_str (arr, 7, nmc_property_connection_get_read_only (setting));
+	set_val_str (arr, 8, nmc_property_connection_get_permissions (setting));
+	set_val_str (arr, 9, nmc_property_connection_get_zone (setting));
+	set_val_str (arr, 10, nmc_property_connection_get_master (setting));
+	set_val_str (arr, 11, nmc_property_connection_get_slave_type (setting));
+	set_val_str (arr, 12, nmc_property_connection_get_secondaries (setting));
+	set_val_str (arr, 13, nmc_property_connection_get_gateway_ping_timeout (setting));
+	g_ptr_array_add (nmc->output_data, arr);
+
+	print_data (nmc);  /* Print all data */
 
 	return TRUE;
 }
 
-gboolean
-setting_vlan_details (NMSettingVlan *s_vlan, NmCli *nmc)
+static gboolean
+setting_wired_details (NMSetting *setting, NmCli *nmc, const char *one_prop)
 {
-	char *vlan_id_str, *vlan_flags_str, *vlan_ingress_prio_str, *vlan_egress_prio_str;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	NMSettingWired *s_wired = NM_SETTING_WIRED (setting);
+	NmcOutputField *tmpl, *arr;
+	size_t tmpl_len;
 
-	g_return_val_if_fail (NM_IS_SETTING_VLAN (s_vlan), FALSE);
+	g_return_val_if_fail (NM_IS_SETTING_WIRED (s_wired), FALSE);
 
-	nmc->allowed_fields = nmc_fields_setting_vlan;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_VLAN_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	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));
+	set_val_str (arr, 2, nmc_property_wired_get_speed (setting));
+	set_val_str (arr, 3, nmc_property_wired_get_duplex (setting));
+	set_val_str (arr, 4, nmc_property_wired_get_auto_negotiate (setting));
+	set_val_str (arr, 5, nmc_property_wired_get_mac_address (setting));
+	set_val_str (arr, 6, nmc_property_wired_get_cloned_mac_address (setting));
+	set_val_str (arr, 7, nmc_property_wired_get_mac_address_blacklist (setting));
+	set_val_str (arr, 8, nmc_property_wired_get_mtu (setting));
+	set_val_str (arr, 9, nmc_property_wired_get_s390_subchannels (setting));
+	set_val_str (arr, 10, nmc_property_wired_get_s390_nettype (setting));
+	set_val_str (arr, 11, nmc_property_wired_get_s390_options (setting));
+	g_ptr_array_add (nmc->output_data, arr);
+
+	print_data (nmc);  /* Print all data */
 
-	vlan_id_str = g_strdup_printf ("%d", nm_setting_vlan_get_id (s_vlan));
-	vlan_flags_str = vlan_flags_to_string (nm_setting_vlan_get_flags (s_vlan));
-	vlan_ingress_prio_str = vlan_priorities_to_string (s_vlan, NM_VLAN_INGRESS_MAP);
-	vlan_egress_prio_str = vlan_priorities_to_string (s_vlan, NM_VLAN_EGRESS_MAP);
+	return TRUE;
+}
 
-	nmc->allowed_fields[0].value = NM_SETTING_VLAN_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_vlan_get_interface_name (s_vlan);
-	nmc->allowed_fields[2].value = nm_setting_vlan_get_parent (s_vlan);
-	nmc->allowed_fields[3].value = vlan_id_str;
-	nmc->allowed_fields[4].value = vlan_flags_str;
-	nmc->allowed_fields[5].value = vlan_ingress_prio_str;
-	nmc->allowed_fields[6].value = vlan_egress_prio_str;
+static gboolean
+setting_802_1X_details (NMSetting *setting, NmCli *nmc, const char *one_prop)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_802_1X_get_identity (setting));
+	set_val_str (arr, 3, nmc_property_802_1X_get_anonymous_identity (setting));
+	set_val_str (arr, 4, nmc_property_802_1X_get_pac_file (setting));
+	set_val_str (arr, 5, nmc_property_802_1X_get_ca_cert (setting));
+	set_val_str (arr, 6, nmc_property_802_1X_get_ca_path (setting));
+	set_val_str (arr, 7, nmc_property_802_1X_get_subject_match (setting));
+	set_val_str (arr, 8, nmc_property_802_1X_get_altsubject_matches (setting));
+	set_val_str (arr, 9, nmc_property_802_1X_get_client_cert (setting));
+	set_val_str (arr, 10, nmc_property_802_1X_get_phase1_peapver (setting));
+	set_val_str (arr, 11, nmc_property_802_1X_get_phase1_peaplabel (setting));
+	set_val_str (arr, 12, nmc_property_802_1X_get_phase1_fast_provisioning (setting));
+	set_val_str (arr, 13, nmc_property_802_1X_get_phase2_auth (setting));
+	set_val_str (arr, 14, nmc_property_802_1X_get_phase2_autheap (setting));
+	set_val_str (arr, 15, nmc_property_802_1X_get_phase2_ca_cert (setting));
+	set_val_str (arr, 16, nmc_property_802_1X_get_phase2_ca_path (setting));
+	set_val_str (arr, 17, nmc_property_802_1X_get_phase2_subject_match (setting));
+	set_val_str (arr, 18, nmc_property_802_1X_get_phase2_altsubject_matches (setting));
+	set_val_str (arr, 19, nmc_property_802_1X_get_phase2_client_cert (setting));
+	set_val_str (arr, 20, nmc_property_802_1X_get_password (setting));
+	set_val_str (arr, 21, nmc_property_802_1X_get_password_flags (setting));
+	set_val_str (arr, 22, nmc_property_802_1X_get_password_raw (setting));
+	set_val_str (arr, 23, nmc_property_802_1X_get_password_raw_flags (setting));
+	set_val_str (arr, 24, nmc_property_802_1X_get_private_key (setting));
+	set_val_str (arr, 25, nmc_property_802_1X_get_private_key_password (setting));
+	set_val_str (arr, 26, nmc_property_802_1X_get_private_key_password_flags (setting));
+	set_val_str (arr, 27, nmc_property_802_1X_get_phase2_private_key (setting));
+	set_val_str (arr, 28, nmc_property_802_1X_get_phase2_private_key_password (setting));
+	set_val_str (arr, 29, nmc_property_802_1X_get_phase2_private_key_password_flags (setting));
+	set_val_str (arr, 30, nmc_property_802_1X_get_pin (setting));
+	set_val_str (arr, 31, nmc_property_802_1X_get_pin_flags (setting));
+	set_val_str (arr, 32, nmc_property_802_1X_get_system_ca_certs (setting));
+	g_ptr_array_add (nmc->output_data, arr);
+
+	print_data (nmc);  /* Print all data */
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	return TRUE;
+}
 
-	g_free (vlan_id_str);
-	g_free (vlan_flags_str);
-	g_free (vlan_ingress_prio_str);
-	g_free (vlan_egress_prio_str);
+static gboolean
+setting_wireless_details (NMSetting *setting, NmCli *nmc, const char *one_prop)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_wireless_get_mode (setting));
+	set_val_str (arr, 3, nmc_property_wireless_get_band (setting));
+	set_val_str (arr, 4, nmc_property_wireless_get_channel (setting));
+	set_val_str (arr, 5, nmc_property_wireless_get_bssid (setting));
+	set_val_str (arr, 6, nmc_property_wireless_get_rate (setting));
+	set_val_str (arr, 7, nmc_property_wireless_get_tx_power (setting));
+	set_val_str (arr, 8, nmc_property_wireless_get_mac_address (setting));
+	set_val_str (arr, 9, nmc_property_wireless_get_cloned_mac_address (setting));
+	set_val_str (arr, 10, nmc_property_wireless_get_mac_address_blacklist (setting));
+	set_val_str (arr, 11, nmc_property_wireless_get_mtu (setting));
+	set_val_str (arr, 12, nmc_property_wireless_get_seen_bssids (setting));
+	set_val_str (arr, 13, nmc_property_wireless_get_hidden (setting));
+	g_ptr_array_add (nmc->output_data, arr);
+
+	print_data (nmc);  /* Print all data */
 
 	return TRUE;
 }
 
-gboolean
-setting_adsl_details (NMSettingAdsl *s_adsl, NmCli *nmc)
+static gboolean
+setting_wireless_security_details (NMSetting *setting, NmCli *nmc, const char *one_prop)
 {
-	char *pswd_flags;
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting);
+	NmcOutputField *tmpl, *arr;
+	size_t tmpl_len;
 
-	g_return_val_if_fail (NM_IS_SETTING_ADSL (s_adsl), FALSE);
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (s_wireless_sec), FALSE);
 
-	nmc->allowed_fields = nmc_fields_setting_adsl;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_ADSL_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	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));
+	set_val_str (arr, 2, nmc_property_wifi_sec_get_wep_tx_keyidx (setting));
+	set_val_str (arr, 3, nmc_property_wifi_sec_get_auth_alg (setting));
+	set_val_str (arr, 4, nmc_property_wifi_sec_get_proto (setting));
+	set_val_str (arr, 5, nmc_property_wifi_sec_get_pairwise (setting));
+	set_val_str (arr, 6, nmc_property_wifi_sec_get_group (setting));
+	set_val_str (arr, 7, nmc_property_wifi_sec_get_leap_username (setting));
+	set_val_str (arr, 8, nmc_property_wifi_sec_get_wep_key0 (setting));
+	set_val_str (arr, 9, nmc_property_wifi_sec_get_wep_key1 (setting));
+	set_val_str (arr, 10, nmc_property_wifi_sec_get_wep_key2 (setting));
+	set_val_str (arr, 11, nmc_property_wifi_sec_get_wep_key3 (setting));
+	set_val_str (arr, 12, nmc_property_wifi_sec_get_wep_key_flags (setting));
+	set_val_str (arr, 13, nmc_property_wifi_sec_get_wep_key_type (setting));
+	set_val_str (arr, 14, nmc_property_wifi_sec_get_psk (setting));
+	set_val_str (arr, 15, nmc_property_wifi_sec_get_psk_flags (setting));
+	set_val_str (arr, 16, nmc_property_wifi_sec_get_leap_password (setting));
+	set_val_str (arr, 17, nmc_property_wifi_sec_get_leap_password_flags (setting));
+	g_ptr_array_add (nmc->output_data, arr);
+
+	print_data (nmc);  /* Print all data */
 
-	pswd_flags = secret_flags_to_string (nm_setting_adsl_get_password_flags (s_adsl));
+	return TRUE;
+}
 
-	nmc->allowed_fields[0].value = NM_SETTING_ADSL_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_adsl_get_username (s_adsl);
-	nmc->allowed_fields[2].value = nm_setting_adsl_get_password (s_adsl);
-	nmc->allowed_fields[3].value = pswd_flags;
-	nmc->allowed_fields[4].value = nm_setting_adsl_get_protocol (s_adsl);
-	nmc->allowed_fields[5].value = nm_setting_adsl_get_encapsulation (s_adsl);
-	nmc->allowed_fields[6].value = g_strdup_printf ("%d", nm_setting_adsl_get_vpi (s_adsl));
-	nmc->allowed_fields[7].value = g_strdup_printf ("%d", nm_setting_adsl_get_vci (s_adsl));
+static gboolean
+setting_ip4_config_details (NMSetting *setting, NmCli *nmc, const char *one_prop)
+{
+	NMSettingIP4Config *s_ip4 = NM_SETTING_IP4_CONFIG (setting);
+	NmcOutputField *tmpl, *arr;
+	size_t tmpl_len;
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (s_ip4), FALSE);
 
-	g_free (pswd_flags);
-	g_free ((char*) nmc->allowed_fields[6].value);
-	g_free ((char*) nmc->allowed_fields[7].value);
+	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));
+	set_val_str (arr, 2, nmc_property_ipv4_get_dns (setting));
+	set_val_str (arr, 3, nmc_property_ipv4_get_dns_search (setting));
+	set_val_str (arr, 4, nmc_property_ipv4_get_addresses (setting));
+	set_val_str (arr, 5, nmc_property_ipv4_get_routes (setting));
+	set_val_str (arr, 6, nmc_property_ipv4_get_ignore_auto_routes (setting));
+	set_val_str (arr, 7, nmc_property_ipv4_get_ignore_auto_dns (setting));
+	set_val_str (arr, 8, nmc_property_ipv4_get_dhcp_client_id (setting));
+	set_val_str (arr, 9, nmc_property_ipv4_get_dhcp_send_hostname (setting));
+	set_val_str (arr, 10, nmc_property_ipv4_get_dhcp_hostname (setting));
+	set_val_str (arr, 11, nmc_property_ipv4_get_never_default (setting));
+	set_val_str (arr, 12, nmc_property_ipv4_get_may_fail (setting));
+	g_ptr_array_add (nmc->output_data, arr);
+
+	print_data (nmc);  /* Print all data */
 
 	return TRUE;
 }
 
-gboolean
-setting_bridge_details (NMSettingBridge *s_bridge, NmCli *nmc)
+static gboolean
+setting_ip6_config_details (NMSetting *setting, NmCli *nmc, const char *one_prop)
 {
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG (setting);
+	NmcOutputField *tmpl, *arr;
+	size_t tmpl_len;
 
-	g_return_val_if_fail (NM_IS_SETTING_BRIDGE (s_bridge), FALSE);
+	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));
+	set_val_str (arr, 2, nmc_property_ipv6_get_dns (setting));
+	set_val_str (arr, 3, nmc_property_ipv6_get_dns_search (setting));
+	set_val_str (arr, 4, nmc_property_ipv6_get_addresses (setting));
+	set_val_str (arr, 5, nmc_property_ipv6_get_routes (setting));
+	set_val_str (arr, 6, nmc_property_ipv6_get_ignore_auto_routes (setting));
+	set_val_str (arr, 7, nmc_property_ipv6_get_ignore_auto_dns (setting));
+	set_val_str (arr, 8, nmc_property_ipv6_get_never_default (setting));
+	set_val_str (arr, 9, nmc_property_ipv6_get_may_fail (setting));
+	set_val_str (arr, 10, nmc_property_ipv6_get_ip6_privacy (setting));
+	set_val_str (arr, 11, nmc_property_ipv6_get_dhcp_hostname (setting));
+	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)
+{
+	NMSettingSerial *s_serial = NM_SETTING_SERIAL (setting);
+	NmcOutputField *tmpl, *arr;
+	size_t tmpl_len;
 
-	nmc->allowed_fields = nmc_fields_setting_bridge;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_BRIDGE_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	g_return_val_if_fail (NM_IS_SETTING_SERIAL (s_serial), FALSE);
 
-	nmc->allowed_fields[0].value = NM_SETTING_BRIDGE_SETTING_NAME;
-	nmc->allowed_fields[1].value = nm_setting_bridge_get_interface_name (s_bridge);
-	nmc->allowed_fields[2].value = nm_setting_bridge_get_stp (s_bridge) ? _("yes") : _("no");
-	nmc->allowed_fields[3].value = g_strdup_printf ("%u", nm_setting_bridge_get_priority (s_bridge));
-	nmc->allowed_fields[4].value = g_strdup_printf ("%u", nm_setting_bridge_get_forward_delay (s_bridge));
-	nmc->allowed_fields[5].value = g_strdup_printf ("%u", nm_setting_bridge_get_hello_time (s_bridge));
-	nmc->allowed_fields[6].value = g_strdup_printf ("%u", nm_setting_bridge_get_max_age (s_bridge));
-	nmc->allowed_fields[7].value = g_strdup_printf ("%u", nm_setting_bridge_get_ageing_time (s_bridge));
+	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);
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	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));
+	set_val_str (arr, 2, nmc_property_serial_get_bits (setting));
+	set_val_str (arr, 3, nmc_property_serial_get_parity (setting));
+	set_val_str (arr, 4, nmc_property_serial_get_stopbits (setting));
+	set_val_str (arr, 5, nmc_property_serial_get_send_delay (setting));
+	g_ptr_array_add (nmc->output_data, arr);
 
-	/* free values */
-	g_free ((char*) nmc->allowed_fields[3].value);
-	g_free ((char*) nmc->allowed_fields[4].value);
-	g_free ((char*) nmc->allowed_fields[5].value);
-	g_free ((char*) nmc->allowed_fields[6].value);
-	g_free ((char*) nmc->allowed_fields[7].value);
+	print_data (nmc);  /* Print all data */
 
 	return TRUE;
 }
 
-gboolean
-setting_bridge_port_details (NMSettingBridgePort *s_bridge_port, NmCli *nmc)
+static gboolean
+setting_ppp_details (NMSetting *setting, NmCli *nmc, const char *one_prop)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_ppp_get_refuse_eap (setting));
+	set_val_str (arr, 3, nmc_property_ppp_get_refuse_pap (setting));
+	set_val_str (arr, 4, nmc_property_ppp_get_refuse_chap (setting));
+	set_val_str (arr, 5, nmc_property_ppp_get_refuse_mschap (setting));
+	set_val_str (arr, 6, nmc_property_ppp_get_refuse_mschapv2 (setting));
+	set_val_str (arr, 7, nmc_property_ppp_get_nobsdcomp (setting));
+	set_val_str (arr, 8, nmc_property_ppp_get_nodeflate (setting));
+	set_val_str (arr, 9, nmc_property_ppp_get_no_vj_comp (setting));
+	set_val_str (arr, 10, nmc_property_ppp_get_require_mppe (setting));
+	set_val_str (arr, 11, nmc_property_ppp_get_require_mppe_128 (setting));
+	set_val_str (arr, 12, nmc_property_ppp_get_mppe_stateful (setting));
+	set_val_str (arr, 13, nmc_property_ppp_get_crtscts (setting));
+	set_val_str (arr, 14, nmc_property_ppp_get_baud (setting));
+	set_val_str (arr, 15, nmc_property_ppp_get_mru (setting));
+	set_val_str (arr, 16, nmc_property_ppp_get_mtu (setting));
+	set_val_str (arr, 17, nmc_property_ppp_get_lcp_echo_failure (setting));
+	set_val_str (arr, 18, nmc_property_ppp_get_lcp_echo_interval (setting));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_pppoe_get_username (setting));
+	set_val_str (arr, 3, nmc_property_pppoe_get_password (setting));
+	set_val_str (arr, 4, nmc_property_pppoe_get_password_flags (setting));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_gsm_get_username (setting));
+	set_val_str (arr, 3, nmc_property_gsm_get_password (setting));
+	set_val_str (arr, 4, nmc_property_gsm_get_password_flags (setting));
+	set_val_str (arr, 5, nmc_property_gsm_get_apn (setting));
+	set_val_str (arr, 6, nmc_property_gsm_get_network_id (setting));
+	set_val_str (arr, 7, nmc_property_gsm_get_network_type (setting));
+	set_val_str (arr, 8, nmc_property_gsm_get_allowed_bands (setting));
+	set_val_str (arr, 9, nmc_property_gsm_get_pin (setting));
+	set_val_str (arr, 10, nmc_property_gsm_get_pin_flags (setting));
+	set_val_str (arr, 11, nmc_property_gsm_get_home_only (setting));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_cdma_get_username (setting));
+	set_val_str (arr, 3, nmc_property_cdma_get_password (setting));
+	set_val_str (arr, 4, nmc_property_cdma_get_password_flags (setting));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_bluetooth_get_type (setting));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_olpc_get_channel (setting));
+	set_val_str (arr, 3, nmc_property_olpc_get_anycast_address (setting));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_vpn_get_user_name (setting));
+	set_val_str (arr, 3, nmc_property_vpn_get_data (setting));
+	set_val_str (arr, 4, nmc_property_vpn_get_secrets (setting));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_wimax_get_network_name (setting));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_ib_get_mtu (setting));
+	set_val_str (arr, 3, nmc_property_ib_get_transport_mode (setting));
+	set_val_str (arr, 4, nmc_property_ib_get_p_key (setting));
+	set_val_str (arr, 5, nmc_property_ib_get_parent (setting));
+	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)
+{
+	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_interface_name (setting));
+	set_val_str (arr, 2, nmc_property_bond_get_options (setting));
+	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)
+{
+	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_interface_name (setting));
+	set_val_str (arr, 2, nmc_property_vlan_get_parent (setting));
+	set_val_str (arr, 3, nmc_property_vlan_get_id (setting));
+	set_val_str (arr, 4, nmc_property_vlan_get_flags (setting));
+	set_val_str (arr, 5, nmc_property_vlan_get_ingress_priority_map (setting));
+	set_val_str (arr, 6, nmc_property_vlan_get_egress_priority_map (setting));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_adsl_get_password (setting));
+	set_val_str (arr, 3, nmc_property_adsl_get_password_flags (setting));
+	set_val_str (arr, 4, nmc_property_adsl_get_protocol (setting));
+	set_val_str (arr, 5, nmc_property_adsl_get_encapsulation (setting));
+	set_val_str (arr, 6, nmc_property_adsl_get_vpi (setting));
+	set_val_str (arr, 7, nmc_property_adsl_get_vci (setting));
+	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)
+{
+	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_interface_name (setting));
+	set_val_str (arr, 2, nmc_property_bridge_get_mac_address (setting));
+	set_val_str (arr, 3, nmc_property_bridge_get_stp (setting));
+	set_val_str (arr, 4, nmc_property_bridge_get_priority (setting));
+	set_val_str (arr, 5, nmc_property_bridge_get_forward_delay (setting));
+	set_val_str (arr, 6, nmc_property_bridge_get_hello_time (setting));
+	set_val_str (arr, 7, nmc_property_bridge_get_max_age (setting));
+	set_val_str (arr, 8, nmc_property_bridge_get_ageing_time (setting));
+	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)
 {
-	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
-	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
-	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
+	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);
 
-	nmc->allowed_fields = nmc_fields_setting_bridge_port;
-	nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_BRIDGE_PORT_ALL, nmc->allowed_fields, NULL);
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES;
-	print_fields (nmc->print_fields, nmc->allowed_fields);  /* Print field names */
+	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));
+	set_val_str (arr, 2, nmc_property_bridge_port_get_path_cost (setting));
+	set_val_str (arr, 3, nmc_property_bridge_port_get_hairpin_mode (setting));
+	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)
+{
+	NMSettingTeam *s_team = NM_SETTING_TEAM (setting);
+	NmcOutputField *tmpl, *arr;
+	size_t tmpl_len;
 
-	nmc->allowed_fields[0].value = NM_SETTING_BRIDGE_PORT_SETTING_NAME;
-	nmc->allowed_fields[1].value = g_strdup_printf ("%u", nm_setting_bridge_port_get_priority (s_bridge_port));
-	nmc->allowed_fields[2].value = g_strdup_printf ("%u", nm_setting_bridge_port_get_path_cost (s_bridge_port));
-	nmc->allowed_fields[3].value = nm_setting_bridge_port_get_hairpin_mode (s_bridge_port) ? _("yes") : _("no");
+	g_return_val_if_fail (NM_IS_SETTING_TEAM (s_team), FALSE);
 
-	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
-	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
+	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);
 
-	g_free ((char*) nmc->allowed_fields[1].value);
-	g_free ((char*) nmc->allowed_fields[2].value);
+	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_interface_name (setting));
+	set_val_str (arr, 2, nmc_property_team_get_config (setting));
+	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)
+{
+	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));
+	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)
+{
+	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));
+	set_val_str (arr, 2, nmc_property_dcb_get_app_fcoe_priority (setting));
+	set_val_str (arr, 3, nmc_property_dcb_get_app_fcoe_mode (setting));
+	set_val_str (arr, 4, nmc_property_dcb_get_app_iscsi_flags (setting));
+	set_val_str (arr, 5, nmc_property_dcb_get_app_iscsi_priority (setting));
+	set_val_str (arr, 6, nmc_property_dcb_get_app_fip_flags (setting));
+	set_val_str (arr, 7, nmc_property_dcb_get_app_fip_priority (setting));
+	set_val_str (arr, 8, nmc_property_dcb_get_pfc_flags (setting));
+	set_val_str (arr, 9, nmc_property_dcb_get_pfc (setting));
+	set_val_str (arr, 10, nmc_property_dcb_get_pg_flags (setting));
+	set_val_str (arr, 11, nmc_property_dcb_get_pg_group_id (setting));
+	set_val_str (arr, 12, nmc_property_dcb_get_pg_group_bandwidth (setting));
+	set_val_str (arr, 13, nmc_property_dcb_get_pg_bandwidth (setting));
+	set_val_str (arr, 14, nmc_property_dcb_get_pg_strict (setting));
+	set_val_str (arr, 15, nmc_property_dcb_get_pg_traffic_class (setting));
+	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);
+} 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 },
+	{ NULL },
+};
+
+gboolean
+setting_details (NMSetting *setting, NmCli *nmc, const char *one_prop)
+{
+	const SettingDetails *iter = &detail_printers[0];
+
+	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+
+	while (iter->sname) {
+		if (nm_connection_lookup_setting_type (iter->sname) == G_OBJECT_TYPE (setting))
+			return iter->func (setting, nmc, one_prop);
+		iter++;
+	}
+
+	g_assert_not_reached ();
+	return FALSE;
+}
+