diff options
| author | Michael Biebl <biebl@debian.org> | 2019-03-26 23:25:23 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2019-03-26 23:25:23 +0100 |
| commit | 9a6dcbf895f9da01768e64b73cec88c16157d91e (patch) | |
| tree | a359958930d731e9f1b59344642e10754419fe84 /clients/cli/connections.c | |
| parent | 964ae8cc391520440cf5aa13e2b9cc34850ea6c2 (diff) | |
New upstream version 1.16.0 upstream/1.16.0
Diffstat (limited to 'clients/cli/connections.c')
| -rw-r--r-- | clients/cli/connections.c | 477 |
1 files changed, 318 insertions, 159 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 8a10691e..6db44f87 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -22,14 +22,13 @@ #include "connections.h" #include <stdio.h> -#include <string.h> #include <stdlib.h> #include <unistd.h> -#include <errno.h> #include <signal.h> #include <netinet/ether.h> #include <readline/readline.h> #include <readline/history.h> +#include <fcntl.h> #include "nm-client-utils.h" #include "nm-vpn-helpers.h" @@ -140,15 +139,68 @@ active_connection_get_state_ord (NMActiveConnection *active) return -1; } -static int -active_connection_cmp (NMActiveConnection *ac_a, NMActiveConnection *ac_b) +int +nmc_active_connection_cmp (NMActiveConnection *ac_a, NMActiveConnection *ac_b) { + NMSettingIPConfig *s_ip; + NMRemoteConnection *conn; + NMIPConfig *da_ip; + NMIPConfig *db_ip; + int da_num_addrs; + int db_num_addrs; + int cmp = 0; + + /* Non-active sort last. */ NM_CMP_SELF (ac_a, ac_b); NM_CMP_DIRECT (active_connection_get_state_ord (ac_b), active_connection_get_state_ord (ac_a)); - NM_CMP_DIRECT_STRCMP0 (nm_active_connection_get_id (ac_a), nm_active_connection_get_id (ac_b)); - NM_CMP_DIRECT_STRCMP0 (nm_active_connection_get_connection_type (ac_a), nm_active_connection_get_connection_type (ac_b)); - NM_CMP_DIRECT_STRCMP0 (nm_object_get_path (NM_OBJECT (ac_a)), nm_object_get_path (NM_OBJECT (ac_b))); + + /* Shared connections (likely hotspots) go on the top if possible */ + conn = nm_active_connection_get_connection (ac_a); + s_ip = conn ? nm_connection_get_setting_ip6_config (NM_CONNECTION (conn)) : NULL; + if (s_ip && strcmp (nm_setting_ip_config_get_method (s_ip), NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) + cmp++; + conn = nm_active_connection_get_connection (ac_b); + s_ip = conn ? nm_connection_get_setting_ip6_config (NM_CONNECTION (conn)) : NULL; + if (s_ip && strcmp (nm_setting_ip_config_get_method (s_ip), NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) + cmp--; + NM_CMP_RETURN (cmp); + + conn = nm_active_connection_get_connection (ac_a); + s_ip = conn ? nm_connection_get_setting_ip4_config (NM_CONNECTION (conn)) : NULL; + if (s_ip && strcmp (nm_setting_ip_config_get_method (s_ip), NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) + cmp++; + conn = nm_active_connection_get_connection (ac_b); + s_ip = conn ? nm_connection_get_setting_ip4_config (NM_CONNECTION (conn)) : NULL; + if (s_ip && strcmp (nm_setting_ip_config_get_method (s_ip), NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) + cmp--; + NM_CMP_RETURN (cmp); + + /* VPNs go next */ + NM_CMP_DIRECT (!!nm_active_connection_get_vpn (ac_a), + !!nm_active_connection_get_vpn (ac_b)); + + /* Default devices are prioritized */ + NM_CMP_DIRECT (nm_active_connection_get_default (ac_a), + nm_active_connection_get_default (ac_b)); + + /* Default IPv6 devices are prioritized */ + NM_CMP_DIRECT (nm_active_connection_get_default6 (ac_a), + nm_active_connection_get_default6 (ac_b)); + + /* Sort by number of addresses. */ + da_ip = nm_active_connection_get_ip4_config (ac_a); + da_num_addrs = da_ip ? nm_ip_config_get_addresses (da_ip)->len : 0; + db_ip = nm_active_connection_get_ip4_config (ac_b); + db_num_addrs = db_ip ? nm_ip_config_get_addresses (db_ip)->len : 0; + + da_ip = nm_active_connection_get_ip6_config (ac_a); + da_num_addrs += da_ip ? nm_ip_config_get_addresses (da_ip)->len : 0; + db_ip = nm_active_connection_get_ip6_config (ac_b); + db_num_addrs += db_ip ? nm_ip_config_get_addresses (db_ip)->len : 0; + + NM_CMP_DIRECT (da_num_addrs, db_num_addrs); + return 0; } @@ -742,6 +794,7 @@ const NmcMetaGenericInfo *const metagen_con_active_vpn[_NMC_GENERIC_INFO_TYPE_CO NM_SETTING_IP4_CONFIG_SETTING_NAME","\ NM_SETTING_IP6_CONFIG_SETTING_NAME","\ NM_SETTING_SERIAL_SETTING_NAME","\ + NM_SETTING_WIFI_P2P_SETTING_NAME","\ NM_SETTING_PPP_SETTING_NAME","\ NM_SETTING_PPPOE_SETTING_NAME","\ NM_SETTING_ADSL_SETTING_NAME","\ @@ -769,6 +822,7 @@ const NmcMetaGenericInfo *const metagen_con_active_vpn[_NMC_GENERIC_INFO_TYPE_CO NM_SETTING_VXLAN_SETTING_NAME"," \ NM_SETTING_WPAN_SETTING_NAME","\ NM_SETTING_6LOWPAN_SETTING_NAME","\ + NM_SETTING_WIREGUARD_SETTING_NAME","\ NM_SETTING_PROXY_SETTING_NAME"," \ NM_SETTING_TC_CONFIG_SETTING_NAME"," \ NM_SETTING_SRIOV_SETTING_NAME"," \ @@ -991,8 +1045,10 @@ usage_connection_add (void) " [source-port-min <0-65535>]\n" " [source-port-max <0-65535>]\n" " [destination-port <0-65535>]\n\n" - " wpan: [short-addr <0x0000-0xffff>]\n\n" - " [pan-id <0x0000-0xffff>]\n\n" + " wpan: [short-addr <0x0000-0xffff>]\n" + " [pan-id <0x0000-0xffff>]\n" + " [page <default|0-31>]\n" + " [channel <default|0-26>]\n" " [mac <MAC address>]\n\n" " 6lowpan: dev <parent device (connection UUID, ifname, or MAC)>\n" " dummy:\n\n" @@ -1141,12 +1197,20 @@ construct_header_name (const char *base, const char *spec) } static int -get_ac_for_connection_cmp (gconstpointer pa, gconstpointer pb, gpointer user_data) +get_ac_for_connection_cmp (gconstpointer pa, gconstpointer pb) { NMActiveConnection *ac_a = *((NMActiveConnection *const*) pa); NMActiveConnection *ac_b = *((NMActiveConnection *const*) pb); - return active_connection_cmp (ac_a, ac_b); + NM_CMP_RETURN (nmc_active_connection_cmp (ac_a, ac_b)); + NM_CMP_DIRECT_STRCMP0 (nm_active_connection_get_id (ac_a), + nm_active_connection_get_id (ac_b)); + NM_CMP_DIRECT_STRCMP0 (nm_active_connection_get_connection_type (ac_a), + nm_active_connection_get_connection_type (ac_b)); + NM_CMP_DIRECT_STRCMP0 (nm_object_get_path (NM_OBJECT (ac_a)), + nm_object_get_path (NM_OBJECT (ac_b))); + + g_return_val_if_reached (0); } static NMActiveConnection * @@ -1172,7 +1236,7 @@ get_ac_for_connection (const GPtrArray *active_cons, NMConnection *connection, G } if (result) { - g_ptr_array_sort_with_data (result, get_ac_for_connection_cmp, NULL); + g_ptr_array_sort (result, get_ac_for_connection_cmp); best_candidate = result->pdata[0]; } @@ -1629,12 +1693,10 @@ con_show_get_items_cmp (gconstpointer pa, gconstpointer pb, gpointer user_data) switch (item) { case NMC_SORT_ACTIVE: - NM_CMP_DIRECT (active_connection_get_state_ord (ac_b), - active_connection_get_state_ord (ac_a)); + NM_CMP_RETURN (nmc_active_connection_cmp (ac_b, ac_a)); break; case NMC_SORT_ACTIVE_INV: - NM_CMP_DIRECT (active_connection_get_state_ord (ac_a), - active_connection_get_state_ord (ac_b)); + NM_CMP_RETURN (nmc_active_connection_cmp (ac_a, ac_b)); break; case NMC_SORT_TYPE: @@ -1673,13 +1735,12 @@ con_show_get_items_cmp (gconstpointer pa, gconstpointer pb, gpointer user_data) nm_connection_get_uuid (c_b)); NM_CMP_DIRECT_STRCMP0 (nm_connection_get_path (c_a), nm_connection_get_path (c_b)); - - /* This line is not expected to be reached, because there shouldn't be two - * different connections with the same path. Anyway, fall-through and compare by - * active connections... */ } - return active_connection_cmp (ac_a, ac_b); + NM_CMP_DIRECT_STRCMP0 (nm_object_get_path (NM_OBJECT (ac_a)), + nm_object_get_path (NM_OBJECT (ac_b))); + + g_return_val_if_reached (0); } static GPtrArray * @@ -1755,7 +1816,7 @@ con_show_get_items (NmCli *nmc, gboolean active_only, gboolean show_active_field * color (activated or not) based on primary_active. */ if (!row_data) { /* this is unexpected. The active connection references a connection that - * seemingly no longer exists. It's a bug in libnm. Add a row nontheless. */ + * seemingly no longer exists. It's a bug in libnm. Add a row nonetheless. */ row_data = _metagen_con_show_row_data_new_for_connection (c, show_active_fields); g_hash_table_insert (row_hash, c, row_data); } @@ -1985,8 +2046,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv) } } - /* Optionally start paging the output. */ - nmc_terminal_spawn_pager (&nmc->nmc_config); + nm_cli_spawn_pager (nmc); items = con_show_get_items (nmc, active_only, show_active_fields, order); g_ptr_array_add (items, NULL); @@ -2287,7 +2347,7 @@ find_device_for_connection (NmCli *nmc, continue; if (!nm_device_connection_compatible (dev, connection, error)) { - g_prefix_error (error, _("device '%s' not compatible with connection '%s':"), + g_prefix_error (error, _("device '%s' not compatible with connection '%s': "), iface, nm_setting_connection_get_id (s_con)); return FALSE; } @@ -2340,6 +2400,43 @@ typedef struct { NMActiveConnection *active; } ActivateConnectionInfo; +static void +active_connection_hint (GString *return_text, + NMActiveConnection *active, + NMDevice *device) +{ + NMRemoteConnection *connection; + nm_auto_free_gstring GString *hint = NULL; + const GPtrArray *devices; + guint i; + + if (!active) + return; + + if (!nm_streq (NM_CONFIG_DEFAULT_LOGGING_BACKEND, "journal")) + return; + + connection = nm_active_connection_get_connection (active); + g_return_if_fail (connection); + + hint = g_string_new ("journalctl -xe "); + g_string_append_printf (hint, "NM_CONNECTION=%s", + nm_connection_get_uuid (NM_CONNECTION (connection))); + + if (device) + g_string_append_printf (hint, " + NM_DEVICE=%s", nm_device_get_iface (device)); + else { + devices = nm_active_connection_get_devices (active); + for (i = 0; i < devices->len; i++) { + g_string_append_printf (hint, " + NM_DEVICE=%s", + nm_device_get_iface (NM_DEVICE (g_ptr_array_index (devices, i)))); + } + } + + g_string_append (return_text, "\n"); + g_string_append_printf (return_text, _("Hint: use '%s' to get more details."), hint->str); +} + static void activate_connection_info_finish (ActivateConnectionInfo *info); static void @@ -2368,6 +2465,7 @@ check_activated (ActivateConnectionInfo *info) nm_assert (reason); g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s"), reason); + active_connection_hint (nmc->return_text, info->active, info->device); nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION; activate_connection_info_finish (info); break; @@ -2375,7 +2473,7 @@ check_activated (ActivateConnectionInfo *info) if (nmc->secret_agent) { NMRemoteConnection *connection = nm_active_connection_get_connection (info->active); - nm_secret_agent_simple_enable (NM_SECRET_AGENT_SIMPLE (nmc->secret_agent), + nm_secret_agent_simple_enable (nmc->secret_agent, nm_connection_get_path (NM_CONNECTION (connection))); } break; @@ -2490,6 +2588,7 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s"), error->message); g_error_free (error); + active_connection_hint (nmc->return_text, info->active, info->device); nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION; activate_connection_info_finish (info); } else { @@ -2676,7 +2775,6 @@ nmc_activate_connection (NmCli *nmc, g_hash_table_destroy (nmc->pwds_hash); nmc->pwds_hash = pwds_hash; - /* Create secret agent */ nmc->secret_agent = nm_secret_agent_simple_new ("nmcli-connect"); if (nmc->secret_agent) { g_signal_connect (nmc->secret_agent, @@ -2726,14 +2824,14 @@ do_connection_up (NmCli *nmc, int argc, char **argv) argc_ptr = &argc; if (argc == 0 && nmc->ask) { - char *line; + gs_free char *line = NULL; /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); - line = nmc_readline (PROMPT_CONNECTION); + line = nmc_readline (&nmc->nmc_config, + PROMPT_CONNECTION); nmc_string_to_arg_array (line, NULL, TRUE, &arg_arr, &arg_num); - g_free (line); argv_ptr = &arg_arr; argc_ptr = &arg_num; } @@ -2906,6 +3004,7 @@ connection_cb_info_finish (ConnectionCbInfo *info, gpointer obj) nm_clear_g_source (&info->timeout_id); nm_clear_g_cancellable (&info->cancellable); + g_ptr_array_free (info->obj_list, TRUE); g_signal_handlers_disconnect_by_func (info->nmc->client, connection_removed_cb, info); @@ -2980,9 +3079,11 @@ do_connection_down (NmCli *nmc, int argc, char **argv) g_assert (!nmc->complete); if (nmc->ask) { - char *line = nmc_readline (PROMPT_ACTIVE_CONNECTIONS); + gs_free char *line = NULL; + + line = nmc_readline (&nmc->nmc_config, + PROMPT_ACTIVE_CONNECTIONS); nmc_string_to_arg_array (line, NULL, TRUE, &arg_arr, &arg_num); - g_free (line); arg_ptr = arg_arr; } if (arg_num == 0) { @@ -3204,7 +3305,7 @@ get_valid_properties_string (const NMMetaSettingValidPartItem *const*array, str = g_string_sized_new (1024); for (i = 0; i < 2; i++, iter = array_slv) { - for(; !full_match && iter && *iter; iter++) { + for (; !full_match && iter && *iter; iter++) { const NMMetaSettingInfoEditor *setting_info = (*iter)->setting_info; if ( !(g_str_has_prefix (setting_info->general->setting_name, prefix)) @@ -3850,9 +3951,13 @@ reset_options (void) } static gboolean -set_property (NMConnection *connection, - const char *setting_name, const char *property, const char *value, - char modifier, GError **error) +set_property (NMClient *client, + NMConnection *connection, + const char *setting_name, + const char *property, + const char *value, + char modifier, + GError **error) { gs_free char *property_name = NULL, *value_free = NULL; NMSetting *setting; @@ -3885,7 +3990,7 @@ set_property (NMConnection *connection, value = value_free = g_strdup (value); nmc_setting_reset_property (setting, property_name, NULL); } - if (!nmc_setting_set_property (setting, property_name, value, &local)) { + if (!nmc_setting_set_property (client, setting, property_name, value, &local)) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("Error: failed to modify %s.%s: %s."), setting_name, property, local->message); @@ -3937,7 +4042,7 @@ set_option (NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abst if (option && option->check_and_set) { return option->check_and_set (nmc, connection, option, value, error); } else if (value) { - return set_property (connection, setting_name, property_name, + return set_property (nmc->client, connection, setting_name, property_name, value, inf_flags & NM_META_PROPERTY_INF_FLAG_MULTI ? '+' : '\0', error); } else if (inf_flags & NM_META_PROPERTY_INF_FLAG_REQD) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, @@ -3985,7 +4090,7 @@ con_settings (NMConnection *connection, const NMMetaSettingValidPartItem *const* /* * Make sure all required settings are in place (should be called when - * it's possible that a type is aready set). + * it's possible that a type is already set). */ static void ensure_settings (NMConnection *connection, const NMMetaSettingValidPartItem *const*item) @@ -4059,7 +4164,7 @@ set_connection_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, co } if (slave_type) { - if (!set_property (con, NM_SETTING_CONNECTION_SETTING_NAME, + if (!set_property (nmc->client, con, NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, '\0', error)) { return FALSE; @@ -4076,7 +4181,7 @@ set_connection_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, co NM_SETTING_CONNECTION_INTERFACE_NAME); } - if (!set_property (con, option->setting_info->general->setting_name, option->property, value, '\0', error)) + if (!set_property (nmc->client, con, option->setting_info->general->setting_name, option->property, value, '\0', error)) return FALSE; if (!con_settings (con, &type_settings, &slv_settings, error)) @@ -4105,7 +4210,7 @@ set_connection_iface (NmCli *nmc, NMConnection *con, const OptionInfo *option, c } } - return set_property (con, option->setting_info->general->setting_name, option->property, value, '\0', error); + return set_property (nmc->client, con, option->setting_info->general->setting_name, option->property, value, '\0', error); } static gboolean @@ -4128,13 +4233,13 @@ set_connection_master (NmCli *nmc, NMConnection *con, const OptionInfo *option, connections = nm_client_get_connections (nmc->client); value = normalized_master_for_slave (connections, value, slave_type, &slave_type); - if (!set_property (con, NM_SETTING_CONNECTION_SETTING_NAME, + if (!set_property (nmc->client, con, NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, '\0', error)) { return FALSE; } - return set_property (con, option->setting_info->general->setting_name, option->property, value, '\0', error); + return set_property (nmc->client, con, option->setting_info->general->setting_name, option->property, value, '\0', error); } static gboolean @@ -4248,7 +4353,7 @@ set_bluetooth_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, con return FALSE; } - return set_property (con, option->setting_info->general->setting_name, option->property, value, '\0', error); + return set_property (nmc->client, con, option->setting_info->general->setting_name, option->property, value, '\0', error); } static gboolean @@ -4267,7 +4372,7 @@ set_ip4_address (NmCli *nmc, NMConnection *con, const OptionInfo *option, const NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); } - return set_property (con, option->setting_info->general->setting_name, option->property, value, + return set_property (nmc->client, con, option->setting_info->general->setting_name, option->property, value, '+', error); } @@ -4287,7 +4392,7 @@ set_ip6_address (NmCli *nmc, NMConnection *con, const OptionInfo *option, const NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, NULL); } - return set_property (con, option->setting_info->general->setting_name, option->property, value, + return set_property (nmc->client, con, option->setting_info->general->setting_name, option->property, value, '+', error); } @@ -4573,7 +4678,7 @@ nmc_read_connection_properties (NmCli *nmc, if (!*argc && nmc->complete) complete_property (setting, strv[1], value ?: "", connection); - if (!set_property (connection, setting_name, strv[1], value, modifier, error)) + if (!set_property (nmc->client, connection, setting_name, strv[1], value, modifier, error)) return FALSE; } else { NMMetaSettingType s; @@ -4853,7 +4958,9 @@ ask_option (NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abst g_print (_("You can specify this option more than once. Press <Enter> when you're done.\n")); again: - value = nmc_readline ("%s", prompt); + value = nmc_readline (&nmc->nmc_config, + "%s", + prompt); if (multi && !value) return; @@ -4943,23 +5050,25 @@ questionnaire_mandatory (NmCli *nmc, NMConnection *connection) } static gboolean -want_provide_opt_args (const char *type, int num) +want_provide_opt_args (const NmcConfig *nmc_config, + const char *type, + guint num) { - char *answer; - gboolean ret = TRUE; + gs_free char *answer = NULL; /* Ask for optional arguments. */ g_print (ngettext ("There is %d optional setting for %s.\n", - "There are %d optional settings for %s.\n", num), - num, type); - answer = nmc_readline (ngettext ("Do you want to provide it? %s", - "Do you want to provide them? %s", num), + "There are %d optional settings for %s.\n", + num), + (int) num, + type); + answer = nmc_readline (nmc_config, + ngettext ("Do you want to provide it? %s", + "Do you want to provide them? %s", + num), prompt_yes_no (TRUE, NULL)); - answer = answer ? g_strstrip (answer) : NULL; - if (answer && !matches (answer, WORD_YES)) - ret = FALSE; - g_free (answer); - return ret; + nm_strstrip (answer); + return !answer || matches (answer, WORD_YES); } static gboolean @@ -5029,7 +5138,9 @@ again: /* Now ask for the settings. */ if ( already_confirmed - || want_provide_opt_args (_(setting_info->pretty_name), infos->len)) { + || want_provide_opt_args (&nmc->nmc_config, + _(setting_info->pretty_name), + infos->len)) { ask_option (nmc, connection, infos->pdata[0]); already_confirmed = TRUE; /* asking for an option may enable other options. Create the list again. */ @@ -5059,7 +5170,7 @@ do_connection_add (NmCli *nmc, int argc, char **argv) next_arg (nmc, &argc, &argv, NULL); - rl_attempted_completion_function = (rl_completion_func_t *) nmcli_con_add_tab_completion; + rl_attempted_completion_function = nmcli_con_add_tab_completion; nmc->return_value = NMC_RESULT_SUCCESS; @@ -6615,7 +6726,7 @@ progress_activation_editor_cb (gpointer user_data) NMRemoteConnection *connection; connection = nm_active_connection_get_connection (ac); - nm_secret_agent_simple_enable (NM_SECRET_AGENT_SIMPLE (info->nmc->secret_agent), + nm_secret_agent_simple_enable (info->nmc->secret_agent, nm_object_get_path (NM_OBJECT (connection))); } @@ -6656,6 +6767,10 @@ activate_connection_editor_cb (GObject *client, } else g_object_unref (active); } + + nm_g_object_unref (info->device); + g_free (info); + set_info_and_signal_editor_thread (error, monitor_ac_info); g_clear_error (&error); } @@ -6749,20 +6864,16 @@ is_connection_dirty (NMConnection *connection, NMRemoteConnection *remote) } static gboolean -confirm_quit (void) +confirm_quit (const NmcConfig *nmc_config) { - char *answer; - gboolean want_quit = FALSE; + gs_free char *answer = NULL; - answer = nmc_readline (_("The connection is not saved. " + answer = nmc_readline (nmc_config, + _("The connection is not saved. " "Do you really want to quit? %s"), prompt_yes_no (FALSE, NULL)); - answer = answer ? g_strstrip (answer) : NULL; - if (answer && matches (answer, WORD_YES)) - want_quit = TRUE; - - g_free (answer); - return want_quit; + nm_strstrip (answer); + return (answer && matches (answer, WORD_YES)); } /* @@ -6797,7 +6908,7 @@ property_edit_submenu (NmCli *nmc, gboolean removed; gboolean dirty; - /* Get the remote connection again, it may have disapeared */ + /* Get the remote connection again, it may have disappeared */ removed = refresh_remote_connection (rem_con_weak, rem_con); if (removed) { g_print (_("The connection profile has been removed from another client. " @@ -6810,10 +6921,13 @@ property_edit_submenu (NmCli *nmc, if (nmc->editor_status_line) editor_show_status_line (connection, dirty, temp_changes); - cmd_property_user = nmc_readline ("%s", prompt); + cmd_property_user = nmc_readline (&nmc->nmc_config, + "%s", + prompt); if (!cmd_property_user || !*cmd_property_user) continue; - cmdsub = parse_editor_sub_cmd (g_strstrip (cmd_property_user), &cmd_property_arg); + g_strstrip (cmd_property_user); + cmdsub = parse_editor_sub_cmd (cmd_property_user, &cmd_property_arg); switch (cmdsub) { case NMC_EDITOR_SUB_CMD_SET: @@ -6834,7 +6948,9 @@ property_edit_submenu (NmCli *nmc, g_print (_("Allowed values for '%s' property: %s\n"), prop_name, avals_str); } - prop_val_user = nmc_readline (_("Enter '%s' value: "), prop_name); + prop_val_user = nmc_readline (&nmc->nmc_config, + _("Enter '%s' value: "), + prop_name); } else prop_val_user = g_strdup (cmd_property_arg); @@ -6846,7 +6962,7 @@ property_edit_submenu (NmCli *nmc, nmc_property_set_default_value (curr_setting, prop_name); } - set_result = nmc_setting_set_property (curr_setting, prop_name, prop_val_user, &tmp_err); + set_result = nmc_setting_set_property (nmc->client, curr_setting, prop_name, prop_val_user, &tmp_err); if (!set_result) { g_print (_("Error: failed to set '%s' property: %s\n"), prop_name, tmp_err->message); g_clear_error (&tmp_err); @@ -6862,12 +6978,14 @@ property_edit_submenu (NmCli *nmc, case NMC_EDITOR_SUB_CMD_CHANGE: rl_startup_hook = nmc_rl_set_deftext; nmc_rl_pre_input_deftext = nmc_setting_get_property_parsable (curr_setting, prop_name, NULL); - prop_val_user = nmc_readline (_("Edit '%s' value: "), prop_name); + prop_val_user = nmc_readline (&nmc->nmc_config, + _("Edit '%s' value: "), + prop_name); nmc_property_get_gvalue (curr_setting, prop_name, &prop_g_value); nmc_property_set_default_value (curr_setting, prop_name); - if (!nmc_setting_set_property (curr_setting, prop_name, prop_val_user, &tmp_err)) { + if (!nmc_setting_set_property (nmc->client, curr_setting, prop_name, prop_val_user, &tmp_err)) { g_print (_("Error: failed to set '%s' property: %s\n"), prop_name, tmp_err->message); g_clear_error (&tmp_err); g_signal_handlers_block_matched (curr_setting, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, NULL); @@ -6879,19 +6997,20 @@ property_edit_submenu (NmCli *nmc, case NMC_EDITOR_SUB_CMD_REMOVE: if (cmd_property_arg) { unsigned long val_int = G_MAXUINT32; - char *option = NULL; + gs_free char *option = NULL; - if (!nmc_string_to_uint (cmd_property_arg, TRUE, 0, G_MAXUINT32, &val_int)) + if (!nmc_string_to_uint (cmd_property_arg, TRUE, 0, G_MAXUINT32, &val_int)) { option = g_strdup (cmd_property_arg); + g_strstrip (option); + } if (!nmc_setting_remove_property_option (curr_setting, prop_name, - option ? g_strstrip (option) : NULL, + option, (guint32) val_int, &tmp_err)) { g_print (_("Error: %s\n"), tmp_err->message); g_clear_error (&tmp_err); } - g_free (option); } else { if (!nmc_setting_reset_property (curr_setting, prop_name, &tmp_err)) { g_print (_("Error: failed to remove value of '%s': %s\n"), prop_name, @@ -6934,7 +7053,7 @@ property_edit_submenu (NmCli *nmc, case NMC_EDITOR_SUB_CMD_QUIT: if (is_connection_dirty (connection, *rem_con)) { - if (confirm_quit ()) + if (confirm_quit (&nmc->nmc_config)) return FALSE; } else return FALSE; @@ -6995,7 +7114,8 @@ create_setting_by_name (const char *name, const NMMetaSettingValidPartItem *cons } static const char * -ask_check_setting (const char *arg, +ask_check_setting (const NmcConfig *nmc_config, + const char *arg, const NMMetaSettingValidPartItem *const*valid_settings_main, const NMMetaSettingValidPartItem *const*valid_settings_slave, const char *valid_settings_str) @@ -7006,12 +7126,12 @@ ask_check_setting (const char *arg, if (!arg) { g_print (_("Available settings: %s\n"), valid_settings_str); - setting_name_user = nmc_readline (EDITOR_PROMPT_SETTING); + setting_name_user = nmc_readline (nmc_config, + EDITOR_PROMPT_SETTING); } else setting_name_user = g_strdup (arg); - if (setting_name_user) - g_strstrip (setting_name_user); + nm_strstrip (setting_name_user); if (!(setting_name = check_valid_name (setting_name_user, valid_settings_main, @@ -7025,7 +7145,8 @@ ask_check_setting (const char *arg, } static const char * -ask_check_property (const char *arg, +ask_check_property (const NmcConfig *nmc_config, + const char *arg, const char **valid_props, const char *valid_props_str) { @@ -7035,9 +7156,9 @@ ask_check_property (const char *arg, if (!arg) { g_print (_("Available properties: %s\n"), valid_props_str); - prop_name_user = nmc_readline (EDITOR_PROMPT_PROPERTY); - if (prop_name_user) - g_strstrip (prop_name_user); + prop_name_user = nmc_readline (nmc_config, + EDITOR_PROMPT_PROPERTY); + nm_strstrip (prop_name_user); } else prop_name_user = g_strdup (arg); @@ -7064,7 +7185,9 @@ update_connection_timestamp (NMConnection *src, NMConnection *dst) } static gboolean -confirm_connection_saving (NMConnection *local, NMConnection *remote) +confirm_connection_saving (const NmcConfig *nmc_config, + NMConnection *local, + NMConnection *remote) { NMSettingConnection *s_con_loc, *s_con_rem; gboolean ac_local, ac_remote; @@ -7082,16 +7205,15 @@ confirm_connection_saving (NMConnection *local, NMConnection *remote) ac_remote = FALSE; if (ac_local && !ac_remote) { - char *answer; - answer = nmc_readline (_("Saving the connection with 'autoconnect=yes'. " + gs_free char *answer = NULL; + + answer = nmc_readline (nmc_config, + _("Saving the connection with 'autoconnect=yes'. " "That might result in an immediate activation of the connection.\n" - "Do you still want to save? %s"), prompt_yes_no (TRUE, NULL)); - answer = answer ? g_strstrip (answer) : NULL; - if (!answer || matches (answer, WORD_YES)) - confirmed = TRUE; - else - confirmed = FALSE; - g_free (answer); + "Do you still want to save? %s"), + prompt_yes_no (TRUE, NULL)); + nm_strstrip (answer); + confirmed = (!answer || matches (answer, WORD_YES)); } return confirmed; } @@ -7196,9 +7318,11 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t if (nmc->editor_status_line) editor_show_status_line (connection, dirty, temp_changes); - cmd_user = nmc_readline ("%s", menu_ctx.main_prompt); + cmd_user = nmc_readline (&nmc->nmc_config, + "%s", + menu_ctx.main_prompt); - /* Get the remote connection again, it may have disapeared */ + /* Get the remote connection again, it may have disappeared */ removed = refresh_remote_connection (&weak, &rem_con); if (removed) { g_print (_("The connection profile has been removed from another client. " @@ -7208,7 +7332,9 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t if (!cmd_user || !*cmd_user) continue; - cmd = parse_editor_main_cmd (g_strstrip (cmd_user), &cmd_arg); + g_strstrip (cmd_user); + + cmd = parse_editor_main_cmd (cmd_user, &cmd_arg); split_editor_main_cmd_args (cmd_arg, &cmd_arg_s, &cmd_arg_p, &cmd_arg_v); switch (cmd) { @@ -7222,7 +7348,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t const char *const*avals; GError *tmp_err = NULL; - prop_name = ask_check_property (cmd_arg, + prop_name = ask_check_property (&nmc->nmc_config, + cmd_arg, (const char **) menu_ctx.valid_props, menu_ctx.valid_props_str); if (!prop_name) @@ -7236,10 +7363,12 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t g_print (_("Allowed values for '%s' property: %s\n"), prop_name, avals_str); } - prop_val_user = nmc_readline (_("Enter '%s' value: "), prop_name); + prop_val_user = nmc_readline (&nmc->nmc_config, + _("Enter '%s' value: "), + prop_name); /* Set property value */ - if (!nmc_setting_set_property (menu_ctx.curr_setting, prop_name, prop_val_user, &tmp_err)) { + if (!nmc_setting_set_property (nmc->client, menu_ctx.curr_setting, prop_name, prop_val_user, &tmp_err)) { g_print (_("Error: failed to set '%s' property: %s\n"), prop_name, tmp_err->message); g_clear_error (&tmp_err); } @@ -7294,11 +7423,13 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t g_print (_("Allowed values for '%s' property: %s\n"), prop_name, avals_str); } - cmd_arg_v = nmc_readline (_("Enter '%s' value: "), prop_name); + cmd_arg_v = nmc_readline (&nmc->nmc_config, + _("Enter '%s' value: "), + prop_name); } /* Set property value */ - if (!nmc_setting_set_property (ss, prop_name, cmd_arg_v, &tmp_err)) { + if (!nmc_setting_set_property (nmc->client, ss, prop_name, cmd_arg_v, &tmp_err)) { g_print (_("Error: failed to set '%s' property: %s\n"), prop_name, tmp_err->message); g_clear_error (&tmp_err); @@ -7317,7 +7448,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t NMSetting *setting; const char *user_arg = cmd_arg_s ?: cmd_arg_p; - setting_name = ask_check_setting (user_arg, + setting_name = ask_check_setting (&nmc->nmc_config, + user_arg, valid_settings_main, valid_settings_slave, valid_settings_str); @@ -7363,7 +7495,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t /* level 1 - setting selected */ const char *prop_name; - prop_name = ask_check_property (cmd_arg_p, + prop_name = ask_check_property (&nmc->nmc_config, + cmd_arg_p, (const char **) menu_ctx.valid_props, menu_ctx.valid_props_str); if (!prop_name) @@ -7386,7 +7519,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t GError *tmp_err = NULL; const char *prop_name; - prop_name = ask_check_property (cmd_arg, + prop_name = ask_check_property (&nmc->nmc_config, + cmd_arg, (const char **) menu_ctx.valid_props, menu_ctx.valid_props_str); if (!prop_name) @@ -7480,7 +7614,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t if (menu_ctx.level == 1) { const char *prop_name; - prop_name = ask_check_property (cmd_arg, + prop_name = ask_check_property (&nmc->nmc_config, + cmd_arg, (const char **) menu_ctx.valid_props, menu_ctx.valid_props_str); if (!prop_name) @@ -7682,9 +7817,12 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t } /* Ask for save confirmation if the connection changes to autoconnect=yes */ - if (nmc->editor_save_confirmation) - if (!confirm_connection_saving (connection, NM_CONNECTION (rem_con))) + if (nmc->editor_save_confirmation) { + if (!confirm_connection_saving (&nmc->nmc_config, + connection, + NM_CONNECTION (rem_con))) break; + } if (!rem_con) { /* Tell the settings service to add the new connection */ @@ -7823,7 +7961,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t nmc_editor_error->message); g_error_free (nmc_editor_error); } else { - nmc_readline (_("Monitoring connection activation (press any key to continue)\n")); + nmc_readline (&nmc->nmc_config, + _("Monitoring connection activation (press any key to continue)\n")); } if (nmc_editor_monitor_ac) { @@ -7897,7 +8036,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t case NMC_EDITOR_MAIN_CMD_QUIT: if (is_connection_dirty (connection, rem_con)) { - if (confirm_quit ()) + if (confirm_quit (&nmc->nmc_config)) cmd_loop = FALSE; /* quit command loop */ } else cmd_loop = FALSE; /* quit command loop */ @@ -8085,7 +8224,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) /* Setup some readline completion stuff */ /* Set a pointer to an alternative function to create matches */ - rl_attempted_completion_function = (rl_completion_func_t *) nmcli_editor_tab_completion; + rl_attempted_completion_function = nmcli_editor_tab_completion; /* Use ' ' and '.' as word break characters */ rl_completer_word_break_characters = ". "; @@ -8173,8 +8312,9 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) g_print (_("Error: invalid connection type; %s\n"), err1->message); g_clear_error (&err1); - type_ask = nmc_readline (EDITOR_PROMPT_CON_TYPE); - type = type_ask = type_ask ? g_strstrip (type_ask) : NULL; + type_ask = nmc_readline (&nmc->nmc_config, + EDITOR_PROMPT_CON_TYPE); + type = type_ask = nm_strstrip (type_ask); connection_type = check_valid_name_toplevel (type_ask, &slave_type, &err1); } nm_clear_g_free (&tmp_str); @@ -8367,14 +8507,14 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) argc_ptr = &argc; if (argc == 0 && nmc->ask) { - char *line; + gs_free char *line = NULL; /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); - line = nmc_readline (PROMPT_CONNECTION); + line = nmc_readline (&nmc->nmc_config, + PROMPT_CONNECTION); nmc_string_to_arg_array (line, NULL, TRUE, &arg_arr, &arg_num); - g_free (line); argv_ptr = &arg_arr; argc_ptr = &arg_num; } @@ -8390,9 +8530,10 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) if (argv[0]) new_name = *argv; - else if (nmc->ask) - new_name = new_name_ask = nmc_readline (_("New connection name: ")); - else { + else if (nmc->ask) { + new_name = new_name_ask = nmc_readline (&nmc->nmc_config, + _("New connection name: ")); + } else { g_string_printf (nmc->return_text, _("Error: <new name> argument is missing.")); NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } @@ -8477,14 +8618,14 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) if (argc == 0) { if (nmc->ask) { - char *line; + gs_free char *line = NULL; /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); - line = nmc_readline (PROMPT_CONNECTIONS); + line = nmc_readline (&nmc->nmc_config, + PROMPT_CONNECTIONS); nmc_string_to_arg_array (line, NULL, TRUE, &arg_arr, &arg_num); - g_free (line); arg_ptr = arg_arr; } if (arg_num == 0) { @@ -8733,10 +8874,13 @@ do_connection_import (NmCli *nmc, int argc, char **argv) g_assert (!nmc->complete); if (nmc->ask) { - type_ask = nmc_readline ("%s: ", gettext (NM_META_TEXT_PROMPT_VPN_TYPE)); - filename_ask = nmc_readline (gettext (PROMPT_IMPORT_FILE)); - type = type_ask = type_ask ? g_strstrip (type_ask) : NULL; - filename = filename_ask = filename_ask ? g_strstrip (filename_ask) : NULL; + type_ask = nmc_readline (&nmc->nmc_config, + "%s: ", + gettext (NM_META_TEXT_PROMPT_VPN_TYPE)); + type = nm_strstrip (type_ask); + filename_ask = nmc_readline (&nmc->nmc_config, + gettext (PROMPT_IMPORT_FILE)); + filename = nm_strstrip (filename_ask); } else { g_string_printf (nmc->return_text, _("Error: No arguments provided.")); NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); @@ -8744,8 +8888,11 @@ do_connection_import (NmCli *nmc, int argc, char **argv) } while (argc > 0) { - if (argc == 1 && nmc->complete) - nmc_complete_strings (*argv, "type", "file", NULL); + if (argc == 1 && nmc->complete) { + nmc_complete_strings (*argv, + type ? NULL : "type", + filename ? NULL : "file"); + } if (strcmp (*argv, "type") == 0) { argc--; @@ -8755,8 +8902,13 @@ do_connection_import (NmCli *nmc, int argc, char **argv) NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } - if (argc == 1 && nmc->complete) - complete_option ((const NMMetaAbstractInfo *) nm_meta_property_info_vpn_service_type, *argv, NULL); + if ( argc == 1 + && nmc->complete) { + nmc_complete_strings (*argv, "wireguard"); + complete_option ((const NMMetaAbstractInfo *) nm_meta_property_info_vpn_service_type, + *argv, + NULL); + } if (!type) type = *argv; @@ -8796,21 +8948,26 @@ do_connection_import (NmCli *nmc, int argc, char **argv) NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } - service_type = nm_vpn_plugin_info_list_find_service_type (nm_vpn_get_plugin_infos (), type); - if (!service_type) { - g_string_printf (nmc->return_text, _("Error: failed to find VPN plugin for %s."), type); - NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN); - } + if (nm_streq (type, "wireguard")) + connection = nm_vpn_wireguard_import (filename, &error); + else { + service_type = nm_vpn_plugin_info_list_find_service_type (nm_vpn_get_plugin_infos (), type); + if (!service_type) { + g_string_printf (nmc->return_text, _("Error: failed to find VPN plugin for %s."), type); + NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN); + } - /* Import VPN configuration */ - plugin = nm_vpn_get_editor_plugin (service_type, &error); - if (!plugin) { - g_string_printf (nmc->return_text, _("Error: failed to load VPN plugin: %s."), - error->message); - NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN); + /* Import VPN configuration */ + plugin = nm_vpn_get_editor_plugin (service_type, &error); + if (!plugin) { + g_string_printf (nmc->return_text, _("Error: failed to load VPN plugin: %s."), + error->message); + NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN); + } + + connection = nm_vpn_editor_plugin_import (plugin, filename, &error); } - connection = nm_vpn_editor_plugin_import (plugin, filename, &error); if (!connection) { g_string_printf (nmc->return_text, _("Error: failed to import '%s': %s."), filename, error->message); @@ -8853,14 +9010,14 @@ do_connection_export (NmCli *nmc, int argc, char **argv) argc_ptr = &argc; if (argc == 0 && nmc->ask) { - char *line; + gs_free char *line = NULL; /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); - line = nmc_readline (PROMPT_VPN_CONNECTION); + line = nmc_readline (&nmc->nmc_config, + PROMPT_VPN_CONNECTION); nmc_string_to_arg_array (line, NULL, TRUE, &arg_arr, &arg_num); - g_free (line); argv_ptr = &arg_arr; argc_ptr = &arg_num; } @@ -8883,8 +9040,10 @@ do_connection_export (NmCli *nmc, int argc, char **argv) goto finish; } - if (out_name == NULL && nmc->ask) - out_name = out_name_ask = nmc_readline (_("Output file name: ")); + if (!out_name && nmc->ask) { + out_name = out_name_ask = nmc_readline (&nmc->nmc_config, + _("Output file name: ")); + } type = nm_connection_get_connection_type (connection); if (g_strcmp0 (type, NM_SETTING_VPN_SETTING_NAME) != 0) { @@ -8908,7 +9067,7 @@ do_connection_export (NmCli *nmc, int argc, char **argv) else { nm_auto_close int fd = -1; - fd = g_mkstemp (tmpfile); + fd = g_mkstemp_full (tmpfile, O_RDWR | O_CLOEXEC, 0600); if (fd == -1) { g_string_printf (nmc->return_text, _("Error: failed to create temporary file %s."), tmpfile); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; @@ -9060,7 +9219,7 @@ do_connections (NmCli *nmc, int argc, char **argv) nmc_start_polkit_agent_start_try (nmc); /* Set completion function for 'nmcli con' */ - rl_attempted_completion_function = (rl_completion_func_t *) nmcli_con_tab_completion; + rl_attempted_completion_function = nmcli_con_tab_completion; nmc_do_cmd (nmc, connection_cmds, *argv, argc, argv); |