about summary refs log tree commit diff
path: root/clients/cli/devices.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/cli/devices.c')
-rw-r--r--clients/cli/devices.c1004
1 files changed, 596 insertions, 408 deletions
diff --git a/clients/cli/devices.c b/clients/cli/devices.c
index aa28678f..ca575c33 100644
--- a/clients/cli/devices.c
+++ b/clients/cli/devices.c
@@ -39,99 +39,518 @@
 #define PROMPT_INTERFACE  _("Interface: ")
 #define PROMPT_INTERFACES _("Interface(s): ")
 
-const NmcMetaGenericInfo *const nmc_fields_dev_status[] = {
-	NMC_META_GENERIC ("DEVICE"),       /* 0 */
-	NMC_META_GENERIC ("TYPE"),         /* 1 */
-	NMC_META_GENERIC ("STATE"),        /* 2 */
-	NMC_META_GENERIC ("DBUS-PATH"),    /* 3 */
-	NMC_META_GENERIC ("CONNECTION"),   /* 4 */
-	NMC_META_GENERIC ("CON-UUID"),     /* 5 */
-	NMC_META_GENERIC ("CON-PATH"),     /* 6 */
-	NULL,
+/*****************************************************************************/
+
+static char *
+ap_wpa_rsn_flags_to_string (NM80211ApSecurityFlags flags)
+{
+	char *flags_str[16]; /* Enough space for flags and terminating NULL */
+	char *ret_str;
+	int i = 0;
+
+	if (flags & NM_802_11_AP_SEC_PAIR_WEP40)
+		flags_str[i++] = g_strdup ("pair_wpe40");
+	if (flags & NM_802_11_AP_SEC_PAIR_WEP104)
+		flags_str[i++] = g_strdup ("pair_wpe104");
+	if (flags & NM_802_11_AP_SEC_PAIR_TKIP)
+		flags_str[i++] = g_strdup ("pair_tkip");
+	if (flags & NM_802_11_AP_SEC_PAIR_CCMP)
+		flags_str[i++] = g_strdup ("pair_ccmp");
+	if (flags & NM_802_11_AP_SEC_GROUP_WEP40)
+		flags_str[i++] = g_strdup ("group_wpe40");
+	if (flags & NM_802_11_AP_SEC_GROUP_WEP104)
+		flags_str[i++] = g_strdup ("group_wpe104");
+	if (flags & NM_802_11_AP_SEC_GROUP_TKIP)
+		flags_str[i++] = g_strdup ("group_tkip");
+	if (flags & NM_802_11_AP_SEC_GROUP_CCMP)
+		flags_str[i++] = g_strdup ("group_ccmp");
+	if (flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
+		flags_str[i++] = g_strdup ("psk");
+	if (flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
+		flags_str[i++] = g_strdup ("802.1X");
+
+	if (i == 0)
+		flags_str[i++] = g_strdup (_("(none)"));
+
+	flags_str[i] = NULL;
+
+	ret_str = g_strjoinv (" ", flags_str);
+
+	i = 0;
+	while (flags_str[i])
+		g_free (flags_str[i++]);
+
+	return ret_str;
+}
+
+static NMMetaColor
+wifi_signal_to_color (guint8 strength)
+{
+	if (strength > 80)
+		return NM_META_COLOR_WIFI_SIGNAL_EXCELLENT;
+	else if (strength > 55)
+		return NM_META_COLOR_WIFI_SIGNAL_GOOD;
+	else if (strength > 30)
+		return NM_META_COLOR_WIFI_SIGNAL_FAIR;
+	else if (strength > 5)
+		return NM_META_COLOR_WIFI_SIGNAL_POOR;
+	else
+		return NM_META_COLOR_WIFI_SIGNAL_UNKNOWN;
+}
+
+/*****************************************************************************/
+
+static gconstpointer
+_metagen_device_status_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
+{
+	NMDevice *d = target;
+	NMActiveConnection *ac;
+
+	NMC_HANDLE_COLOR (nmc_device_state_to_color (nm_device_get_state (d)));
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DEVICE:
+		return nm_device_get_iface (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_TYPE:
+		return nm_device_get_type_description (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_STATE:
+		return nmc_meta_generic_get_str_i18n (nmc_device_state_to_string (nm_device_get_state (d)),
+		                                      get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DBUS_PATH:
+		return nm_object_get_path (NM_OBJECT (d));
+	case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CONNECTION:
+		ac = nm_device_get_active_connection (d);
+		return ac ? nm_active_connection_get_id (ac) : NULL;
+	case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_UUID:
+		ac = nm_device_get_active_connection (d);
+		return ac ? nm_active_connection_get_uuid (ac) : NULL;
+	case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_PATH:
+		ac = nm_device_get_active_connection (d);
+		return ac ? nm_object_get_path (NM_OBJECT (ac)) : NULL;
+	default:
+		break;
+	}
+
+	g_return_val_if_reached (NULL);
+}
+
+const NmcMetaGenericInfo *const metagen_device_status[_NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_NUM + 1] = {
+#define _METAGEN_DEVICE_STATUS(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_status_get_fcn)
+	_METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DEVICE,     "DEVICE"),
+	_METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_TYPE,       "TYPE"),
+	_METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_STATE,      "STATE"),
+	_METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DBUS_PATH,  "DBUS-PATH"),
+	_METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CONNECTION, "CONNECTION"),
+	_METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_UUID,   "CON-UUID"),
+	_METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_PATH,   "CON-PATH"),
 };
-#define NMC_FIELDS_DEV_STATUS_COMMON  "DEVICE,TYPE,STATE,CONNECTION"
-
-const NmcMetaGenericInfo *const nmc_fields_dev_show_general[] = {
-	NMC_META_GENERIC ("NAME"),                /* 0 */
-	NMC_META_GENERIC ("DEVICE"),              /* 1 */
-	NMC_META_GENERIC ("TYPE"),                /* 2 */
-	NMC_META_GENERIC ("NM-TYPE"),             /* 3 */
-	NMC_META_GENERIC ("VENDOR"),              /* 4 */
-	NMC_META_GENERIC ("PRODUCT"),             /* 5 */
-	NMC_META_GENERIC ("DRIVER"),              /* 6 */
-	NMC_META_GENERIC ("DRIVER-VERSION"),      /* 7 */
-	NMC_META_GENERIC ("FIRMWARE-VERSION"),    /* 8 */
-	NMC_META_GENERIC ("HWADDR"),              /* 9 */
-	NMC_META_GENERIC ("MTU"),                 /* 10 */
-	NMC_META_GENERIC ("STATE"),               /* 11 */
-	NMC_META_GENERIC ("REASON"),              /* 12 */
-	NMC_META_GENERIC ("UDI"),                 /* 13 */
-	NMC_META_GENERIC ("IP-IFACE"),            /* 14 */
-	NMC_META_GENERIC ("IS-SOFTWARE"),         /* 15 */
-	NMC_META_GENERIC ("NM-MANAGED"),          /* 16 */
-	NMC_META_GENERIC ("AUTOCONNECT"),         /* 17 */
-	NMC_META_GENERIC ("FIRMWARE-MISSING"),    /* 18 */
-	NMC_META_GENERIC ("NM-PLUGIN-MISSING"),   /* 19 */
-	NMC_META_GENERIC ("PHYS-PORT-ID"),        /* 20 */
-	NMC_META_GENERIC ("CONNECTION"),          /* 21 */
-	NMC_META_GENERIC ("CON-UUID"),            /* 22 */
-	NMC_META_GENERIC ("CON-PATH"),            /* 23 */
-	NMC_META_GENERIC ("METERED"),             /* 24 */
-	NULL,
+
+/*****************************************************************************/
+
+static gconstpointer
+_metagen_device_detail_general_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
+{
+	NMDevice *d = target;
+	NMActiveConnection *ac;
+	NMDeviceState state;
+	NMDeviceStateReason state_reason;
+	const char *s;
+
+	NMC_HANDLE_COLOR (NM_META_COLOR_NONE);
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE:
+		return nm_device_get_iface (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE:
+		return nm_device_get_type_description (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE:
+		return G_OBJECT_TYPE_NAME (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR:
+		return nm_device_get_vendor (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT:
+		return nm_device_get_product (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER:
+		s = nm_device_get_driver (d);
+		return s ?: nmc_meta_generic_get_str_i18n (N_("(unknown)"), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION:
+		return nm_device_get_driver_version (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION:
+		return nm_device_get_firmware_version (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR:
+		s = nm_device_get_hw_address (d);
+		return s ?: nmc_meta_generic_get_str_i18n (N_("(unknown)"), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU:
+		return (*out_to_free = g_strdup_printf ("%u", (guint) nm_device_get_mtu (d)));
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE:
+		state = nm_device_get_state (d);
+		return (*out_to_free = nmc_meta_generic_get_enum_with_detail (NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES,
+		                                                              state,
+		                                                              nmc_device_state_to_string (state),
+		                                                              get_type));
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_REASON:
+		state_reason = nm_device_get_state_reason (d);
+		return (*out_to_free = nmc_meta_generic_get_enum_with_detail (NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES,
+		                                                              state_reason,
+		                                                              nmc_device_reason_to_string (state_reason),
+		                                                              get_type));
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_UDI:
+		return nm_device_get_udi (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP_IFACE:
+		return nm_device_get_ip_iface (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IS_SOFTWARE:
+		return nmc_meta_generic_get_bool (nm_device_is_software (d), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_MANAGED:
+		return nmc_meta_generic_get_bool (nm_device_get_managed (d), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_AUTOCONNECT:
+		return nmc_meta_generic_get_bool (nm_device_get_autoconnect (d), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_MISSING:
+		return nmc_meta_generic_get_bool (nm_device_get_firmware_missing (d), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_PLUGIN_MISSING:
+		return nmc_meta_generic_get_bool (nm_device_get_nm_plugin_missing (d), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PHYS_PORT_ID:
+		return nm_device_get_physical_port_id (d);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CONNECTION:
+		ac = nm_device_get_active_connection (d);
+		return ac ? nm_active_connection_get_id (ac) : NULL;
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_UUID:
+		ac = nm_device_get_active_connection (d);
+		return ac ? nm_active_connection_get_uuid (ac) : NULL;
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_PATH:
+		ac = nm_device_get_active_connection (d);
+		return ac ? nm_object_get_path (NM_OBJECT (ac)) : NULL;
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_METERED:
+		return nmc_meta_generic_get_str_i18n (nmc_device_metered_to_string (nm_device_get_metered (d)),
+		                                      get_type);
+	default:
+		break;
+	}
+
+	g_return_val_if_reached (NULL);
+}
+
+const NmcMetaGenericInfo *const metagen_device_detail_general[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NUM + 1] = {
+#define _METAGEN_DEVICE_DETAIL_GENERAL(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_general_get_fcn)
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE,            "DEVICE"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE,              "TYPE"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE,           "NM-TYPE"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR,            "VENDOR"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT,           "PRODUCT"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER,            "DRIVER"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION,    "DRIVER-VERSION"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION,  "FIRMWARE-VERSION"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR,            "HWADDR"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU,               "MTU"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE,             "STATE"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_REASON,            "REASON"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_UDI,               "UDI"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP_IFACE,          "IP-IFACE"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IS_SOFTWARE,       "IS-SOFTWARE"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_MANAGED,        "NM-MANAGED"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_AUTOCONNECT,       "AUTOCONNECT"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_MISSING,  "FIRMWARE-MISSING"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_PLUGIN_MISSING, "NM-PLUGIN-MISSING"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PHYS_PORT_ID,      "PHYS-PORT-ID"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CONNECTION,        "CONNECTION"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_UUID,          "CON-UUID"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_PATH,          "CON-PATH"),
+	_METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_METERED,           "METERED"),
 };
-#define NMC_FIELDS_DEV_SHOW_GENERAL_COMMON  "NAME,DEVICE,TYPE,VENDOR,PRODUCT,DRIVER,HWADDR,STATE"
 
-const NmcMetaGenericInfo *const nmc_fields_dev_show_connections[] = {
-	NMC_META_GENERIC ("NAME"),                         /* 0 */
-	NMC_META_GENERIC ("AVAILABLE-CONNECTION-PATHS"),   /* 1 */
-	NMC_META_GENERIC ("AVAILABLE-CONNECTIONS"),        /* 2 */
-	NULL,
+/*****************************************************************************/
+
+static NMRemoteConnection **
+_device_get_available_connections (NMDevice *d, guint *out_len)
+{
+	NMRemoteConnection **avail_cons;
+	const GPtrArray *avail_cons_arr;
+
+	avail_cons_arr = nm_device_get_available_connections (d);
+	if (!avail_cons_arr || avail_cons_arr->len == 0) {
+		*out_len = 0;
+		return NULL;
+	}
+
+	avail_cons = (NMRemoteConnection **) nmc_objects_sort_by_path ((const NMObject *const*) avail_cons_arr->pdata,
+	                                                               avail_cons_arr->len);
+	nm_assert (avail_cons_arr->len == NM_PTRARRAY_LEN (avail_cons));
+	*out_len = avail_cons_arr->len;
+	return avail_cons;
+}
+
+static gconstpointer
+_metagen_device_detail_connections_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
+{
+	NMDevice *d = target;
+	gs_free NMRemoteConnection **avail_cons = NULL;
+	guint avail_cons_len;
+	guint i, j;
+	char **arr = NULL;
+	GString *str;
+	gboolean had_prefix, has_prefix;
+
+	NMC_HANDLE_COLOR (NM_META_COLOR_NONE);
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTIONS:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+
+		avail_cons = _device_get_available_connections (d, &avail_cons_len);
+		if (avail_cons_len == 0)
+			goto arr_out;
+
+		arr = g_new (char *, avail_cons_len + 1);
+		j = 0;
+		for (i = 0; i < avail_cons_len; i++) {
+			NMRemoteConnection *ac = avail_cons[i];
+			const char *ac_id = nm_connection_get_id (NM_CONNECTION (ac));
+			const char *ac_uuid = nm_connection_get_uuid (NM_CONNECTION (ac));
+
+			if (!ac_id || !ac_uuid) {
+				const char *ac_path = nm_connection_get_path (NM_CONNECTION (ac));
+
+				if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) {
+					arr[j++] =   ac_path
+					           ? g_strdup_printf (_("<invisible> | %s"), ac_path)
+					           : g_strdup (_("<invisible>"));
+				} else {
+					arr[j++] =   ac_path
+					           ? g_strdup_printf ("<invisible> | %s", ac_path)
+					           : g_strdup ("<invisible>");
+				}
+			} else
+				arr[j++] = g_strdup_printf ("%s | %s", ac_uuid, ac_id);
+		}
+		arr[j] = NULL;
+		goto arr_out;
+
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTION_PATHS:
+
+		avail_cons = _device_get_available_connections (d, &avail_cons_len);
+		if (avail_cons_len == 0)
+			return NULL;
+
+		str = g_string_new (NULL);
+
+		had_prefix = FALSE;
+		for (i = 0; i < avail_cons_len; i++) {
+			NMRemoteConnection *ac = avail_cons[i];
+			const char *p = nm_connection_get_path (NM_CONNECTION (ac));
+
+			if (!p)
+				continue;
+
+			has_prefix =    g_str_has_prefix (p, NM_DBUS_PATH_SETTINGS_CONNECTION"/")
+			             && p[NM_STRLEN (NM_DBUS_PATH_SETTINGS_CONNECTION"/")];
+
+			if (str->len > 0) {
+				if (   had_prefix
+				    && !has_prefix)
+					g_string_append_c (str, '}');
+				g_string_append_c (str, ',');
+			}
+
+			if (!has_prefix)
+				g_string_append (str, p);
+			else {
+				if (!had_prefix)
+					g_string_printf (str, "%s/{", NM_DBUS_PATH_SETTINGS_CONNECTION);
+				g_string_append (str, &p[NM_STRLEN (NM_DBUS_PATH_SETTINGS_CONNECTION"/")]);
+			}
+			had_prefix = has_prefix;
+		}
+		if (had_prefix)
+			g_string_append_c (str, '}');
+
+		return (*out_to_free = g_string_free (str, FALSE));
+
+	default:
+		break;
+	}
+
+	g_return_val_if_reached (NULL);
+
+arr_out:
+	NM_SET_OUT (out_is_default, !arr || !arr[0]);
+	*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
+	*out_to_free = arr;
+	return arr;
+}
+
+const NmcMetaGenericInfo *const metagen_device_detail_connections[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_NUM + 1] = {
+#define _METAGEN_DEVICE_DETAIL_CONNECTIONS(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_connections_get_fcn)
+	_METAGEN_DEVICE_DETAIL_CONNECTIONS (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTION_PATHS, "AVAILABLE-CONNECTION-PATHS"),
+	_METAGEN_DEVICE_DETAIL_CONNECTIONS (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTIONS,      "AVAILABLE-CONNECTIONS"),
 };
-#define NMC_FIELDS_DEV_SHOW_CONNECTIONS_COMMON  "NAME,AVAILABLE-CONNECTION-PATHS,AVAILABLE-CONNECTIONS"
-
-const NmcMetaGenericInfo *const nmc_fields_dev_show_cap[] = {
-	NMC_META_GENERIC ("NAME"),             /* 0 */
-	NMC_META_GENERIC ("CARRIER-DETECT"),   /* 1 */
-	NMC_META_GENERIC ("SPEED"),            /* 2 */
-	NMC_META_GENERIC ("IS-SOFTWARE"),      /* 3 */
-	NMC_META_GENERIC ("SRIOV"),            /* 4 */
-	NULL,
+
+/*****************************************************************************/
+
+static gconstpointer
+_metagen_device_detail_capabilities_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
+{
+	NMDevice *d = target;
+	NMDeviceCapabilities caps;
+	guint32 speed;
+
+	NMC_HANDLE_COLOR (NM_META_COLOR_NONE);
+
+	caps = nm_device_get_capabilities (d);
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_CARRIER_DETECT:
+		return nmc_meta_generic_get_bool (NM_FLAGS_HAS (caps, NM_DEVICE_CAP_CARRIER_DETECT), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SPEED:
+		speed = 0;
+		if (NM_IS_DEVICE_ETHERNET (d)) {
+			/* Speed in Mb/s */
+			speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (d));
+		} else if (NM_IS_DEVICE_WIFI (d)) {
+			/* Speed in b/s */
+			speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (d));
+			speed /= 1000;
+		}
+
+		if (speed) {
+			if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
+				return (*out_to_free = g_strdup_printf (_("%u Mb/s"), (guint) speed));
+			return (*out_to_free = g_strdup_printf ("%u Mb/s", (guint) speed));
+		}
+		return nmc_meta_generic_get_str_i18n (N_("unknown"), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_IS_SOFTWARE:
+		return nmc_meta_generic_get_bool (NM_FLAGS_HAS (caps, NM_DEVICE_CAP_IS_SOFTWARE), get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SRIOV:
+		return nmc_meta_generic_get_bool (NM_FLAGS_HAS (caps, NM_DEVICE_CAP_SRIOV), get_type);
+	default:
+		break;
+	}
+
+	g_return_val_if_reached (NULL);
+}
+
+const NmcMetaGenericInfo *const metagen_device_detail_capabilities[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_NUM + 1] = {
+#define _METAGEN_DEVICE_DETAIL_CAPABILITIES(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_capabilities_get_fcn)
+	_METAGEN_DEVICE_DETAIL_CAPABILITIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_CARRIER_DETECT, "CARRIER-DETECT"),
+	_METAGEN_DEVICE_DETAIL_CAPABILITIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SPEED,          "SPEED"),
+	_METAGEN_DEVICE_DETAIL_CAPABILITIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_IS_SOFTWARE,    "IS-SOFTWARE"),
+	_METAGEN_DEVICE_DETAIL_CAPABILITIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SRIOV,          "SRIOV"),
 };
-#define NMC_FIELDS_DEV_SHOW_CAP_COMMON  "NAME,CARRIER-DETECT,SPEED,IS-SOFTWARE"
 
-const NmcMetaGenericInfo *const nmc_fields_dev_show_wired_prop[] = {
-	NMC_META_GENERIC ("NAME"),               /* 0 */
-	NMC_META_GENERIC ("CARRIER"),            /* 1 */
-	NMC_META_GENERIC ("S390-SUBCHANNELS"),   /* 2 */
-	NULL,
+/*****************************************************************************/
+
+static gconstpointer
+_metagen_device_detail_wired_properties_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
+{
+	NMDevice *d = target;
+
+	NMC_HANDLE_COLOR (NM_META_COLOR_NONE);
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_CARRIER:
+		return nmc_meta_generic_get_bool_onoff (nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (d)),
+		                                        get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_S390_SUBCHANNELS:
+		if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
+			return NULL;
+		*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
+		return nm_device_ethernet_get_s390_subchannels (NM_DEVICE_ETHERNET (d));
+	default:
+		break;
+	}
+
+	g_return_val_if_reached (NULL);
+}
+
+const NmcMetaGenericInfo *const metagen_device_detail_wired_properties[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_NUM + 1] = {
+#define _METAGEN_DEVICE_DETAIL_WIRED_PROPERTIES(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_wired_properties_get_fcn)
+	_METAGEN_DEVICE_DETAIL_WIRED_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_CARRIER,          "CARRIER"),
+	_METAGEN_DEVICE_DETAIL_WIRED_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_S390_SUBCHANNELS, "S390-SUBCHANNELS"),
 };
-#define NMC_FIELDS_DEV_SHOW_WIRED_PROP_COMMON  "NAME,CARRIER,S390-SUBCHANNELS"
-
-const NmcMetaGenericInfo *const nmc_fields_dev_show_wifi_prop[] = {
-	NMC_META_GENERIC ("NAME"),    /* 0 */
-	NMC_META_GENERIC ("WEP"),     /* 1 */
-	NMC_META_GENERIC ("WPA"),     /* 2 */
-	NMC_META_GENERIC ("WPA2"),    /* 3 */
-	NMC_META_GENERIC ("TKIP"),    /* 4 */
-	NMC_META_GENERIC ("CCMP"),    /* 5 */
-	NMC_META_GENERIC ("AP"),      /* 6 */
-	NMC_META_GENERIC ("ADHOC"),   /* 7 */
-	NMC_META_GENERIC ("2GHZ"),    /* 8 */
-	NMC_META_GENERIC ("5GHZ"),    /* 9 */
-	NULL,
+
+/*****************************************************************************/
+
+static gconstpointer
+_metagen_device_detail_wifi_properties_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
+{
+	NMDevice *d = target;
+	NMDeviceWifiCapabilities wcaps;
+
+	NMC_HANDLE_COLOR (NM_META_COLOR_NONE);
+
+	wcaps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (d));
+
+	switch (info->info_type) {
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP:
+		return nmc_meta_generic_get_bool (NM_FLAGS_ANY (wcaps, NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104),
+		                                  get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA:
+		return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_WPA),
+		                                  get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2:
+		return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_RSN),
+		                                  get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP:
+		return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_CIPHER_TKIP),
+		                                  get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP:
+		return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_CIPHER_CCMP),
+		                                  get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP:
+		return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_AP),
+		                                  get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC:
+		return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_ADHOC),
+		                                  get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ:
+		return nmc_meta_generic_get_str_i18n (  NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_FREQ_VALID)
+		                                      ? (  NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_FREQ_2GHZ)
+		                                         ? N_("yes")
+		                                         : N_("no"))
+		                                      : N_("unknown"),
+		                                      get_type);
+	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ:
+		return nmc_meta_generic_get_str_i18n (  NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_FREQ_VALID)
+		                                      ? (  NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_FREQ_5GHZ)
+		                                         ? N_("yes")
+		                                         : N_("no"))
+		                                      : N_("unknown"),
+		                                      get_type);
+	default:
+		break;
+	}
+
+	g_return_val_if_reached (NULL);
+}
+
+const NmcMetaGenericInfo *const metagen_device_detail_wifi_properties[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_NUM + 1] = {
+#define _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(type, name) \
+	[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_wifi_properties_get_fcn)
+	_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP,   "WEP"),
+	_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA,   "WPA"),
+	_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2,  "WPA2"),
+	_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP,  "TKIP"),
+	_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP,  "CCMP"),
+	_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP,    "AP"),
+	_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC, "ADHOC"),
+	_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ,  "2GHZ"),
+	_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ,  "5GHZ"),
 };
-#define NMC_FIELDS_DEV_SHOW_WIFI_PROP_COMMON  "NAME,WEP,WPA,WPA2,TKIP,CCMP,AP,ADHOC"
-
-const NmcMetaGenericInfo *const nmc_fields_dev_show_wimax_prop[] = {
-	NMC_META_GENERIC ("NAME"),       /* 0 */
-	NMC_META_GENERIC ("CTR-FREQ"),   /* 1 */
-	NMC_META_GENERIC ("RSSI"),       /* 2 */
-	NMC_META_GENERIC ("CINR"),       /* 3 */
-	NMC_META_GENERIC ("TX-POW"),     /* 4 */
-	NMC_META_GENERIC ("BSID"),       /* 5 */
-	NULL,
+
+/*****************************************************************************/
+
+const NmcMetaGenericInfo *const metagen_device_detail_wimax_properties[] = {
+	NMC_META_GENERIC ("CTR-FREQ"),
+	NMC_META_GENERIC ("RSSI"),
+	NMC_META_GENERIC ("CINR"),
+	NMC_META_GENERIC ("TX-POW"),
+	NMC_META_GENERIC ("BSID"),
 };
-#define NMC_FIELDS_DEV_SHOW_WIMAX_PROP_COMMON  "NAME,CTR-FREQ,RSSI,CINR,TX-POW,BSID"
+
+/*****************************************************************************/
 
 const NmcMetaGenericInfo *const nmc_fields_dev_wifi_list[] = {
 	NMC_META_GENERIC ("NAME"),        /* 0 */
@@ -201,23 +620,23 @@ const NmcMetaGenericInfo *const nmc_fields_dev_show_bluetooth[] = {
 
 /* Available sections for 'device show' */
 const NmcMetaGenericInfo *const nmc_fields_dev_show_sections[] = {
-	NMC_META_GENERIC_WITH_NESTED ("GENERAL",           nmc_fields_dev_show_general + 1),      /* 0 */
-	NMC_META_GENERIC_WITH_NESTED ("CAPABILITIES",      nmc_fields_dev_show_cap + 1),          /* 1 */
-	NMC_META_GENERIC_WITH_NESTED ("WIFI-PROPERTIES",   nmc_fields_dev_show_wifi_prop + 1),    /* 2 */
+	NMC_META_GENERIC_WITH_NESTED ("GENERAL",           metagen_device_detail_general),        /* 0 */
+	NMC_META_GENERIC_WITH_NESTED ("CAPABILITIES",      metagen_device_detail_capabilities),   /* 1 */
+	NMC_META_GENERIC_WITH_NESTED ("WIFI-PROPERTIES",   metagen_device_detail_wifi_properties), /* 2 */
 	NMC_META_GENERIC_WITH_NESTED ("AP",                nmc_fields_dev_wifi_list + 1),         /* 3 */
-	NMC_META_GENERIC_WITH_NESTED ("WIRED-PROPERTIES",  nmc_fields_dev_show_wired_prop + 1),   /* 4 */
-	NMC_META_GENERIC_WITH_NESTED ("WIMAX-PROPERTIES",  nmc_fields_dev_show_wimax_prop + 1),   /* 5 */
+	NMC_META_GENERIC_WITH_NESTED ("WIRED-PROPERTIES",  metagen_device_detail_wired_properties), /* 4 */
+	NMC_META_GENERIC_WITH_NESTED ("WIMAX-PROPERTIES",  metagen_device_detail_wimax_properties), /* 5 */
 	NMC_META_GENERIC_WITH_NESTED ("NSP",               nmc_fields_dev_wimax_list + 1),        /* 6 */
 	NMC_META_GENERIC_WITH_NESTED ("IP4",               metagen_ip4_config),                   /* 7 */
-	NMC_META_GENERIC_WITH_NESTED ("DHCP4",             nmc_fields_dhcp_config + 1),           /* 8 */
-	NMC_META_GENERIC_WITH_NESTED ("IP6",               nmc_fields_ip6_config + 1),            /* 9 */
-	NMC_META_GENERIC_WITH_NESTED ("DHCP6",             nmc_fields_dhcp_config + 1),           /* 10 */
+	NMC_META_GENERIC_WITH_NESTED ("DHCP4",             metagen_dhcp_config),                  /* 8 */
+	NMC_META_GENERIC_WITH_NESTED ("IP6",               metagen_ip6_config),                   /* 9 */
+	NMC_META_GENERIC_WITH_NESTED ("DHCP6",             metagen_dhcp_config),                  /* 10 */
 	NMC_META_GENERIC_WITH_NESTED ("BOND",              nmc_fields_dev_show_master_prop + 1),  /* 11 */
 	NMC_META_GENERIC_WITH_NESTED ("TEAM",              nmc_fields_dev_show_team_prop + 1),    /* 12 */
 	NMC_META_GENERIC_WITH_NESTED ("BRIDGE",            nmc_fields_dev_show_master_prop + 1),  /* 13 */
 	NMC_META_GENERIC_WITH_NESTED ("VLAN",              nmc_fields_dev_show_vlan_prop + 1),    /* 14 */
 	NMC_META_GENERIC_WITH_NESTED ("BLUETOOTH",         nmc_fields_dev_show_bluetooth + 1),    /* 15 */
-	NMC_META_GENERIC_WITH_NESTED ("CONNECTIONS",       nmc_fields_dev_show_connections + 1),  /* 16 */
+	NMC_META_GENERIC_WITH_NESTED ("CONNECTIONS",       metagen_device_detail_connections),    /* 16 */
 	NULL,
 };
 #define NMC_FIELDS_DEV_SHOW_SECTIONS_COMMON  "GENERAL.DEVICE,GENERAL.TYPE,GENERAL.HWADDR,GENERAL.MTU,GENERAL.STATE,"\
@@ -707,63 +1126,6 @@ sort_access_points (const GPtrArray *aps)
 	return sorted;
 }
 
-static NMMetaColor
-wifi_signal_to_color (guint8 strength)
-{
-	if (strength > 80)
-		return NM_META_COLOR_WIFI_SIGNAL_EXCELLENT;
-	else if (strength > 55)
-		return NM_META_COLOR_WIFI_SIGNAL_GOOD;
-	else if (strength > 30)
-		return NM_META_COLOR_WIFI_SIGNAL_FAIR;
-	else if (strength > 5)
-		return NM_META_COLOR_WIFI_SIGNAL_POOR;
-	else
-		return NM_META_COLOR_WIFI_SIGNAL_UNKNOWN;
-}
-
-static char *
-ap_wpa_rsn_flags_to_string (NM80211ApSecurityFlags flags)
-{
-	char *flags_str[16]; /* Enough space for flags and terminating NULL */
-	char *ret_str;
-	int i = 0;
-
-	if (flags & NM_802_11_AP_SEC_PAIR_WEP40)
-		flags_str[i++] = g_strdup ("pair_wpe40");
-	if (flags & NM_802_11_AP_SEC_PAIR_WEP104)
-		flags_str[i++] = g_strdup ("pair_wpe104");
-	if (flags & NM_802_11_AP_SEC_PAIR_TKIP)
-		flags_str[i++] = g_strdup ("pair_tkip");
-	if (flags & NM_802_11_AP_SEC_PAIR_CCMP)
-		flags_str[i++] = g_strdup ("pair_ccmp");
-	if (flags & NM_802_11_AP_SEC_GROUP_WEP40)
-		flags_str[i++] = g_strdup ("group_wpe40");
-	if (flags & NM_802_11_AP_SEC_GROUP_WEP104)
-		flags_str[i++] = g_strdup ("group_wpe104");
-	if (flags & NM_802_11_AP_SEC_GROUP_TKIP)
-		flags_str[i++] = g_strdup ("group_tkip");
-	if (flags & NM_802_11_AP_SEC_GROUP_CCMP)
-		flags_str[i++] = g_strdup ("group_ccmp");
-	if (flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
-		flags_str[i++] = g_strdup ("psk");
-	if (flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
-		flags_str[i++] = g_strdup ("802.1X");
-
-	if (i == 0)
-		flags_str[i++] = g_strdup (_("(none)"));
-
-	flags_str[i] = NULL;
-
-	ret_str = g_strjoinv (" ", flags_str);
-
-	i = 0;
-	while (flags_str[i])
-		g_free (flags_str[i++]);
-
-	return ret_str;
-}
-
 typedef struct {
 	NmCli *nmc;
 	int index;
@@ -923,18 +1285,6 @@ construct_header_name (const char *base, const char *spec)
 	return g_strdup_printf ("%s (%s)", base, spec);
 }
 
-static const char *
-get_active_connection_id (NMDevice *device)
-{
-	NMActiveConnection *ac;
-
-	ac = nm_device_get_active_connection (device);
-	if (!ac)
-		return NULL;
-
-	return nm_active_connection_get_id (ac);
-}
-
 static gboolean
 print_bond_bridge_info (NMDevice *device,
                         NmCli *nmc,
@@ -1061,13 +1411,7 @@ static gboolean
 show_device_info (NMDevice *device, NmCli *nmc)
 {
 	GError *error = NULL;
-	const char *hwaddr = NULL;
 	NMDeviceState state = NM_DEVICE_STATE_UNKNOWN;
-	NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
-	NMDeviceCapabilities caps;
-	NMActiveConnection *acon;
-	guint32 speed;
-	char *speed_str, *state_str, *reason_str, *mtu_str;
 	GArray *sections_array;
 	int k;
 	const char *fields_str = NULL;
@@ -1104,12 +1448,12 @@ show_device_info (NMDevice *device, NmCli *nmc)
 
 		/* Lazy way to retrieve sorted array from 0 to the number of dev fields */
 		out_indices = parse_output_fields (NULL,
-		                                   (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_general,
+		                                   (const NMMetaAbstractInfo *const*) metagen_device_detail_general,
 		                                   FALSE, NULL, NULL);
 
-		row = g_new0 (NmcOutputField, G_N_ELEMENTS (nmc_fields_dev_show_general));
-		for (i = 0; i < G_N_ELEMENTS (nmc_fields_dev_show_general); i++)
-			row[i].info = (const NMMetaAbstractInfo *) &nmc_fields_dev_show_general[i];
+		row = g_new0 (NmcOutputField, G_N_ELEMENTS (metagen_device_detail_general));
+		for (i = 0; i < G_N_ELEMENTS (metagen_device_detail_general); i++)
+			row[i].info = (const NMMetaAbstractInfo *) &metagen_device_detail_general[i];
 
 		print_required_fields (&nmc->nmc_config, NMC_OF_FLAG_MAIN_HEADER_ONLY,
 		                       out_indices, header_name,
@@ -1121,138 +1465,65 @@ show_device_info (NMDevice *device, NmCli *nmc)
 		int section_idx = g_array_index (sections_array, int, k);
 		char *section_fld = (char *) g_ptr_array_index (fields_in_section, k);
 
-		if (nmc->nmc_config.print_output != NMC_PRINT_TERSE && !nmc->nmc_config.multiline_output && was_output)
+		if (   NM_IN_SET (nmc->nmc_config.print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY)
+		    && !nmc->nmc_config.multiline_output
+		    && was_output)
 			g_print ("\n"); /* Print empty line between groups in tabular mode */
 
 		was_output = FALSE;
 
 		state = nm_device_get_state (device);
-		reason = nm_device_get_state_reason (device);
-
-		/* section GENERAL */
-		if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[0]->name)) {
-			NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
-			tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_general;
-			out_indices = parse_output_fields (section_fld,
-			                                   tmpl, FALSE, NULL, NULL);
-			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
-			g_ptr_array_add (out.output_data, arr);
-
-			state_str = g_strdup_printf ("%d (%s)", state, nmc_device_state_to_string (state));
-			reason_str = g_strdup_printf ("%d (%s)", reason, nmc_device_reason_to_string (reason));
-			hwaddr = nm_device_get_hw_address (device);
-			mtu_str = g_strdup_printf ("%u", nm_device_get_mtu (device));
-			acon = nm_device_get_active_connection (device);
-
-			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
-			set_val_strc (arr, 0, nmc_fields_dev_show_sections[0]->name);  /* "GENERAL"*/
-			set_val_strc (arr, 1, nm_device_get_iface (device));
-			set_val_strc (arr, 2, nm_device_get_type_description (device));
-			set_val_strc (arr, 3, G_OBJECT_TYPE_NAME (device));
-			set_val_strc (arr, 4, nm_device_get_vendor (device));
-			set_val_strc (arr, 5, nm_device_get_product (device));
-			set_val_strc (arr, 6, nm_device_get_driver (device) ? nm_device_get_driver (device) : _("(unknown)"));
-			set_val_strc (arr, 7, nm_device_get_driver_version (device));
-			set_val_strc (arr, 8, nm_device_get_firmware_version (device));
-			set_val_strc (arr, 9, hwaddr ?: _("(unknown)"));
-			set_val_str  (arr, 10, mtu_str);
-			set_val_str  (arr, 11, state_str);
-			set_val_str  (arr, 12, reason_str);
-			set_val_strc (arr, 13, nm_device_get_udi (device));
-			set_val_strc (arr, 14, nm_device_get_ip_iface (device));
-			set_val_strc (arr, 15, nm_device_is_software (device) ? _("yes") : _("no"));
-			set_val_strc (arr, 16, nm_device_get_managed (device) ? _("yes") : _("no"));
-			set_val_strc (arr, 17, nm_device_get_autoconnect (device) ? _("yes") : _("no"));
-			set_val_strc (arr, 18, nm_device_get_firmware_missing (device) ? _("yes") : _("no"));
-			set_val_strc (arr, 19, nm_device_get_nm_plugin_missing (device) ? _("yes") : _("no"));
-			set_val_strc (arr, 20, nm_device_get_physical_port_id (device));
-			set_val_strc (arr, 21, get_active_connection_id (device));
-			set_val_strc (arr, 22, acon ? nm_active_connection_get_uuid (acon) : NULL);
-			set_val_strc (arr, 23, acon ? nm_object_get_path (NM_OBJECT (acon)) : NULL);
-			set_val_strc (arr, 24, nmc_device_metered_to_string (nm_device_get_metered (device)));
-			g_ptr_array_add (out.output_data, arr);
+		if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_general) {
+			gs_free char *f = section_fld ? g_strdup_printf ("GENERAL.%s", section_fld) : NULL;
 
-			print_data_prepare_width (out.output_data);
-			print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
+			nmc_print (&nmc->nmc_config,
+			           (gpointer[]) { device, NULL },
+			           NULL,
+			           NULL,
+			           NMC_META_GENERIC_GROUP ("GENERAL", metagen_device_detail_general, N_("NAME")),
+			           f,
+			           NULL);
 			was_output = TRUE;
+			continue;
 		}
 
-		/* section CAPABILITIES */
-		if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[1]->name)) {
-			NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
+		if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_capabilities) {
+			gs_free char *f = section_fld ? g_strdup_printf ("CAPABILITIES.%s", section_fld) : NULL;
 
-			tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_cap;
-			out_indices = parse_output_fields (section_fld,
-			                                   tmpl, FALSE, NULL, NULL);
-			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
-			g_ptr_array_add (out.output_data, arr);
+			nmc_print (&nmc->nmc_config,
+			           (gpointer[]) { device, NULL },
+			           NULL,
+			           NULL,
+			           NMC_META_GENERIC_GROUP ("CAPABILITIES", metagen_device_detail_capabilities, N_("NAME")),
+			           f,
+			           NULL);
+			was_output = TRUE;
+			continue;
+		}
 
-			caps = nm_device_get_capabilities (device);
-			speed = 0;
-			if (NM_IS_DEVICE_ETHERNET (device)) {
-				/* Speed in Mb/s */
-				speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (device));
-			} else if (NM_IS_DEVICE_WIFI (device)) {
-				/* Speed in b/s */
-				speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (device));
-				speed /= 1000;
+		if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_wifi_properties) {
+			if (NM_IS_DEVICE_WIFI (device)) {
+				gs_free char *f = section_fld ? g_strdup_printf ("WIFI-PROPERTIES.%s", section_fld) : NULL;
+
+				nmc_print (&nmc->nmc_config,
+				           (gpointer[]) { device, NULL },
+				           NULL,
+				           NULL,
+				           NMC_META_GENERIC_GROUP ("WIFI-PROPERTIES", metagen_device_detail_wifi_properties, N_("NAME")),
+				           f,
+				           NULL);
+				was_output = TRUE;
 			}
-			speed_str = speed ? g_strdup_printf (_("%u Mb/s"), speed) : g_strdup (_("unknown"));
-
-			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
-			set_val_strc (arr, 0, nmc_fields_dev_show_sections[1]->name);  /* "CAPABILITIES" */
-			set_val_strc (arr, 1, (caps & NM_DEVICE_CAP_CARRIER_DETECT) ? _("yes") : _("no"));
-			set_val_str  (arr, 2, speed_str);
-			set_val_strc (arr, 3, (caps & NM_DEVICE_CAP_IS_SOFTWARE) ? _("yes") : _("no"));
-			set_val_strc (arr, 4, (caps & NM_DEVICE_CAP_SRIOV) ? _("yes") : _("no"));
-			g_ptr_array_add (out.output_data, arr);
-
-			print_data_prepare_width (out.output_data);
-			print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
-			was_output = TRUE;
+			continue;
 		}
 
 		/* Wireless specific information */
 		if ((NM_IS_DEVICE_WIFI (device))) {
-			NMDeviceWifiCapabilities wcaps;
 			NMAccessPoint *active_ap = NULL;
 			const char *active_bssid = NULL;
 			GPtrArray *aps;
 
-			/* section WIFI-PROPERTIES */
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[2]->name)) {
-				NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
-
-				wcaps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (device));
-
-				tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_wifi_prop;
-				out_indices = parse_output_fields (section_fld,
-				                                   tmpl, FALSE, NULL, NULL);
-				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
-				g_ptr_array_add (out.output_data, arr);
-
-				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
-				set_val_strc (arr, 0, nmc_fields_dev_show_sections[2]->name);  /* "WIFI-PROPERTIES" */
-				set_val_strc (arr, 1, (wcaps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) ?
-				                        _("yes") : _("no"));
-				set_val_strc (arr, 2, (wcaps & NM_WIFI_DEVICE_CAP_WPA) ? _("yes") : _("no"));
-				set_val_strc (arr, 3, (wcaps & NM_WIFI_DEVICE_CAP_RSN) ? _("yes") : _("no"));
-				set_val_strc (arr, 4, (wcaps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP) ? _("yes") : _("no"));
-				set_val_strc (arr, 5, (wcaps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP) ? _("yes") : _("no"));
-				set_val_strc (arr, 6, (wcaps & NM_WIFI_DEVICE_CAP_AP) ? _("yes") : _("no"));
-				set_val_strc (arr, 7, (wcaps & NM_WIFI_DEVICE_CAP_ADHOC) ? _("yes") : _("no"));
-				set_val_strc (arr, 8, !(wcaps & NM_WIFI_DEVICE_CAP_FREQ_VALID) ? _("unknown") :
-				                      ((wcaps & NM_WIFI_DEVICE_CAP_FREQ_2GHZ) ? _("yes") : _("no")));
-				set_val_strc (arr, 9, !(wcaps & NM_WIFI_DEVICE_CAP_FREQ_VALID) ? _("unknown") :
-				                      ((wcaps & NM_WIFI_DEVICE_CAP_FREQ_5GHZ) ? _("yes") : _("no")));
-				g_ptr_array_add (out.output_data, arr);
-
-				print_data_prepare_width (out.output_data);
-				print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
-				was_output = TRUE;
-			}
-
 			/* section AP */
 			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[3]->name)) {
 				NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
@@ -1287,28 +1558,22 @@ show_device_info (NMDevice *device, NmCli *nmc)
 				print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
 				was_output = TRUE;
 			}
-		} else if (NM_IS_DEVICE_ETHERNET (device)) {
-			/* WIRED-PROPERTIES */
-			if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[4]->name)) {
-				NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
-
-				tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_wired_prop;
-				out_indices = parse_output_fields (section_fld,
-				                                   tmpl, FALSE, NULL, NULL);
-				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
-				g_ptr_array_add (out.output_data, arr);
-
-				arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
-				set_val_strc (arr, 0, nmc_fields_dev_show_sections[4]->name);  /* "WIRED-PROPERTIES" */
-				set_val_strc (arr, 1, (nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (device))) ?
-				                        _("on") : _("off"));
-				set_val_arrc (arr, 2, ((const char **) nm_device_ethernet_get_s390_subchannels (NM_DEVICE_ETHERNET (device))));
-				g_ptr_array_add (out.output_data, arr);
+		}
 
-				print_data_prepare_width (out.output_data);
-				print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
+		if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_wired_properties) {
+			if ((NM_IS_DEVICE_ETHERNET (device))) {
+				gs_free char *f = section_fld ? g_strdup_printf ("WIRED-PROPERTIES.%s", section_fld) : NULL;
+
+				nmc_print (&nmc->nmc_config,
+				           (gpointer[]) { device, NULL },
+				           NULL,
+				           NULL,
+				           NMC_META_GENERIC_GROUP ("WIRED-PROPERTIES", metagen_device_detail_wired_properties, N_("NAME")),
+				           f,
+				           NULL);
 				was_output = TRUE;
 			}
+			continue;
 		}
 
 		/* IP configuration info */
@@ -1319,19 +1584,19 @@ show_device_info (NMDevice *device, NmCli *nmc)
 
 		/* IP4 */
 		if (cfg4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[7]->name))
-			was_output = print_ip4_config (cfg4, &nmc->nmc_config, section_fld);
+			was_output = print_ip_config (cfg4, AF_INET, &nmc->nmc_config, section_fld);
 
 		/* DHCP4 */
 		if (dhcp4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[8]->name))
-			was_output = print_dhcp_config (dhcp4, &nmc->nmc_config, nmc_fields_dev_show_sections[8]->name, section_fld);
+			was_output = print_dhcp_config (dhcp4, AF_INET, &nmc->nmc_config, section_fld);
 
 		/* IP6 */
 		if (cfg6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[9]->name))
-			was_output = print_ip6_config (cfg6, &nmc->nmc_config, nmc_fields_dev_show_sections[9]->name, section_fld);
+			was_output = print_ip_config (cfg6, AF_INET6, &nmc->nmc_config, section_fld);
 
 		/* DHCP6 */
 		if (dhcp6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[10]->name))
-			was_output = print_dhcp_config (dhcp6, &nmc->nmc_config, nmc_fields_dev_show_sections[10]->name, section_fld);
+			was_output = print_dhcp_config (dhcp6, AF_INET6, &nmc->nmc_config, section_fld);
 
 		/* Bond specific information */
 		if (NM_IS_DEVICE_BOND (device)) {
@@ -1398,55 +1663,18 @@ show_device_info (NMDevice *device, NmCli *nmc)
 			}
 		}
 
-		/* section CONNECTIONS */
-		if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[16]->name)) {
-			const GPtrArray *avail_cons;
-			GString *ac_paths_str;
-			char **ac_arr = NULL;
-			int i;
-			NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
-
-			tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_connections;
-			out_indices = parse_output_fields (section_fld,
-			                                   tmpl, FALSE, NULL, NULL);
-			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
-			g_ptr_array_add (out.output_data, arr);
-
-			/* available-connections */
-			avail_cons = nm_device_get_available_connections (device);
-			ac_paths_str = g_string_new (NULL);
-			if (avail_cons->len) {
-				ac_arr = g_new (char *, avail_cons->len + 1);
-				ac_arr[avail_cons->len] = NULL;
-			}
-			for (i = 0; i < avail_cons->len; i++) {
-				NMRemoteConnection *avail_con = g_ptr_array_index (avail_cons, i);
-				const char *ac_path = nm_connection_get_path (NM_CONNECTION (avail_con));
-				const char *ac_id = nm_connection_get_id (NM_CONNECTION (avail_con));
-				const char *ac_uuid = nm_connection_get_uuid (NM_CONNECTION (avail_con));
-
-				ac_arr[i] = g_strdup_printf ("%s | %s", ac_uuid, ac_id);
-
-				if (i == 0)
-					g_string_printf (ac_paths_str, "%s/{", NM_DBUS_PATH_SETTINGS);
-				else
-					g_string_append_c (ac_paths_str, ',');
-				g_string_append (ac_paths_str, strrchr (ac_path, '/') + 1);
-			}
-			if (ac_paths_str->len > 0)
-				g_string_append_c (ac_paths_str, '}');
-
-			arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
-			set_val_strc (arr, 0, nmc_fields_dev_show_sections[16]->name);  /* "CONNECTIONS" */
-			set_val_str  (arr, 1, ac_paths_str->str);
-			set_val_arr  (arr, 2, (ac_arr));
-			g_ptr_array_add (out.output_data, arr);
-
-			print_data_prepare_width (out.output_data);
-			print_data (&nmc->nmc_config, out_indices, NULL, 0, &out);
+		if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_connections) {
+			gs_free char *f = section_fld ? g_strdup_printf ("CONNECTIONS.%s", section_fld) : NULL;
 
-			g_string_free (ac_paths_str, FALSE);
+			nmc_print (&nmc->nmc_config,
+			           (gpointer[]) { device, NULL },
+			           NULL,
+			           NULL,
+			           NMC_META_GENERIC_GROUP ("CONNECTIONS", metagen_device_detail_connections, N_("NAME")),
+			           f,
+			           NULL);
 			was_output = TRUE;
+			continue;
 		}
 	}
 
@@ -1470,50 +1698,18 @@ nmc_device_state_to_color (NMDeviceState state)
 	else if (state == NM_DEVICE_STATE_ACTIVATED)
 		return NM_META_COLOR_DEVICE_ACTIVATED;
 
-	g_return_val_if_reached (NM_META_COLOR_DEVICE_UNKNOWN);
-}
-
-static void
-fill_output_device_status (NMDevice *device, GPtrArray *output_data)
-{
-	NMActiveConnection *ac;
-	NMDeviceState state;
-	NMMetaColor color;
-	NmcOutputField *arr = nmc_dup_fields_array ((const NMMetaAbstractInfo *const*) nmc_fields_dev_status,
-	                                            0);
-
-	state = nm_device_get_state (device);
-	ac = nm_device_get_active_connection (device);
-
-	/* Show devices in color */
-	color = nmc_device_state_to_color (state);
-	set_val_color_all (arr, color);
-
-	set_val_strc (arr, 0, nm_device_get_iface (device));
-	set_val_strc (arr, 1, nm_device_get_type_description (device));
-	set_val_strc (arr, 2, nmc_device_state_to_string (state));
-	set_val_strc (arr, 3, nm_object_get_path (NM_OBJECT (device)));
-	set_val_strc (arr, 4, get_active_connection_id (device));
-	set_val_strc (arr, 5, ac ? nm_active_connection_get_uuid (ac) : NULL);
-	set_val_strc (arr, 6, ac ? nm_object_get_path (NM_OBJECT (ac)) : NULL);
-
-	g_ptr_array_add (output_data, arr);
+	return NM_META_COLOR_DEVICE_UNKNOWN;
 }
 
 static NMCResultCode
 do_devices_status (NmCli *nmc, int argc, char **argv)
 {
 	GError *error = NULL;
-	NMDevice **devices;
-	int i;
+	gs_free NMDevice **devices = NULL;
 	const char *fields_str = NULL;
-	const NMMetaAbstractInfo *const*tmpl;
-	NmcOutputField *arr;
-	NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
 
 	next_arg (nmc, &argc, &argv, NULL);
 
-	/* Nothing to complete */
 	if (nmc->complete)
 		return nmc->return_value;
 
@@ -1523,33 +1719,25 @@ do_devices_status (NmCli *nmc, int argc, char **argv)
 	}
 
 	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
-		fields_str = NMC_FIELDS_DEV_STATUS_COMMON;
+		fields_str = "DEVICE,TYPE,STATE,CONNECTION";
 	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) {
 	} else
 		fields_str = nmc->required_fields;
 
-	tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_status;
-	out_indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
+	devices = nmc_get_devices_sorted (nmc->client);
 
-	if (error) {
+	if (!nmc_print (&nmc->nmc_config,
+	                (gpointer *) devices,
+	                NULL,
+	                N_("Status of devices"),
+	                (const NMMetaAbstractInfo *const*) metagen_device_status,
+	                fields_str,
+	                &error)) {
 		g_string_printf (nmc->return_text, _("Error: 'device status': %s"), error->message);
 		g_error_free (error);
 		return NMC_RESULT_ERROR_USER_INPUT;
 	}
 
-	/* Add headers */
-	arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
-	g_ptr_array_add (out.output_data, arr);
-
-	devices = nmc_get_devices_sorted (nmc->client);
-	for (i = 0; devices[i]; i++)
-		fill_output_device_status (devices[i], out.output_data);
-
-	print_data_prepare_width (out.output_data);
-	print_data (&nmc->nmc_config, out_indices, _("Status of devices"), 0, &out);
-
-	g_free (devices);
-
 	return NMC_RESULT_SUCCESS;
 }
 
@@ -1619,7 +1807,7 @@ progress_cb (gpointer user_data)
 {
 	NMDevice *device = (NMDevice *) user_data;
 
-	nmc_terminal_show_progress (device ? nmc_device_state_to_string (nm_device_get_state (device)) : "");
+	nmc_terminal_show_progress (device ? gettext (nmc_device_state_to_string (nm_device_get_state (device))) : "");
 
 	return TRUE;
 }
@@ -1664,7 +1852,7 @@ connected_state_cb (NMDevice *device, NMActiveConnection *active)
 	           || state >= NM_DEVICE_STATE_DEACTIVATING) {
 		reason = nm_device_get_state_reason (device);
 		g_print (_("Error: Connection activation failed: (%d) %s.\n"),
-		         reason, nmc_device_reason_to_string (reason));
+		         reason, gettext (nmc_device_reason_to_string (reason)));
 	} else
 		return;
 
@@ -2404,7 +2592,7 @@ device_state (NMDevice *device, GParamSpec *pspec, NmCli *nmc)
 	color = nmc_device_state_to_color (state);
 	str = nmc_colorize (&nmc->nmc_config, color, "%s: %s\n",
 	                    nm_device_get_iface (device),
-	                    nmc_device_state_to_string (state));
+	                    gettext (nmc_device_state_to_string (state)));
 
 	g_print ("%s", str);
 	g_free (str);
@@ -3354,7 +3542,7 @@ generate_wpa_key (char *key, size_t len)
 		while (!g_ascii_isalnum (c))
 			c = g_random_int_range (33, 126);
 
-		key[i] = (gchar) c;
+		key[i] = (char) c;
 	}
 	key[WPA_PASSKEY_SIZE] = '\0';
 }