From 59ea03cc0825997a58c2f65f4f9170b0dadd6578 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 26 Apr 2018 14:41:13 +0200 Subject: [PATCH] cli: rework printing of vpn active-connection properties use nmc_print() for the job. --- clients/cli/connections.c | 254 ++++++++++-------- clients/cli/connections.h | 2 +- clients/cli/nmcli.c | 2 +- clients/cli/utils.h | 38 ++- .../test_004-026.expected | 4 +- 5 files changed, 176 insertions(+), 124 deletions(-) diff --git a/clients/cli/connections.c b/clients/cli/connections.c index a38ad3c406..66468fdbc5 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -185,17 +185,24 @@ get_ac_device_string (NMActiveConnection *active) /* FIXME: The same or similar code for VPN info appears also in nm-applet (applet-dialogs.c), * and in gnome-control-center as well. It could probably be shared somehow. */ -static char * +static const char * get_vpn_connection_type (NMConnection *connection) { + NMSettingVpn *s_vpn; const char *type, *p; + s_vpn = nm_connection_get_setting_vpn (connection); + if (!s_vpn) + return NULL; + /* The service type is in form of "org.freedesktop.NetworkManager.vpnc". * Extract end part after last dot, e.g. "vpnc" */ type = nm_setting_vpn_get_service_type (nm_connection_get_setting_vpn (connection)); + if (!type) + return NULL; p = strrchr (type, '.'); - return g_strdup (p ? p + 1 : type); + return p ? p + 1 : type; } /* VPN parameters can be found at: @@ -206,31 +213,35 @@ get_vpn_connection_type (NMConnection *connection) * http://git.gnome.org/browse/network-manager-openswan/tree/src/nm-openswan-service.h * See also 'properties' directory in these plugins. */ -static const gchar * +static const char * find_vpn_gateway_key (const char *vpn_type) { - if (g_strcmp0 (vpn_type, "openvpn") == 0) return "remote"; - if (g_strcmp0 (vpn_type, "vpnc") == 0) return "IPSec gateway"; - if (g_strcmp0 (vpn_type, "pptp") == 0) return "gateway"; - if (g_strcmp0 (vpn_type, "openconnect") == 0) return "gateway"; - if (g_strcmp0 (vpn_type, "openswan") == 0) return "right"; - if (g_strcmp0 (vpn_type, "libreswan") == 0) return "right"; - if (g_strcmp0 (vpn_type, "ssh") == 0) return "remote"; - if (g_strcmp0 (vpn_type, "l2tp") == 0) return "gateway"; - return ""; + if (vpn_type) { + if (nm_streq (vpn_type, "openvpn")) return "remote"; + if (nm_streq (vpn_type, "vpnc")) return "IPSec gateway"; + if (nm_streq (vpn_type, "pptp")) return "gateway"; + if (nm_streq (vpn_type, "openconnect")) return "gateway"; + if (nm_streq (vpn_type, "openswan")) return "right"; + if (nm_streq (vpn_type, "libreswan")) return "right"; + if (nm_streq (vpn_type, "ssh")) return "remote"; + if (nm_streq (vpn_type, "l2tp")) return "gateway"; + } + return NULL; } -static const gchar * +static const char * find_vpn_username_key (const char *vpn_type) { - if (g_strcmp0 (vpn_type, "openvpn") == 0) return "username"; - if (g_strcmp0 (vpn_type, "vpnc") == 0) return "Xauth username"; - if (g_strcmp0 (vpn_type, "pptp") == 0) return "user"; - if (g_strcmp0 (vpn_type, "openconnect") == 0) return "username"; - if (g_strcmp0 (vpn_type, "openswan") == 0) return "leftxauthusername"; - if (g_strcmp0 (vpn_type, "libreswan") == 0) return "leftxauthusername"; - if (g_strcmp0 (vpn_type, "l2tp") == 0) return "user"; - return ""; + if (vpn_type) { + if (nm_streq (vpn_type, "openvpn")) return "username"; + if (nm_streq (vpn_type, "vpnc")) return "Xauth username"; + if (nm_streq (vpn_type, "pptp")) return "user"; + if (nm_streq (vpn_type, "openconnect")) return "username"; + if (nm_streq (vpn_type, "openswan")) return "leftxauthusername"; + if (nm_streq (vpn_type, "libreswan")) return "leftxauthusername"; + if (nm_streq (vpn_type, "l2tp")) return "user"; + } + return NULL; } enum VpnDataItem { @@ -241,8 +252,8 @@ enum VpnDataItem { static const gchar * get_vpn_data_item (NMConnection *connection, enum VpnDataItem vpn_data_item) { - const char *key; - gs_free char *type = NULL; + const char *type; + const char *key = NULL; type = get_vpn_connection_type (connection); @@ -254,10 +265,11 @@ get_vpn_data_item (NMConnection *connection, enum VpnDataItem vpn_data_item) key = find_vpn_username_key (type); break; default: - key = ""; break; } + if (!key) + return NULL; return nm_setting_vpn_get_data_item (nm_connection_get_setting_vpn (connection), key); } @@ -627,6 +639,100 @@ const NmcMetaGenericInfo *const metagen_con_active_general[_NMC_GENERIC_INFO_TYP /*****************************************************************************/ +static gconstpointer +_metagen_con_active_vpn_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMActiveConnection *ac = target; + NMConnection *c; + NMSettingVpn *s_vpn = NULL; + NMVpnConnectionState vpn_state; + guint i; + const char *s; + char **arr = NULL; + + nm_assert (NM_IS_VPN_CONNECTION (ac)); + + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); + + nm_assert (NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_PRETTY, NM_META_ACCESSOR_GET_TYPE_PARSABLE)); + + c = NM_CONNECTION (nm_active_connection_get_connection (ac)); + if (c) + s_vpn = nm_connection_get_setting_vpn (c); + + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_CON_VPN_TYPE: + return c ? get_vpn_connection_type (c) : NULL; + case NMC_GENERIC_INFO_TYPE_CON_VPN_USERNAME: + if ( s_vpn + && (s = nm_setting_vpn_get_user_name (s_vpn))) + return s; + return c ? get_vpn_data_item (c, VPN_DATA_ITEM_USERNAME) : NULL; + case NMC_GENERIC_INFO_TYPE_CON_VPN_GATEWAY: + return c ? get_vpn_data_item (c, VPN_DATA_ITEM_GATEWAY) : NULL; + case NMC_GENERIC_INFO_TYPE_CON_VPN_BANNER: + s = nm_vpn_connection_get_banner (NM_VPN_CONNECTION (ac)); + if (s) + return (*out_to_free = g_strescape (s, "")); + return NULL; + case NMC_GENERIC_INFO_TYPE_CON_VPN_VPN_STATE: + vpn_state = nm_vpn_connection_get_vpn_state (NM_VPN_CONNECTION (ac)); + return (*out_to_free = nmc_meta_generic_get_enum_with_detail (NMC_META_GENERIC_GET_ENUM_TYPE_DASH, + vpn_state, + vpn_connection_state_to_string (vpn_state), + get_type)); + case NMC_GENERIC_INFO_TYPE_CON_VPN_CFG: + if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV)) + return NULL; + if (s_vpn) { + gs_free char **arr2 = NULL; + guint n; + + arr2 = (char **) nm_setting_vpn_get_data_keys (s_vpn, &n); + if (!n) + goto arr_out; + + nm_assert (arr2 && !arr2[n]); + for (i = 0; i < n; i++) { + const char *k = arr2[i]; + const char *v; + + nm_assert (k); + v = nm_setting_vpn_get_data_item (s_vpn, k); + /* update the arr array in-place. Previously it contained + * the constant keys, now it contains the strdup'ed output text. */ + arr2[i] = g_strdup_printf ("%s = %s", k, v); + } + + arr = g_steal_pointer (&arr2); + } + goto arr_out; + 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_con_active_vpn[_NMC_GENERIC_INFO_TYPE_CON_ACTIVE_VPN_NUM + 1] = { +#define _METAGEN_CON_ACTIVE_VPN(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_con_active_vpn_get_fcn) + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_TYPE, "TYPE"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_USERNAME, "USERNAME"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_GATEWAY, "GATEWAY"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_BANNER, "BANNER"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_VPN_STATE, "VPN-STATE"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_CFG, "CFG"), +}; + +/*****************************************************************************/ + #define NMC_FIELDS_SETTINGS_NAMES_ALL NM_SETTING_CONNECTION_SETTING_NAME","\ NM_SETTING_WIRED_SETTING_NAME","\ NM_SETTING_802_1X_SETTING_NAME","\ @@ -667,24 +773,13 @@ const NmcMetaGenericInfo *const metagen_con_active_general[_NMC_GENERIC_INFO_TYP // NM_SETTING_DUMMY_SETTING_NAME // NM_SETTING_WIMAX_SETTING_NAME -const NmcMetaGenericInfo *const nmc_fields_con_active_details_vpn[] = { - NMC_META_GENERIC ("GROUP"), /* 0 */ - NMC_META_GENERIC ("TYPE"), /* 1 */ - NMC_META_GENERIC ("USERNAME"), /* 2 */ - NMC_META_GENERIC ("GATEWAY"), /* 3 */ - NMC_META_GENERIC ("BANNER"), /* 4 */ - NMC_META_GENERIC ("VPN-STATE"), /* 5 */ - NMC_META_GENERIC ("CFG"), /* 6 */ - NULL, -}; - const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = { NMC_META_GENERIC_WITH_NESTED ("GENERAL", metagen_con_active_general), /* 0 */ NMC_META_GENERIC_WITH_NESTED ("IP4", metagen_ip4_config), /* 1 */ NMC_META_GENERIC_WITH_NESTED ("DHCP4", nmc_fields_dhcp_config + 1), /* 2 */ NMC_META_GENERIC_WITH_NESTED ("IP6", nmc_fields_ip6_config + 1), /* 3 */ NMC_META_GENERIC_WITH_NESTED ("DHCP6", nmc_fields_dhcp_config + 1), /* 4 */ - NMC_META_GENERIC_WITH_NESTED ("VPN", nmc_fields_con_active_details_vpn + 1), /* 5 */ + NMC_META_GENERIC_WITH_NESTED ("VPN", metagen_con_active_vpn), /* 5 */ NULL, }; @@ -1219,19 +1314,6 @@ nmc_active_connection_state_to_color (NMActiveConnectionState state) return NM_META_COLOR_CONNECTION_UNKNOWN; } -typedef struct { - char **array; - guint32 idx; -} FillVPNDataInfo; - -static void -fill_vpn_data_item (const char *key, const char *value, gpointer user_data) -{ - FillVPNDataInfo *info = (FillVPNDataInfo *) user_data; - - info->array[info->idx++] = g_strdup_printf ("%s = %s", key, value); -} - static gboolean nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) { @@ -1240,8 +1322,6 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) GPtrArray *group_fields = NULL; int i; const char *fields_str = NULL; - const NMMetaAbstractInfo *const*tmpl; - NmcOutputField *arr; const char *base_hdr = _("Activate connection details"); gboolean was_output = FALSE; @@ -1343,69 +1423,17 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) was_output = was_output || b1; } - /* VPN */ - if (NM_IS_VPN_CONNECTION (acon) && - strcasecmp (nmc_fields_con_active_details_groups[group_idx]->name, nmc_fields_con_active_details_groups[5]->name) == 0) { - NMConnection *con; - NMSettingConnection *s_con; - NMSettingVpn *s_vpn; - NMVpnConnectionState vpn_state; - char *type_str, *banner_str = NULL, *vpn_state_str; - const char *banner; - const char *username = NULL; - char **vpn_data_array = NULL; - guint32 items_num; - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); - - con = NM_CONNECTION (nm_active_connection_get_connection (acon)); - - s_con = nm_connection_get_setting_connection (con); - g_assert (s_con); - - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_vpn; - out_indices = parse_output_fields (group_fld, - tmpl, FALSE, NULL, NULL); - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); - g_ptr_array_add (out.output_data, arr); - - s_vpn = nm_connection_get_setting_vpn (con); - if (s_vpn) { - items_num = nm_setting_vpn_get_num_data_items (s_vpn); - if (items_num > 0) { - FillVPNDataInfo info; - - vpn_data_array = g_new (char *, items_num + 1); - info.array = vpn_data_array; - info.idx = 0; - nm_setting_vpn_foreach_data_item (s_vpn, &fill_vpn_data_item, &info); - vpn_data_array[items_num] = NULL; - } - username = nm_setting_vpn_get_user_name (s_vpn); + if (nmc_fields_con_active_details_groups[group_idx]->nested == metagen_con_active_vpn) { + if (NM_IS_VPN_CONNECTION (acon)) { + nmc_print (&nmc->nmc_config, + (gpointer[]) { acon, NULL }, + NULL, + NMC_META_GENERIC_GROUP ("VPN", metagen_con_active_vpn, N_("NAME")), + group_fld, + NULL); + was_output = TRUE; } - - type_str = get_vpn_connection_type (con); - banner = nm_vpn_connection_get_banner (NM_VPN_CONNECTION (acon)); - if (banner) - banner_str = g_strescape (banner, ""); - vpn_state = nm_vpn_connection_get_vpn_state (NM_VPN_CONNECTION (acon)); - vpn_state_str = g_strdup_printf ("%d - %s", - vpn_state, - gettext (vpn_connection_state_to_string (vpn_state))); - - /* Add values */ - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, nmc_fields_con_active_details_groups[5]->name); - set_val_str (arr, 1, type_str); - set_val_strc (arr, 2, username ?: get_vpn_data_item (con, VPN_DATA_ITEM_USERNAME)); - set_val_strc (arr, 3, get_vpn_data_item (con, VPN_DATA_ITEM_GATEWAY)); - set_val_str (arr, 4, banner_str); - set_val_str (arr, 5, vpn_state_str); - set_val_arr (arr, 6, vpn_data_array); - g_ptr_array_add (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; } } diff --git a/clients/cli/connections.h b/clients/cli/connections.h index 43cd97f697..22bfa8ec2a 100644 --- a/clients/cli/connections.h +++ b/clients/cli/connections.h @@ -37,7 +37,7 @@ NMMetaColor nmc_active_connection_state_to_color (NMActiveConnectionState state) extern const NmcMetaGenericInfo *const metagen_con_show[]; extern const NmcMetaGenericInfo *const metagen_con_active_general[]; -extern const NmcMetaGenericInfo *const nmc_fields_con_active_details_vpn[]; +extern const NmcMetaGenericInfo *const metagen_con_active_vpn[]; extern const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[]; #endif /* NMC_CONNECTIONS_H */ diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index c5e0a03fbd..63d0959953 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -193,7 +193,7 @@ complete_fields (const char *option, const char *prefix) complete_field (h, nmc_fields_ip6_config); complete_field (h, metagen_con_show); complete_field (h, metagen_con_active_general); - complete_field (h, nmc_fields_con_active_details_vpn); + complete_field (h, metagen_con_active_vpn); complete_field (h, nmc_fields_con_active_details_groups); complete_field (h, nmc_fields_dev_status); complete_field (h, nmc_fields_dev_show_general); diff --git a/clients/cli/utils.h b/clients/cli/utils.h index 19694d111c..a80b88979b 100644 --- a/clients/cli/utils.h +++ b/clients/cli/utils.h @@ -152,6 +152,14 @@ typedef enum { NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_MASTER_PATH, _NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_NUM, + NMC_GENERIC_INFO_TYPE_CON_VPN_TYPE = 0, + NMC_GENERIC_INFO_TYPE_CON_VPN_USERNAME, + NMC_GENERIC_INFO_TYPE_CON_VPN_GATEWAY, + NMC_GENERIC_INFO_TYPE_CON_VPN_BANNER, + NMC_GENERIC_INFO_TYPE_CON_VPN_VPN_STATE, + NMC_GENERIC_INFO_TYPE_CON_VPN_CFG, + _NMC_GENERIC_INFO_TYPE_CON_ACTIVE_VPN_NUM, + } NmcGenericInfoType; #define NMC_HANDLE_COLOR(color) \ @@ -220,8 +228,13 @@ nmc_meta_generic_get_bool (gboolean val, NMMetaAccessorGetType get_type) return nmc_meta_generic_get_str_i18n (val ? N_("yes") : N_("no"), get_type); } +typedef enum { + NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES, + NMC_META_GENERIC_GET_ENUM_TYPE_DASH, +} NmcMetaGenericGetEnumType; + static inline char * -nmc_meta_generic_get_enum_with_detail (gint64 enum_val, const char *str_val, NMMetaAccessorGetType get_type) +nmc_meta_generic_get_enum_with_detail (NmcMetaGenericGetEnumType get_enum_type, gint64 enum_val, const char *str_val, NMMetaAccessorGetType get_type) { if (!NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_PRETTY, NM_META_ACCESSOR_GET_TYPE_PARSABLE)) @@ -232,12 +245,23 @@ nmc_meta_generic_get_enum_with_detail (gint64 enum_val, const char *str_val, NMM return g_strdup_printf ("%lld", (long long) enum_val); } - /* note that this function will always print "$NUM ($NICK)", also in PARSABLE - * mode. That might not be desired, but it's done for certain properties to preserve - * previous behavior. */ - if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) - return g_strdup_printf (_("%lld (%s)"), (long long) enum_val, gettext (str_val)); - return g_strdup_printf ("%lld (%s)", (long long) enum_val, str_val); + switch (get_enum_type) { + case NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES: + /* note that this function will always print "$NUM ($NICK)", also in PARSABLE + * mode. That might not be desired, but it's done for certain properties to preserve + * previous behavior. */ + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return g_strdup_printf (_("%lld (%s)"), (long long) enum_val, gettext (str_val)); + return g_strdup_printf ("%lld (%s)", (long long) enum_val, str_val); + case NMC_META_GENERIC_GET_ENUM_TYPE_DASH: + /* note that this function will always print "$NUM ($NICK)", also in PARSABLE + * mode. That might not be desired, but it's done for certain properties to preserve + * previous behavior. */ + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return g_strdup_printf (_("%lld - %s"), (long long) enum_val, gettext (str_val)); + return g_strdup_printf ("%lld - %s", (long long) enum_val, str_val); + } + g_return_val_if_reached (NULL); } /*****************************************************************************/ diff --git a/clients/tests/test-client.check-on-disk/test_004-026.expected b/clients/tests/test-client.check-on-disk/test_004-026.expected index e80c54cfbc..a79a8c406b 100644 --- a/clients/tests/test-client.check-on-disk/test_004-026.expected +++ b/clients/tests/test-client.check-on-disk/test_004-026.expected @@ -2,7 +2,7 @@ location: clients/tests/test-client.py:939:test_004()/26 cmd: $NMCLI -t con s con-vpn-1 lang: pl_PL.UTF-8 returncode: 0 -stdout: 2136 bytes +stdout: 2131 bytes >>> connection.id:con-vpn-1 connection.uuid:UUID-con-vpn-1-REPLACED-REPLACED-REP @@ -91,7 +91,7 @@ VPN.TYPE:openvpn VPN.USERNAME: VPN.GATEWAY: VPN.BANNER:*** VPN connection con-vpn-1 *** -VPN.VPN-STATE:5 - Połączono z VPN +VPN.VPN-STATE:5 - VPN connected VPN.CFG[1]:key1 = val1 VPN.CFG[2]:key2 = val2 VPN.CFG[3]:key3 = val3