diff options
Diffstat (limited to 'cli/src/connections.c')
| -rw-r--r-- | cli/src/connections.c | 1053 |
1 files changed, 594 insertions, 459 deletions
diff --git a/cli/src/connections.c b/cli/src/connections.c index 7d4fffc0..ea5211f5 100644 --- a/cli/src/connections.c +++ b/cli/src/connections.c @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2010 - 2011 Red Hat, Inc. + * (C) Copyright 2010 - 2012 Red Hat, Inc. */ #include "config.h" @@ -32,17 +32,6 @@ #include <netinet/ether.h> #include <nm-client.h> -#include <nm-setting-connection.h> -#include <nm-setting-wired.h> -#include <nm-setting-pppoe.h> -#include <nm-setting-wireless.h> -#include <nm-setting-gsm.h> -#include <nm-setting-cdma.h> -#include <nm-setting-bluetooth.h> -#include <nm-setting-olpc-mesh.h> -#if WITH_WIMAX -#include <nm-setting-wimax.h> -#endif #include <nm-device-ethernet.h> #include <nm-device-wifi.h> #if WITH_WIMAX @@ -50,29 +39,20 @@ #endif #include <nm-device-modem.h> #include <nm-device-bt.h> -//#include <nm-device-olpc-mesh.h> +#include <nm-device-olpc-mesh.h> +#include <nm-device-infiniband.h> +#include <nm-device-bond.h> +#include <nm-device-vlan.h> #include <nm-remote-settings.h> #include <nm-vpn-connection.h> +#include <nm-utils.h> #include "utils.h" +#include "common.h" #include "settings.h" #include "connections.h" -/* Available fields for 'con status' */ -static NmcOutputField nmc_fields_con_status[] = { - {"NAME", N_("NAME"), 25, NULL, 0}, /* 0 */ - {"UUID", N_("UUID"), 38, NULL, 0}, /* 1 */ - {"DEVICES", N_("DEVICES"), 10, NULL, 0}, /* 2 */ - {"DEFAULT", N_("DEFAULT"), 8, NULL, 0}, /* 3 */ - {"SPEC-OBJECT", N_("SPEC-OBJECT"), 10, NULL, 0}, /* 4 */ - {"VPN", N_("VPN"), 5, NULL, 0}, /* 5 */ - {"DBUS-PATH", N_("DBUS-PATH"), 51, NULL, 0}, /* 6 */ - {NULL, NULL, 0, NULL, 0} -}; -#define NMC_FIELDS_CON_STATUS_ALL "NAME,UUID,DEVICES,DEFAULT,VPN,DBUS-PATH,SPEC-OBJECT" -#define NMC_FIELDS_CON_STATUS_COMMON "NAME,UUID,DEVICES,DEFAULT,VPN" - /* Available fields for 'con list' */ static NmcOutputField nmc_fields_con_list[] = { {"NAME", N_("NAME"), 25, NULL, 0}, /* 0 */ @@ -88,7 +68,6 @@ static NmcOutputField nmc_fields_con_list[] = { #define NMC_FIELDS_CON_LIST_ALL "NAME,UUID,TYPE,TIMESTAMP,TIMESTAMP-REAL,AUTOCONNECT,READONLY,DBUS-PATH" #define NMC_FIELDS_CON_LIST_COMMON "NAME,UUID,TYPE,TIMESTAMP-REAL" - /* Helper macro to define fields */ #define SETTING_FIELD(setting, width) { setting, N_(setting), width, NULL, 0 } @@ -110,6 +89,9 @@ static NmcOutputField nmc_fields_settings_names[] = { SETTING_FIELD (NM_SETTING_OLPC_MESH_SETTING_NAME, 0), /* 13 */ SETTING_FIELD (NM_SETTING_VPN_SETTING_NAME, 0), /* 14 */ SETTING_FIELD (NM_SETTING_WIMAX_SETTING_NAME, 0), /* 15 */ + SETTING_FIELD (NM_SETTING_INFINIBAND_SETTING_NAME, 0), /* 16 */ + SETTING_FIELD (NM_SETTING_BOND_SETTING_NAME, 0), /* 17 */ + SETTING_FIELD (NM_SETTING_VLAN_SETTING_NAME, 0), /* 18 */ {NULL, NULL, 0, NULL, 0} }; #define NMC_FIELDS_SETTINGS_NAMES_ALL_X NM_SETTING_CONNECTION_SETTING_NAME","\ @@ -126,7 +108,10 @@ static NmcOutputField nmc_fields_settings_names[] = { NM_SETTING_CDMA_SETTING_NAME","\ NM_SETTING_BLUETOOTH_SETTING_NAME","\ NM_SETTING_OLPC_MESH_SETTING_NAME","\ - NM_SETTING_VPN_SETTING_NAME + NM_SETTING_VPN_SETTING_NAME","\ + NM_SETTING_INFINIBAND_SETTING_NAME","\ + NM_SETTING_BOND_SETTING_NAME","\ + NM_SETTING_VLAN_SETTING_NAME #if WITH_WIMAX #define NMC_FIELDS_SETTINGS_NAMES_ALL NMC_FIELDS_SETTINGS_NAMES_ALL_X","\ NM_SETTING_WIMAX_SETTING_NAME @@ -135,6 +120,54 @@ static NmcOutputField nmc_fields_settings_names[] = { #endif +/* Available fields for 'con status' */ +static NmcOutputField nmc_fields_con_status[] = { + {"GROUP", N_("GROUP"), 9, NULL, 0}, /* 0 */ /* used only for 'GENERAL' group listing */ + {"NAME", N_("NAME"), 25, NULL, 0}, /* 1 */ + {"UUID", N_("UUID"), 38, NULL, 0}, /* 2 */ + {"DEVICES", N_("DEVICES"), 10, NULL, 0}, /* 3 */ + {"STATE", N_("STATE"), 12, NULL, 0}, /* 4 */ + {"DEFAULT", N_("DEFAULT"), 8, NULL, 0}, /* 5 */ + {"DEFAULT6", N_("DEFAULT6"), 9, NULL, 0}, /* 6 */ + {"SPEC-OBJECT", N_("SPEC-OBJECT"), 10, NULL, 0}, /* 7 */ + {"VPN", N_("VPN"), 5, NULL, 0}, /* 8 */ + {"DBUS-PATH", N_("DBUS-PATH"), 51, NULL, 0}, /* 9 */ + {"CON-PATH", N_("CON-PATH"), 44, NULL, 0}, /* 10 */ + {"ZONE", N_("ZONE"), 15, NULL, 0}, /* 11 */ + {"MASTER-PATH", N_("MASTER-PATH"), 44, NULL, 0}, /* 12 */ + {NULL, NULL, 0, NULL, 0} +}; +#define NMC_FIELDS_CON_STATUS_ALL "NAME,UUID,DEVICES,STATE,DEFAULT,DEFAULT6,VPN,ZONE,DBUS-PATH,CON-PATH,SPEC-OBJECT,MASTER-PATH" +#define NMC_FIELDS_CON_STATUS_COMMON "NAME,UUID,DEVICES,DEFAULT,VPN,MASTER-PATH" + +/* Available fields for 'con status id/uuid/path <con>' */ +static NmcOutputField nmc_fields_status_details_groups[] = { + {"GENERAL", N_("GENERAL"), 9, NULL, 0}, /* 0 */ + {"IP", N_("IP"), 5, NULL, 0}, /* 1 */ + {"VPN", N_("VPN"), 5, NULL, 0}, /* 2 */ + {NULL, NULL, 0, NULL, 0} +}; +#define NMC_FIELDS_CON_STATUS_DETAILS_ALL "GENERAL,IP,VPN" + +/* GENERAL group is the same as nmc_fields_con_status */ +#define NMC_FIELDS_CON_STATUS_DETAILS_GENERAL_ALL "GROUP,"NMC_FIELDS_CON_STATUS_ALL + +/* IP group is handled by common.c */ + +/* Available fields for VPN group */ +static NmcOutputField nmc_fields_status_details_vpn[] = { + {"GROUP", N_("GROUP"), 9, NULL, 0}, /* 0 */ + {"TYPE", N_("TYPE"), 15, NULL, 0}, /* 1 */ + {"USERNAME", N_("USERNAME"), 15, NULL, 0}, /* 2 */ + {"GATEWAY", N_("GATEWAY"), 25, NULL, 0}, /* 3 */ + {"BANNER", N_("BANNER"), 120, NULL, 0}, /* 4 */ + {"VPN-STATE", N_("VPN-STATE"), 40, NULL, 0}, /* 5 */ + {"CFG", N_("CFG"), 120, NULL, 0}, /* 6 */ + {NULL, NULL, 0, NULL, 0} +}; +#define NMC_FIELDS_CON_STATUS_DETAILS_VPN_ALL "GROUP,TYPE,USERNAME,GATEWAY,BANNER,VPN-STATE,CFG" + + typedef struct { NmCli *nmc; int argc; @@ -153,7 +186,7 @@ usage (void) _("Usage: nmcli con { COMMAND | help }\n" " COMMAND := { list | status | up | down | delete }\n\n" " list [id <id> | uuid <id>]\n" - " status\n" + " status [id <id> | uuid <id> | path <path>]\n" #if WITH_WIMAX " up id <id> | uuid <id> [iface <iface>] [ap <BSSID>] [nsp <name>] [--nowait] [--timeout <timeout>]\n" #else @@ -183,7 +216,6 @@ quit (void) static gboolean nmc_connection_detail (NMConnection *connection, NmCli *nmc) { - NMSetting *setting; GError *error = NULL; GArray *print_settings_array; int i; @@ -229,135 +261,135 @@ nmc_connection_detail (NMConnection *connection, NmCli *nmc) was_output = FALSE; if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[0].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); - if (setting) { - setting_connection_details (setting, nmc); + NMSettingConnection *s_con = nm_connection_get_setting_connection (connection); + if (s_con) { + setting_connection_details (s_con, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[1].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED); - if (setting) { - setting_wired_details (setting, nmc); + NMSettingWired *s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + setting_wired_details (s_wired, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[2].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X); - if (setting) { - setting_802_1X_details (setting, nmc); + NMSetting8021x *s_8021X = nm_connection_get_setting_802_1x (connection); + if (s_8021X) { + setting_802_1X_details (s_8021X, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[3].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS); - if (setting) { - setting_wireless_details (setting, nmc); + NMSettingWireless *s_wireless = nm_connection_get_setting_wireless (connection); + if (s_wireless) { + setting_wireless_details (s_wireless, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[4].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY); - if (setting) { - setting_wireless_security_details (setting, nmc); + NMSettingWirelessSecurity *s_wsec = nm_connection_get_setting_wireless_security (connection); + if (s_wsec) { + setting_wireless_security_details (s_wsec, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[5].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - if (setting) { - setting_ip4_config_details (setting, nmc); + NMSettingIP4Config *s_ip4 = nm_connection_get_setting_ip4_config (connection); + if (s_ip4) { + setting_ip4_config_details (s_ip4, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[6].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); - if (setting) { - setting_ip6_config_details (setting, nmc); + NMSettingIP6Config *s_ip6 = nm_connection_get_setting_ip6_config (connection); + if (s_ip6) { + setting_ip6_config_details (s_ip6, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[7].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_SERIAL); - if (setting) { - setting_serial_details (setting, nmc); + NMSettingSerial *s_serial = nm_connection_get_setting_serial (connection); + if (s_serial) { + setting_serial_details (s_serial, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[8].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_PPP); - if (setting) { - setting_ppp_details (setting, nmc); + NMSettingPPP *s_ppp = nm_connection_get_setting_ppp (connection); + if (s_ppp) { + setting_ppp_details (s_ppp, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[9].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE); - if (setting) { - setting_pppoe_details (setting, nmc); + NMSettingPPPOE *s_pppoe = nm_connection_get_setting_pppoe (connection); + if (s_pppoe) { + setting_pppoe_details (s_pppoe, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[10].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM); - if (setting) { - setting_gsm_details (setting, nmc); + NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (connection); + if (s_gsm) { + setting_gsm_details (s_gsm, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[11].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA); - if (setting) { - setting_cdma_details (setting, nmc); + NMSettingCdma *s_cdma = nm_connection_get_setting_cdma (connection); + if (s_cdma) { + setting_cdma_details (s_cdma, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[12].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH); - if (setting) { - setting_bluetooth_details (setting, nmc); + NMSettingBluetooth *s_bluetooth = nm_connection_get_setting_bluetooth (connection); + if (s_bluetooth) { + setting_bluetooth_details (s_bluetooth, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[13].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH); - if (setting) { - setting_olpc_mesh_details (setting, nmc); + NMSettingOlpcMesh *s_olpc_mesh = nm_connection_get_setting_olpc_mesh (connection); + if (s_olpc_mesh) { + setting_olpc_mesh_details (s_olpc_mesh, nmc); was_output = TRUE; continue; } } if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[14].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN); - if (setting) { - setting_vpn_details (setting, nmc); + NMSettingVPN *s_vpn = nm_connection_get_setting_vpn (connection); + if (s_vpn) { + setting_vpn_details (s_vpn, nmc); was_output = TRUE; continue; } @@ -365,14 +397,41 @@ nmc_connection_detail (NMConnection *connection, NmCli *nmc) #if WITH_WIMAX if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[15].name)) { - setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX); - if (setting) { - setting_wimax_details (setting, nmc); + NMSettingWimax *s_wimax = nm_connection_get_setting_wimax (connection); + if (s_wimax) { + setting_wimax_details (s_wimax, nmc); was_output = TRUE; continue; } } #endif + + if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[16].name)) { + NMSettingInfiniband *s_infiniband = nm_connection_get_setting_infiniband (connection); + if (s_infiniband) { + setting_infiniband_details (s_infiniband, nmc); + was_output = TRUE; + continue; + } + } + + if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[17].name)) { + NMSettingBond *s_bond = nm_connection_get_setting_bond (connection); + if (s_bond) { + setting_bond_details (s_bond, nmc); + was_output = TRUE; + continue; + } + } + + if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[18].name)) { + NMSettingVlan *s_vlan = nm_connection_get_setting_vlan (connection); + if (s_vlan) { + setting_vlan_details (s_vlan, nmc); + was_output = TRUE; + continue; + } + } } if (print_settings_array) @@ -544,19 +603,77 @@ error: return nmc->return_value; } -static void -show_active_connection (gpointer data, gpointer user_data) +static const char * +active_connection_state_to_string (NMActiveConnectionState state) { - NMActiveConnection *active = NM_ACTIVE_CONNECTION (data); - NmCli *nmc = (NmCli *) user_data; - GSList *con_list, *iter; + switch (state) { + case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: + return _("activating"); + case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: + return _("activated"); + case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: + return _("deactivating"); + case NM_ACTIVE_CONNECTION_STATE_UNKNOWN: + default: + return _("unknown"); + } +} + +static const char * +vpn_connection_state_to_string (NMVPNConnectionState state) +{ + switch (state) { + case NM_VPN_CONNECTION_STATE_PREPARE: + return _("VPN connecting (prepare)"); + case NM_VPN_CONNECTION_STATE_NEED_AUTH: + return _("VPN connecting (need authentication)"); + case NM_VPN_CONNECTION_STATE_CONNECT: + return _("VPN connecting"); + case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: + return _("VPN connecting (getting IP configuration)"); + case NM_VPN_CONNECTION_STATE_ACTIVATED: + return _("VPN connected"); + case NM_VPN_CONNECTION_STATE_FAILED: + return _("VPN connection failed"); + case NM_VPN_CONNECTION_STATE_DISCONNECTED: + return _("VPN disconnected"); + default: + return _("unknown"); + } +} + +static NMConnection * +get_connection_for_active (const GSList *con_list, NMActiveConnection *active) +{ + const GSList *iter; + const char *path; + + path = nm_active_connection_get_connection (active); + g_return_val_if_fail (path != NULL, NULL); + + for (iter = con_list; iter; iter = g_slist_next (iter)) { + NMConnection *candidate = NM_CONNECTION (iter->data); + + if (strcmp (nm_connection_get_path (candidate), path) == 0) + return candidate; + } + return NULL; +} + +static gboolean +fill_in_fields_con_status (NMActiveConnection *active, GSList *con_list) +{ + GSList *iter; const char *active_path; NMSettingConnection *s_con; const GPtrArray *devices; GString *dev_str; + NMActiveConnectionState state; int i; + gboolean success = FALSE; active_path = nm_active_connection_get_connection (active); + state = nm_active_connection_get_state (active); /* Get devices of the active connection */ dev_str = g_string_new (NULL); @@ -570,7 +687,6 @@ show_active_connection (gpointer data, gpointer user_data) if (dev_str->len > 0) g_string_truncate (dev_str, dev_str->len - 1); /* Cut off last ',' */ - con_list = nmc->system_connections; for (iter = con_list; iter; iter = g_slist_next (iter)) { NMConnection *connection = (NMConnection *) iter->data; const char *con_path = nm_connection_get_path (connection); @@ -580,410 +696,432 @@ show_active_connection (gpointer data, gpointer user_data) s_con = nm_connection_get_setting_connection (connection); g_assert (s_con != NULL); - /* Obtain field values */ - nmc->allowed_fields[0].value = nm_setting_connection_get_id (s_con); - nmc->allowed_fields[1].value = nm_setting_connection_get_uuid (s_con); - nmc->allowed_fields[2].value = dev_str->str; - nmc->allowed_fields[3].value = nm_active_connection_get_default (active) ? _("yes") : _("no"); - nmc->allowed_fields[4].value = nm_active_connection_get_specific_object (active); - nmc->allowed_fields[5].value = NM_IS_VPN_CONNECTION (active) ? _("yes") : _("no"); - nmc->allowed_fields[6].value = nm_object_get_path (NM_OBJECT (active)); - - nmc->print_fields.flags &= ~NMC_PF_FLAG_MAIN_HEADER_ADD & ~NMC_PF_FLAG_MAIN_HEADER_ONLY & ~NMC_PF_FLAG_FIELD_NAMES; /* Clear header flags */ - print_fields (nmc->print_fields, nmc->allowed_fields); + /* Fill field values */ + nmc_fields_con_status[0].value = nmc_fields_status_details_groups[0].name; + nmc_fields_con_status[1].value = nm_setting_connection_get_id (s_con); + nmc_fields_con_status[2].value = nm_setting_connection_get_uuid (s_con); + nmc_fields_con_status[3].value = dev_str->str; + nmc_fields_con_status[4].value = active_connection_state_to_string (state); + nmc_fields_con_status[5].value = nm_active_connection_get_default (active) ? _("yes") : _("no"); + nmc_fields_con_status[6].value = nm_active_connection_get_default6 (active) ? _("yes") : _("no"); + nmc_fields_con_status[7].value = nm_active_connection_get_specific_object (active); + nmc_fields_con_status[8].value = NM_IS_VPN_CONNECTION (active) ? _("yes") : _("no"); + nmc_fields_con_status[9].value = nm_object_get_path (NM_OBJECT (active)); + nmc_fields_con_status[10].value = nm_active_connection_get_connection (active); + nmc_fields_con_status[11].value = nm_setting_connection_get_zone (s_con); + nmc_fields_con_status[12].value = nm_active_connection_get_master (active); + + success = TRUE; break; } } - g_string_free (dev_str, TRUE); + /* Just free GString here, the char array has to be freed after printing + * (by free_fields_con_status()) */ + g_string_free (dev_str, FALSE); + return success; } -static NMCResultCode -do_connections_status (NmCli *nmc, int argc, char **argv) +static void +free_fields_con_status (void) { - const GPtrArray *active_cons; - GError *error = NULL; - char *fields_str; - char *fields_all = NMC_FIELDS_CON_STATUS_ALL; - char *fields_common = NMC_FIELDS_CON_STATUS_COMMON; - 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; - - nmc->should_wait = FALSE; - - if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) - fields_str = fields_common; - else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) - fields_str = fields_all; - else - fields_str = nmc->required_fields; + /* Just DEVICES string was dynamically allocated */ + g_free ((char *) nmc_fields_con_status[3].value); + nmc_fields_con_status[3].value = NULL; +} - nmc->allowed_fields = nmc_fields_con_status; - nmc->print_fields.indices = parse_output_fields (fields_str, nmc->allowed_fields, &error); +static void +show_active_connection (gpointer data, gpointer user_data) +{ + NMActiveConnection *active = NM_ACTIVE_CONNECTION (data); + NmCli *nmc = (NmCli *) user_data; - if (error) { - if (error->code == 0) - g_string_printf (nmc->return_text, _("Error: 'con status': %s"), error->message); - else - g_string_printf (nmc->return_text, _("Error: 'con status': %s; allowed fields: %s"), error->message, NMC_FIELDS_CON_STATUS_ALL); - g_error_free (error); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto error; - } + fill_in_fields_con_status (active, nmc->system_connections); - if (!nmc_is_nm_running (nmc, &error)) { - if (error) { - g_string_printf (nmc->return_text, _("Error: Can't find out if NetworkManager is running: %s."), error->message); - nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; - g_error_free (error); - } else { - g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); - nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; - } - goto error; - } - - /* Print headers */ - nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ADD | NMC_PF_FLAG_FIELD_NAMES; - nmc->print_fields.header_name = _("Active connections"); + nmc->print_fields.flags &= ~NMC_PF_FLAG_MAIN_HEADER_ADD & ~NMC_PF_FLAG_MAIN_HEADER_ONLY & ~NMC_PF_FLAG_FIELD_NAMES; /* Clear header flags */ print_fields (nmc->print_fields, nmc->allowed_fields); - nmc->get_client (nmc); - active_cons = nm_client_get_active_connections (nmc->client); - if (active_cons && active_cons->len) - g_ptr_array_foreach ((GPtrArray *) active_cons, show_active_connection, (gpointer) nmc); - -error: - return nmc->return_value; + free_fields_con_status (); } -/* -------------------- - * These function should be moved to libnm-glib in the end. - */ -static gboolean -check_ethernet_compatible (NMDeviceEthernet *device, NMConnection *connection, GError **error) +static NMActiveConnection * +find_active_connection (const GPtrArray *active_cons, const GSList *cons, + const char *filter_type, const char *filter_val) { + int i; + const char *s_path, *a_path; + const char *id; + const char *uuid; + NMConnection *con; NMSettingConnection *s_con; - NMSettingWired *s_wired; - const char *connection_type; - gboolean is_pppoe = FALSE; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - connection_type = nm_setting_connection_get_connection_type (s_con); - if ( strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME) - && strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) { - g_set_error (error, 0, 0, - "The connection was not a wired or PPPoE connection."); - return FALSE; - } - if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) - is_pppoe = TRUE; - - s_wired = nm_connection_get_setting_wired (connection); - /* Wired setting is optional for PPPoE */ - if (!is_pppoe && !s_wired) { - g_set_error (error, 0, 0, - "The connection was not a valid wired connection."); - return FALSE; - } - - if (s_wired) { - const GByteArray *mac; - const char *device_mac_str; - struct ether_addr *device_mac = NULL; - - device_mac_str = nm_device_ethernet_get_permanent_hw_address (device); - if (device_mac_str) - device_mac = ether_aton (device_mac_str); - if (!device_mac) { - g_set_error (error, 0, 0, "Invalid device MAC address."); - return FALSE; - } + for (i = 0; active_cons && (i < active_cons->len); i++) { + NMActiveConnection *candidate = g_ptr_array_index (active_cons, i); - mac = nm_setting_wired_get_mac_address (s_wired); - if (mac && memcmp (mac->data, device_mac->ether_addr_octet, ETH_ALEN)) { - g_set_error (error, 0, 0, - "The connection's MAC address did not match this device."); - return FALSE; + s_path = nm_active_connection_get_connection (candidate); + a_path = nm_object_get_path (NM_OBJECT (candidate)); + uuid = nm_active_connection_get_uuid (candidate); + + con = get_connection_for_active (cons, candidate); + s_con = nm_connection_get_setting_connection (con); + g_assert (s_con != NULL); + id = nm_setting_connection_get_id (s_con); + + if (filter_type) { + if ( (strcmp (filter_type, "id") == 0 && strcmp (filter_val, id) == 0) + || (strcmp (filter_type, "uuid") == 0 && strcmp (filter_val, uuid) == 0) + || (strcmp (filter_type, "path") == 0 && strcmp (filter_val, s_path) == 0) + || (strcmp (filter_type, "path") == 0 && strcmp (filter_val, a_path) == 0)) { + return candidate; + } } } + return NULL; +} - // FIXME: check bitrate against device capabilities +typedef struct { + char **array; + guint32 idx; +} FillVPNDataInfo; - return TRUE; +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 -check_wifi_compatible (NMDeviceWifi *device, NMConnection *connection, GError **error) +// 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 * +get_vpn_connection_type (NMConnection *connection) { - NMSettingConnection *s_con; - NMSettingWireless *s_wireless; + const char *type, *p; - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); + /* 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)); + p = strrchr (type, '.'); + return g_strdup (p ? p + 1 : type); +} - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRELESS_SETTING_NAME)) { - g_set_error (error, 0, 0, - "The connection was not a WiFi connection."); - return FALSE; - } +/* VPN parameters can be found at: + * http://git.gnome.org/browse/network-manager-openvpn/tree/src/nm-openvpn-service.h + * http://git.gnome.org/browse/network-manager-vpnc/tree/src/nm-vpnc-service.h + * http://git.gnome.org/browse/network-manager-pptp/tree/src/nm-pptp-service.h + * http://git.gnome.org/browse/network-manager-openconnect/tree/src/nm-openconnect-service.h + * http://git.gnome.org/browse/network-manager-openswan/tree/src/nm-openswan-service.h + * See also 'properties' directory in these plugins. + */ +static const gchar * +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"; + return ""; +} - s_wireless = nm_connection_get_setting_wireless (connection); - if (!s_wireless) { - g_set_error (error, 0, 0, - "The connection was not a valid WiFi connection."); - return FALSE; - } +static const gchar * +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"; + return ""; +} - if (s_wireless) { - const GByteArray *mac; - const char *device_mac_str; - struct ether_addr *device_mac = NULL; +enum VpnDataItem { + VPN_DATA_ITEM_GATEWAY, + VPN_DATA_ITEM_USERNAME +}; - device_mac_str = nm_device_wifi_get_permanent_hw_address (device); - if (device_mac_str) - device_mac = ether_aton (device_mac_str); - if (!device_mac) { - g_set_error (error, 0, 0, "Invalid device MAC address."); - return FALSE; - } +static const gchar * +get_vpn_data_item (NMConnection *connection, enum VpnDataItem vpn_data_item) +{ + const char *key; + char *type = get_vpn_connection_type (connection); - mac = nm_setting_wireless_get_mac_address (s_wireless); - if (mac && memcmp (mac->data, device_mac->ether_addr_octet, ETH_ALEN)) { - g_set_error (error, 0, 0, - "The connection's MAC address did not match this device."); - return FALSE; - } + switch (vpn_data_item) { + case VPN_DATA_ITEM_GATEWAY: + key = find_vpn_gateway_key (type); + break; + case VPN_DATA_ITEM_USERNAME: + key = find_vpn_username_key (type); + break; + default: + key = ""; + break; } + g_free (type); - // FIXME: check channel/freq/band against bands the hardware supports - // FIXME: check encryption against device capabilities - // FIXME: check bitrate against device capabilities - - return TRUE; + return nm_setting_vpn_get_data_item (nm_connection_get_setting_vpn (connection), key); } +/* FIXME end */ static gboolean -check_bt_compatible (NMDeviceBt *device, NMConnection *connection, GError **error) +nmc_active_connection_detail (NMActiveConnection *acon, NmCli *nmc) { - NMSettingConnection *s_con; - NMSettingBluetooth *s_bt; - const GByteArray *array; - char *str; - const char *device_hw_str; - int addr_match = FALSE; - const char *bt_type_str; - guint32 bt_type, bt_capab; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + GError *error = NULL; + GArray *print_groups; + int i; + char *fields_str; + char *fields_all = NMC_FIELDS_CON_STATUS_DETAILS_ALL; + char *fields_common = NMC_FIELDS_CON_STATUS_DETAILS_ALL; + 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 was_output = FALSE; - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); + if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) + fields_str = fields_common; + else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) + fields_str = fields_all; + else + fields_str = nmc->required_fields; - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_BLUETOOTH_SETTING_NAME)) { - g_set_error (error, 0, 0, - "The connection was not a Bluetooth connection."); + print_groups = parse_output_fields (fields_str, nmc_fields_status_details_groups, &error); + if (error) { + if (error->code == 0) + g_string_printf (nmc->return_text, _("Error: 'con status': %s"), error->message); + else + g_string_printf (nmc->return_text, _("Error: 'con status': %s; allowed fields: %s"), error->message, NMC_FIELDS_CON_STATUS_DETAILS_ALL); + g_error_free (error); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return FALSE; } - s_bt = nm_connection_get_setting_bluetooth (connection); - if (!s_bt) { - g_set_error (error, 0, 0, - "The connection was not a valid Bluetooth connection."); - return FALSE; - } + nmc->allowed_fields = nmc_fields_status_details_groups; + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ONLY; + nmc->print_fields.header_name = _("Active connection details"); + nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_CON_STATUS_DETAILS_ALL, nmc->allowed_fields, NULL); + print_fields (nmc->print_fields, nmc->allowed_fields); - array = nm_setting_bluetooth_get_bdaddr (s_bt); - if (!array || (array->len != ETH_ALEN)) { - g_set_error (error, 0, 0, - "The connection did not contain a valid Bluetooth address."); - return FALSE; - } + /* Loop through the groups and print them. */ + for (i = 0; i < print_groups->len; i++) { + int group_idx = g_array_index (print_groups, int, i); - bt_type_str = nm_setting_bluetooth_get_connection_type (s_bt); - g_assert (bt_type_str); + if (nmc->print_output != NMC_PRINT_TERSE && !nmc->multiline_output && was_output) + printf ("\n"); /* Empty line */ - bt_type = NM_BT_CAPABILITY_NONE; - if (!strcmp (bt_type_str, NM_SETTING_BLUETOOTH_TYPE_DUN)) - bt_type = NM_BT_CAPABILITY_DUN; - else if (!strcmp (bt_type_str, NM_SETTING_BLUETOOTH_TYPE_PANU)) - bt_type = NM_BT_CAPABILITY_NAP; + was_output = FALSE; - bt_capab = nm_device_bt_get_capabilities (device); - if (!(bt_type & bt_capab)) { - g_set_error (error, 0, 0, - "The connection was not compatible with the device's capabilities."); - return FALSE; - } + /* GENERAL */ + if (strcasecmp (nmc_fields_status_details_groups[group_idx].name, nmc_fields_status_details_groups[0].name) == 0) { + nmc->allowed_fields = nmc_fields_con_status; + nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_CON_STATUS_DETAILS_GENERAL_ALL, nmc->allowed_fields, NULL); - device_hw_str = nm_device_bt_get_hw_address (device); + /* Print field names */ + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES; + print_fields (nmc->print_fields, nmc->allowed_fields); - str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - array->data[0], array->data[1], array->data[2], - array->data[3], array->data[4], array->data[5]); - addr_match = !strcmp (device_hw_str, str); - g_free (str); + /* Fill in values */ + fill_in_fields_con_status (acon, nmc->system_connections); - return addr_match; -} + /* and print them */ + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX; + print_fields (nmc->print_fields, nmc->allowed_fields); -#if 0 -static gboolean -check_olpc_mesh_compatible (NMDeviceOlpcMesh *device, NMConnection *connection, GError **error) -{ - NMSettingConnection *s_con; - NMSettingOlpcMesh *s_mesh; + free_fields_con_status (); + was_output = TRUE; + } - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + /* IP */ + if (strcasecmp (nmc_fields_status_details_groups[group_idx].name, nmc_fields_status_details_groups[1].name) == 0) { + const GPtrArray *devices; + int j; + + devices = nm_active_connection_get_devices (acon); + for (j = 0; devices && (j < devices->len); j++) { + gboolean b1 = FALSE, b2 = FALSE, b3 = FALSE, b4 = FALSE; + NMDevice *device = g_ptr_array_index (devices, j); + NMIP4Config *cfg4 = nm_device_get_ip4_config (device); + NMIP6Config *cfg6 = nm_device_get_ip6_config (device); + NMDHCP4Config *dhcp4 = nm_device_get_dhcp4_config (device); + NMDHCP6Config *dhcp6 = nm_device_get_dhcp6_config (device); + + b1 = print_ip4_config (cfg4, nmc, "IP4"); + b2 = print_dhcp4_config (dhcp4, nmc, "DHCP4"); + b3 = print_ip6_config (cfg6, nmc, "IP6"); + b4 = print_dhcp6_config (dhcp6, nmc, "DHCP6"); + was_output = was_output || b1 || b2 || b3 || b4; + } + } - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); + /* VPN */ + if (NM_IS_VPN_CONNECTION (acon) && + strcasecmp (nmc_fields_status_details_groups[group_idx].name, nmc_fields_status_details_groups[2].name) == 0) { + NMConnection *con; + NMSettingConnection *s_con; + NMSettingVPN *s_vpn; + NMVPNConnectionState vpn_state; + char *type_str, *banner_str, *vpn_state_str; + const char *username = NULL; + char **vpn_data_array = NULL; + guint32 items_num; + + con = get_connection_for_active (nmc->system_connections, acon); + + s_con = nm_connection_get_setting_connection (con); + g_assert (s_con != NULL); - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_OLPC_MESH_SETTING_NAME)) { - g_set_error (error, 0, 0, - "The connection was not a Mesh connection."); - return FALSE; - } + nmc->allowed_fields = nmc_fields_status_details_vpn; + nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_CON_STATUS_DETAILS_VPN_ALL, nmc->allowed_fields, NULL); - s_mesh = nm_connection_get_setting_olpc_mesh (connection); - if (!s_mesh) { - g_set_error (error, 0, 0, - "The connection was not a valid Mesh connection."); - return FALSE; + /* Print field names */ + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES; + print_fields (nmc->print_fields, nmc->allowed_fields); + + 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); + } + + type_str = get_vpn_connection_type (con); + banner_str = g_strescape (nm_vpn_connection_get_banner (NM_VPN_CONNECTION (acon)), ""); + vpn_state = nm_vpn_connection_get_vpn_state (NM_VPN_CONNECTION (acon)); + vpn_state_str = g_strdup_printf ("%d - %s", vpn_state, vpn_connection_state_to_string (vpn_state)); + + /* Print values */ + set_val_str (nmc->allowed_fields, 0, nmc_fields_status_details_groups[2].name); + set_val_str (nmc->allowed_fields, 1, type_str); + set_val_str (nmc->allowed_fields, 2, username ? username : get_vpn_data_item (con, VPN_DATA_ITEM_USERNAME)); + set_val_str (nmc->allowed_fields, 3, get_vpn_data_item (con, VPN_DATA_ITEM_GATEWAY)); + set_val_str (nmc->allowed_fields, 4, banner_str); + set_val_str (nmc->allowed_fields, 5, vpn_state_str); + set_val_arr (nmc->allowed_fields, 6, (const char **) vpn_data_array); + + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX; + print_fields (nmc->print_fields, nmc->allowed_fields); + + g_free (type_str); + g_free (banner_str); + g_free (vpn_state_str); + g_strfreev (vpn_data_array); + was_output = TRUE; + } } + if (print_groups) + g_array_free (print_groups, FALSE); + return TRUE; } -#endif -#if WITH_WIMAX -static gboolean -check_wimax_compatible (NMDeviceWimax *device, NMConnection *connection, GError **error) +static NMCResultCode +do_connections_status (NmCli *nmc, int argc, char **argv) { - NMSettingConnection *s_con; - NMSettingWimax *s_wimax; - const GByteArray *mac; - const char *device_mac_str; - struct ether_addr *device_mac = NULL; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIMAX_SETTING_NAME)) { - g_set_error (error, 0, 0, - "The connection was not a WiMAX connection."); - return FALSE; - } + const GPtrArray *active_cons; + GError *err = NULL; + GError *err1 = NULL; - s_wimax = nm_connection_get_setting_wimax (connection); - if (!s_wimax) { - g_set_error (error, 0, 0, - "The connection was not a valid WiMAX connection."); - return FALSE; - } + nmc->should_wait = FALSE; - device_mac_str = nm_device_wimax_get_hw_address (device); - if (device_mac_str) - device_mac = ether_aton (device_mac_str); - if (!device_mac) { - g_set_error (error, 0, 0, "Invalid device MAC address."); - return FALSE; + if (!nmc_is_nm_running (nmc, &err)) { + if (err) { + g_string_printf (nmc->return_text, _("Error: Can't find out if NetworkManager is running: %s."), err->message); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + g_error_free (err); + } else { + g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); + nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; + } + goto error; } - mac = nm_setting_wimax_get_mac_address (s_wimax); - if (mac && memcmp (mac->data, device_mac->ether_addr_octet, ETH_ALEN)) { - g_set_error (error, 0, 0, - "The connection's MAC address did not match this device."); - return FALSE; - } + /* Get active connections */ + nmc->get_client (nmc); + active_cons = nm_client_get_active_connections (nmc->client); - return TRUE; -} -#endif + if (argc == 0) { + char *fields_str; + char *fields_all = NMC_FIELDS_CON_STATUS_ALL; + char *fields_common = NMC_FIELDS_CON_STATUS_COMMON; + 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; + + if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) + fields_str = fields_common; + else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) + fields_str = fields_all; + else + fields_str = nmc->required_fields; -static gboolean -check_modem_compatible (NMDeviceModem *device, NMConnection *connection, GError **error) -{ - NMSettingConnection *s_con; - NMSettingGsm *s_gsm; - NMSettingCdma *s_cdma; - NMDeviceModemCapabilities caps = NM_DEVICE_MODEM_CAPABILITY_NONE; + nmc->allowed_fields = nmc_fields_con_status + 1 ; + nmc->print_fields.indices = parse_output_fields (fields_str, nmc->allowed_fields, &err1); + if (err1) + goto error; - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + /* Print headers */ + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ADD | NMC_PF_FLAG_FIELD_NAMES; + nmc->print_fields.header_name = _("Active connections"); + print_fields (nmc->print_fields, nmc->allowed_fields); - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); + if (active_cons && active_cons->len) + g_ptr_array_foreach ((GPtrArray *) active_cons, show_active_connection, (gpointer) nmc); + } else { + while (argc > 0) { + if ( strcmp (*argv, "id") == 0 + || strcmp (*argv, "uuid") == 0 + || strcmp (*argv, "path") == 0) { + const char *selector = *argv; + NMActiveConnection *acon; - /* Figure out what the modem supports */ - caps = nm_device_modem_get_current_capabilities (device); - if (caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) { - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_GSM_SETTING_NAME)) { - g_set_error (error, 0, 0, - "The connection was not a GSM connection."); - return FALSE; - } + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + return nmc->return_value; + } + if (!nmc->mode_specified) + nmc->multiline_output = TRUE; /* multiline mode is default for 'con status id|uuid|path' */ - s_gsm = nm_connection_get_setting_gsm (connection); - if (!s_gsm) { - g_set_error (error, 0, 0, - "The connection was not a valid GSM connection."); - return FALSE; - } - } else if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) { - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_CDMA_SETTING_NAME)) { - g_set_error (error, 0, 0, - "The connection was not a CDMA connection."); - return FALSE; - } + acon = find_active_connection (active_cons, nmc->system_connections, selector, *argv); + if (acon) { + nmc_active_connection_detail (acon, nmc); + } else { + g_string_printf (nmc->return_text, _("Error: '%s' is not an active connection."), *argv); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + } + break; + } else { + g_string_printf (nmc->return_text, _("Error: unknown parameter: %s"), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + } - s_cdma = nm_connection_get_setting_cdma (connection); - if (!s_cdma) { - g_set_error (error, 0, 0, - "The connection was not a valid CDMA connection."); - return FALSE; + argc--; + argv++; } } - return TRUE; -} - -static gboolean -nm_device_is_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) -{ - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - - if (NM_IS_DEVICE_ETHERNET (device)) - return check_ethernet_compatible (NM_DEVICE_ETHERNET (device), connection, error); - else if (NM_IS_DEVICE_WIFI (device)) - return check_wifi_compatible (NM_DEVICE_WIFI (device), connection, error); - else if (NM_IS_DEVICE_BT (device)) - return check_bt_compatible (NM_DEVICE_BT (device), connection, error); -// else if (NM_IS_DEVICE_OLPC_MESH (device)) -// return check_olpc_mesh_compatible (NM_DEVICE_OLPC_MESH (device), connection, error); -#if WITH_WIMAX - else if (NM_IS_DEVICE_WIMAX (device)) - return check_wimax_compatible (NM_DEVICE_WIMAX (device), connection, error); -#endif - else if (NM_IS_DEVICE_MODEM (device)) - return check_modem_compatible (NM_DEVICE_MODEM (device), connection, error); - - g_set_error (error, 0, 0, "unhandled device type '%s'", G_OBJECT_TYPE_NAME (device)); - return FALSE; +error: + if (err1) { + if (err1->code == 0) + g_string_printf (nmc->return_text, _("Error: 'con status': %s"), err1->message); + else + g_string_printf (nmc->return_text, _("Error: 'con status': %s; allowed fields: %s"), err1->message, NMC_FIELDS_CON_STATUS_ALL); + g_error_free (err1); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + } + return nmc->return_value; } -/* -------------------- */ - static NMActiveConnection * get_default_active_connection (NmCli *nmc, NMDevice **device) { @@ -1095,11 +1233,11 @@ find_device_for_connection (NmCli *nmc, if (iface) { const char *dev_iface = nm_device_get_iface (dev); if ( !strcmp (dev_iface, iface) - && nm_device_is_connection_compatible (dev, connection, NULL)) { + && nm_device_connection_compatible (dev, connection, NULL)) { found_device = dev; } } else { - if (nm_device_is_connection_compatible (dev, connection, NULL)) { + if (nm_device_connection_compatible (dev, connection, NULL)) { found_device = dev; } } @@ -1158,45 +1296,6 @@ find_device_for_connection (NmCli *nmc, } static const char * -active_connection_state_to_string (NMActiveConnectionState state) -{ - switch (state) { - case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: - return _("activating"); - case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: - return _("activated"); - case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: - return _("deactivating"); - case NM_ACTIVE_CONNECTION_STATE_UNKNOWN: - default: - return _("unknown"); - } -} - -static const char * -vpn_connection_state_to_string (NMVPNConnectionState state) -{ - switch (state) { - case NM_VPN_CONNECTION_STATE_PREPARE: - return _("VPN connecting (prepare)"); - case NM_VPN_CONNECTION_STATE_NEED_AUTH: - return _("VPN connecting (need authentication)"); - case NM_VPN_CONNECTION_STATE_CONNECT: - return _("VPN connecting"); - case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: - return _("VPN connecting (getting IP configuration)"); - case NM_VPN_CONNECTION_STATE_ACTIVATED: - return _("VPN connected"); - case NM_VPN_CONNECTION_STATE_FAILED: - return _("VPN connection failed"); - case NM_VPN_CONNECTION_STATE_DISCONNECTED: - return _("VPN disconnected"); - default: - return _("unknown"); - } -} - -static const char * vpn_connection_state_reason_to_string (NMVPNConnectionStateReason reason) { switch (reason) { @@ -1341,6 +1440,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv) gboolean id_specified = FALSE; gboolean wait = TRUE; GError *error = NULL; + gboolean is_virtual = FALSE; /* Set default timeout for connection activation. It can take quite a long time. * Using 90 seconds. @@ -1444,9 +1544,13 @@ do_connection_up (NmCli *nmc, int argc, char **argv) g_assert (s_con); con_type = nm_setting_connection_get_connection_type (s_con); - device_found = find_device_for_connection (nmc, connection, iface, ap, nsp, &device, &spec_object, &error); + if ( nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME) + || nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) + is_virtual = TRUE; - if (!device_found) { + device_found = find_device_for_connection (nmc, connection, iface, ap, nsp, &device, &spec_object, &error); + /* Virtual connection may not have their interfaces created yet */ + if (!device_found && !is_virtual) { if (error) g_string_printf (nmc->return_text, _("Error: No suitable device found: %s."), error->message); else @@ -1563,6 +1667,27 @@ error: return nmc->return_value; } +static void +delete_cb (NMRemoteConnection *con, GError *err, gpointer user_data) +{ + NmCli *nmc = (NmCli *) user_data; + + if (err) { + g_string_printf (nmc->return_text, _("Error: Connection deletion failed: %s"), err->message); + nmc->return_value = NMC_RESULT_ERROR_CON_DEL; + } + quit (); +} + +static void +connection_removed_cb (NMRemoteConnection *con, gpointer user_data) +{ + NmCli *nmc = (NmCli *) user_data; + + nmc->return_value = NMC_RESULT_SUCCESS; + quit (); +} + static NMCResultCode do_connection_delete (NmCli *nmc, int argc, char **argv) { @@ -1571,8 +1696,6 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) const char *id = NULL; GError *error = NULL; - nmc->should_wait = FALSE; - while (argc > 0) { if (strcmp (*argv, "id") == 0 || strcmp (*argv, "uuid") == 0) { selector = *argv; @@ -1616,10 +1739,22 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) goto error; } + /* We need to wait a bit so that nmcli's permissions can be queried. + * We will exit either on "Removed" signal or when D-Bus return (error) + * message is received. + */ + nmc->should_wait = TRUE; + + /* Connect to "Removed" signal to be able to exit when connection was removed */ + g_signal_connect (connection, NM_REMOTE_CONNECTION_REMOVED, G_CALLBACK (connection_removed_cb), nmc); + /* Delete the connection */ - nm_remote_connection_delete (NM_REMOTE_CONNECTION (connection), NULL, NULL); + nm_remote_connection_delete (NM_REMOTE_CONNECTION (connection), delete_cb, nmc); + + return nmc->return_value; error: + nmc->should_wait = FALSE; return nmc->return_value; } |