diff options
| author | Michael Biebl <biebl@debian.org> | 2025-08-01 19:15:13 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2025-08-01 19:15:13 +0200 |
| commit | 7e9091a5960f67a84787c03153324915220e4816 (patch) | |
| tree | dc743de962532932ebc3b4ed3a36ddd093d97d68 /src/nmcli | |
| parent | 582eb4472a0f3375042afb9026cbeb50e058a27d (diff) | |
New upstream version 1.54.0 upstream/1.54.0
Diffstat (limited to 'src/nmcli')
| -rw-r--r-- | src/nmcli/agent.c | 2 | ||||
| -rw-r--r-- | src/nmcli/common.c | 2 | ||||
| -rw-r--r-- | src/nmcli/common.h | 10 | ||||
| -rw-r--r-- | src/nmcli/connections.c | 570 | ||||
| -rw-r--r-- | src/nmcli/connections.h | 12 | ||||
| -rw-r--r-- | src/nmcli/devices.c | 2 | ||||
| -rw-r--r-- | src/nmcli/gen-metadata-nm-settings-nmcli.xml.in | 24 | ||||
| -rw-r--r-- | src/nmcli/general.c | 2 | ||||
| -rw-r--r-- | src/nmcli/nmcli-completion | 5 | ||||
| -rw-r--r-- | src/nmcli/settings.c | 23 |
10 files changed, 427 insertions, 225 deletions
diff --git a/src/nmcli/agent.c b/src/nmcli/agent.c index b16a3c51..478f3e68 100644 --- a/src/nmcli/agent.c +++ b/src/nmcli/agent.c @@ -57,7 +57,7 @@ usage_agent_all(void) static char *pre_input_deftext; static int -set_deftext(_NMC_RL_STARTUPHOOK_ARGS) +set_deftext(void) { if (pre_input_deftext && rl_startup_hook) { rl_insert_text(pre_input_deftext); diff --git a/src/nmcli/common.c b/src/nmcli/common.c index 2ced70f3..15a7927b 100644 --- a/src/nmcli/common.c +++ b/src/nmcli/common.c @@ -1138,7 +1138,7 @@ nmc_rl_gen_func_ifnames(const char *text, int state) char *nmc_rl_pre_input_deftext; int -nmc_rl_set_deftext(_NMC_RL_STARTUPHOOK_ARGS) +nmc_rl_set_deftext(void) { if (nmc_rl_pre_input_deftext && rl_startup_hook) { rl_insert_text(nmc_rl_pre_input_deftext); diff --git a/src/nmcli/common.h b/src/nmcli/common.h index 892b2d4e..2ed13054 100644 --- a/src/nmcli/common.h +++ b/src/nmcli/common.h @@ -50,17 +50,9 @@ char *nmc_rl_gen_func_ifnames(const char *text, int state); gboolean nmc_get_in_readline(void); void nmc_set_in_readline(gboolean in_readline); -#if HAVE_EDITLINE_READLINE -/* libedit has different signature for rl_startup_hook function */ -#define _NMC_RL_STARTUPHOOK_ARGS const char *c, int i -#else -/* By default the libreadline shall be used */ -#define _NMC_RL_STARTUPHOOK_ARGS void -#endif - /* for pre-filling a string to readline prompt */ extern char *nmc_rl_pre_input_deftext; -int nmc_rl_set_deftext(_NMC_RL_STARTUPHOOK_ARGS); +int nmc_rl_set_deftext(void); char *nmc_parse_lldp_capabilities(guint value); diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c index bccec3a1..d93e16f0 100644 --- a/src/nmcli/connections.c +++ b/src/nmcli/connections.c @@ -1055,27 +1055,28 @@ const NmcMetaGenericInfo "," NM_SETTING_VETH_SETTING_NAME "," NM_SETTING_802_1X_SETTING_NAME \ "," NM_SETTING_WIRELESS_SETTING_NAME "," NM_SETTING_WIRELESS_SECURITY_SETTING_NAME \ "," 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 "," NM_SETTING_GSM_SETTING_NAME \ - "," NM_SETTING_CDMA_SETTING_NAME "," NM_SETTING_BLUETOOTH_SETTING_NAME \ - "," NM_SETTING_OLPC_MESH_SETTING_NAME "," NM_SETTING_VPN_SETTING_NAME \ - "," NM_SETTING_INFINIBAND_SETTING_NAME "," NM_SETTING_BOND_SETTING_NAME \ - "," NM_SETTING_BOND_PORT_SETTING_NAME "," NM_SETTING_VLAN_SETTING_NAME \ - "," NM_SETTING_BRIDGE_SETTING_NAME "," NM_SETTING_BRIDGE_PORT_SETTING_NAME \ - "," NM_SETTING_TEAM_SETTING_NAME "," NM_SETTING_TEAM_PORT_SETTING_NAME \ - "," NM_SETTING_OVS_BRIDGE_SETTING_NAME "," NM_SETTING_OVS_INTERFACE_SETTING_NAME \ - "," NM_SETTING_OVS_PATCH_SETTING_NAME "," NM_SETTING_OVS_PORT_SETTING_NAME \ - "," NM_SETTING_GENERIC_SETTING_NAME "," NM_SETTING_DCB_SETTING_NAME \ - "," NM_SETTING_TUN_SETTING_NAME "," NM_SETTING_IP_TUNNEL_SETTING_NAME \ - "," NM_SETTING_MACSEC_SETTING_NAME "," NM_SETTING_MACVLAN_SETTING_NAME \ - "," NM_SETTING_VXLAN_SETTING_NAME "," NM_SETTING_VRF_SETTING_NAME \ - "," NM_SETTING_WPAN_SETTING_NAME "," NM_SETTING_6LOWPAN_SETTING_NAME \ - "," NM_SETTING_WIREGUARD_SETTING_NAME "," NM_SETTING_LINK_SETTING_NAME \ - "," NM_SETTING_PROXY_SETTING_NAME "," NM_SETTING_TC_CONFIG_SETTING_NAME \ - "," NM_SETTING_SRIOV_SETTING_NAME "," NM_SETTING_ETHTOOL_SETTING_NAME \ - "," NM_SETTING_OVS_DPDK_SETTING_NAME "," NM_SETTING_HOSTNAME_SETTING_NAME \ - "," NM_SETTING_HSR_SETTING_NAME "," NM_SETTING_IPVLAN_SETTING_NAME + "," NM_SETTING_PREFIX_DELEGATION_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 \ + "," NM_SETTING_GSM_SETTING_NAME "," NM_SETTING_CDMA_SETTING_NAME \ + "," NM_SETTING_BLUETOOTH_SETTING_NAME "," NM_SETTING_OLPC_MESH_SETTING_NAME \ + "," NM_SETTING_VPN_SETTING_NAME "," NM_SETTING_INFINIBAND_SETTING_NAME \ + "," NM_SETTING_BOND_SETTING_NAME "," NM_SETTING_BOND_PORT_SETTING_NAME \ + "," NM_SETTING_VLAN_SETTING_NAME "," NM_SETTING_BRIDGE_SETTING_NAME \ + "," NM_SETTING_BRIDGE_PORT_SETTING_NAME "," NM_SETTING_TEAM_SETTING_NAME \ + "," NM_SETTING_TEAM_PORT_SETTING_NAME "," NM_SETTING_OVS_BRIDGE_SETTING_NAME \ + "," NM_SETTING_OVS_INTERFACE_SETTING_NAME "," NM_SETTING_OVS_PATCH_SETTING_NAME \ + "," NM_SETTING_OVS_PORT_SETTING_NAME "," NM_SETTING_GENERIC_SETTING_NAME \ + "," NM_SETTING_DCB_SETTING_NAME "," NM_SETTING_TUN_SETTING_NAME \ + "," NM_SETTING_IP_TUNNEL_SETTING_NAME "," NM_SETTING_MACSEC_SETTING_NAME \ + "," NM_SETTING_MACVLAN_SETTING_NAME "," NM_SETTING_VXLAN_SETTING_NAME \ + "," NM_SETTING_VRF_SETTING_NAME "," NM_SETTING_WPAN_SETTING_NAME \ + "," NM_SETTING_6LOWPAN_SETTING_NAME "," NM_SETTING_WIREGUARD_SETTING_NAME \ + "," NM_SETTING_LINK_SETTING_NAME "," NM_SETTING_PROXY_SETTING_NAME \ + "," NM_SETTING_TC_CONFIG_SETTING_NAME "," NM_SETTING_SRIOV_SETTING_NAME \ + "," NM_SETTING_ETHTOOL_SETTING_NAME "," NM_SETTING_OVS_DPDK_SETTING_NAME \ + "," NM_SETTING_HOSTNAME_SETTING_NAME "," NM_SETTING_HSR_SETTING_NAME \ + "," NM_SETTING_IPVLAN_SETTING_NAME /* NM_SETTING_DUMMY_SETTING_NAME NM_SETTING_WIMAX_SETTING_NAME */ const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = { @@ -3510,9 +3511,9 @@ do_connection_down(const NMCCommand *cmd, NmCli *nmc, int argc, const char *cons active = found_active_cons->pdata[i]; if (!nm_client_deactivate_connection(nmc->client, active, NULL, &error)) { - nmc_print(_("Connection '%s' deactivation failed: %s\n"), - nm_active_connection_get_id(active), - error->message); + nmc_printerr(_("Connection '%s' deactivation failed: %s\n"), + nm_active_connection_get_id(active), + error->message); g_clear_error(&error); if (info) { @@ -3860,6 +3861,11 @@ check_valid_name_toplevel(const char *val, const char **port_type, GError **erro return NM_SETTING_WIRED_SETTING_NAME; } + if (nm_streq(str, "ovs-port")) + NM_SET_OUT(port_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME); + else if (nm_streq(str, "ovs-interface")) + NM_SET_OUT(port_type, NM_SETTING_OVS_PORT_SETTING_NAME); + setting_info = nm_meta_setting_info_editor_find_by_name(str, TRUE); if (setting_info) return setting_info->general->setting_name; @@ -3999,8 +4005,10 @@ normalized_controller_for_port(const GPtrArray *connections, } if (!out_controller) { - nmc_print(_("Warning: controller='%s' doesn't refer to any existing profile.\n"), - controller); + nmc_printerr( + _("Warning: controller '%s' doesn't refer to any existing profile of type '%s'.\n"), + controller, + type); out_controller = controller; if (out_type) *out_type = type; @@ -4615,8 +4623,11 @@ set_connection_type(NmCli *nmc, gboolean allow_reset, GError **error) { - GError *local = NULL; - const char *port_type = NULL; + NMSettingConnection *s_con = nm_connection_get_setting_connection(con); + GError *local = NULL; + const char *port_type = NULL; + + nm_assert(s_con); value = check_valid_name_toplevel(value, &port_type, &local); if (!value) { @@ -4631,7 +4642,7 @@ set_connection_type(NmCli *nmc, return FALSE; } - if (port_type) { + if (!nm_setting_connection_get_port_type(s_con) && port_type) { if (!set_property(nmc->client, con, NM_SETTING_CONNECTION_SETTING_NAME, @@ -5228,19 +5239,140 @@ get_value(const char **value, return TRUE; } +static int +_copy_connection_properties(const char ***dst, + const char *const *src, + gboolean invert_match, + const char *const *options_list_match) +{ + const char *option; + gboolean match; + int count = 0; + + while (*src) { + option = (**src == '+' || **src == '-') ? *src + 1 : *src; + match = _nm_g_strv_contains(options_list_match, option); + match = invert_match ? !match : match; + if (match) { + *((*dst)++) = src[0]; + *((*dst)++) = src[1]; + count += 2; + } + src++; + if (*src) /* Might be the NULL termination, already */ + src++; + } + + return count; +} + +static gboolean +is_ip_setting_for_port_connection(NMConnection *connection, + const char *setting_name, + const char *property_name, + const char *value, + gboolean *out_is_method_disabled) +{ + NMSettingConnection *s_con; + + *out_is_method_disabled = FALSE; + + if (!NM_IN_STRSET(setting_name, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME)) + return FALSE; + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) + return FALSE; + + if (!nm_setting_connection_get_controller(s_con)) + return FALSE; + + if (nm_streq(property_name, NM_SETTING_IP_CONFIG_METHOD)) { + if (nm_streq(setting_name, NM_SETTING_IP4_CONFIG_SETTING_NAME)) { + if (nm_streq(value, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) + *out_is_method_disabled = TRUE; + } else { + /* IPv6 */ + if (NM_IN_STRSET(value, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) + *out_is_method_disabled = TRUE; + } + } + + return TRUE; +} + gboolean -nmc_process_connection_properties(NmCli *nmc, - NMConnection *connection, - int *argc, - const char *const **argv, - gboolean allow_setting_removal, - GError **error) +nmc_process_connection_properties(NmCli *nmc, + NMConnection *connection, + int argc, + const char *const *argv, + gboolean allow_setting_removal, + GError **error) { + gs_free const char **to_free = NULL; + + if (argc == 0) + return TRUE; + /* First check if we have a port-type, as this would mean we will not * have ip properties but possibly others, port-type specific. + * Then check connection.type and connection.controller, as port-type might + * be deduced from them. + * Don't reorder if we are doing CLI argument completion, as it might give + * unexpected results */ + if (!nmc->complete) { + const char **dst; + + dst = to_free = g_new(const char *, argc + 1); + + argc = _copy_connection_properties( + &dst, + argv, + FALSE, + NM_MAKE_STRV(NM_SETTING_CONNECTION_SETTING_NAME "." NM_SETTING_CONNECTION_PORT_TYPE, + "port-type", /* alias */ + NM_SETTING_CONNECTION_SETTING_NAME "." NM_SETTING_CONNECTION_SLAVE_TYPE, + "slave-type" /* alias */)); + argc += _copy_connection_properties(&dst, + argv, + FALSE, + NM_MAKE_STRV(NM_SETTING_CONNECTION_SETTING_NAME + "." NM_SETTING_CONNECTION_TYPE, + "type" /* alias */)); + argc += _copy_connection_properties( + &dst, + argv, + FALSE, + NM_MAKE_STRV(NM_SETTING_CONNECTION_SETTING_NAME "." NM_SETTING_CONNECTION_CONTROLLER, + "controller", /* alias */ + NM_SETTING_CONNECTION_SETTING_NAME "." NM_SETTING_CONNECTION_MASTER, + "master" /* alias */)); + argc += _copy_connection_properties( + &dst, + argv, + TRUE, + NM_MAKE_STRV(NM_SETTING_CONNECTION_SETTING_NAME "." NM_SETTING_CONNECTION_PORT_TYPE, + "port-type", + NM_SETTING_CONNECTION_SETTING_NAME "." NM_SETTING_CONNECTION_SLAVE_TYPE, + "slave-type", + NM_SETTING_CONNECTION_SETTING_NAME "." NM_SETTING_CONNECTION_TYPE, + "type", + NM_SETTING_CONNECTION_SETTING_NAME "." NM_SETTING_CONNECTION_CONTROLLER, + "controller", + NM_SETTING_CONNECTION_SETTING_NAME "." NM_SETTING_CONNECTION_MASTER, + "master")); + + *dst = NULL; /* NULL terminated as expected by get_value() */ + argv = to_free; + } + /* Go through arguments and set properties */ - do { + while (argc) { const NMMetaSettingValidPartItem *const *type_settings; const NMMetaSettingValidPartItem *const *port_settings; NMMetaAccessorModifier modifier; @@ -5259,19 +5391,10 @@ nmc_process_connection_properties(NmCli *nmc, ensure_settings(connection, port_settings); ensure_settings(connection, type_settings); - if (*argc <= 0) { - g_set_error_literal(error, - NMCLI_ERROR, - NMC_RESULT_ERROR_USER_INPUT, - _("Error: <setting>.<property> argument is missing.")); - return FALSE; - } - nm_assert(argv); nm_assert(*argv); - nm_assert(**argv); - option_orig = **argv; + option_orig = *argv; switch (option_orig[0]) { case '+': @@ -5293,15 +5416,15 @@ nmc_process_connection_properties(NmCli *nmc, NMSetting *ss; const char *setting_name; - (*argc)--; - (*argv)++; + argc--; + argv++; - if (*argc == 1 && nmc->complete) { + if (argc == 1 && nmc->complete) { complete_existing_setting(nmc, connection, value); - return TRUE; + break; } - if (!*argc) { + if (!argc) { g_set_error_literal(error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, @@ -5309,9 +5432,9 @@ nmc_process_connection_properties(NmCli *nmc, return FALSE; } - setting_name = **argv; - (*argc)--; - (*argv)++; + setting_name = *argv; + argc--; + argv++; ss = is_setting_valid(connection, type_settings, port_settings, setting_name); if (!ss) { @@ -5341,30 +5464,64 @@ nmc_process_connection_properties(NmCli *nmc, /* This seems like a <setting>.<property> (such as "connection.id" or "bond.mode"), * optionally prefixed with "+| or "-". */ - if (*argc == 1 && nmc->complete) + if (argc == 1 && nmc->complete) complete_property_name(nmc, connection, modifier, option_sett, option_prop); + argc--; + argv++; + if (!get_value(&value, &argc, &argv, option_orig, error)) + return FALSE; + option_sett_expanded = check_valid_name(option_sett, type_settings, port_settings, &local); if (!option_sett_expanded) { - g_set_error(error, - NMCLI_ERROR, - NMC_RESULT_ERROR_USER_INPUT, - _("Error: invalid or not allowed setting '%s': %s."), - option_sett, - local->message); - g_clear_error(&local); - return FALSE; + gboolean raise_error = TRUE; + gboolean is_method_disabled = FALSE; + + /* The setting does not exist or is now allowed for the given + * connection type or for the given port type. In the past nmcli + * accepted IP-config properties for port connections under some + * circumstances. For backward bug compatibility, still allow + * the user to set the IP method to disabled/ignore for ports, + * so that we don't break user scripts. + * */ + if (is_ip_setting_for_port_connection(connection, + option_sett, + option_prop, + value, + &is_method_disabled)) { + if (is_method_disabled) { + /* Allowed */ + option_sett_expanded = option_sett; + raise_error = FALSE; + g_clear_error(&local); + } else { + /* The property is not a disabled/ignore IP method. Raise a + * meaningful error, instead of the generic "setting X is not + * among LIST" */ + g_clear_error(&local); + g_set_error(&local, + NMCLI_ERROR, + NMC_RESULT_ERROR_USER_INPUT, + _("port connections cannot have IP configuration")); + raise_error = TRUE; + } + } + if (raise_error) { + g_set_error(error, + NMCLI_ERROR, + NMC_RESULT_ERROR_USER_INPUT, + _("Error: invalid or not allowed setting '%s': %s."), + option_sett, + local->message); + g_clear_error(&local); + return FALSE; + } } - (*argc)--; - (*argv)++; - if (!get_value(&value, argc, argv, option_orig, error)) - return FALSE; - - if (!*argc && nmc->complete) { + if (!argc && nmc->complete) { complete_property(nmc, option_sett, option_prop, value ?: "", connection); - return TRUE; + break; } if (!set_property(nmc->client, @@ -5446,7 +5603,7 @@ nmc_process_connection_properties(NmCli *nmc, } if (!chosen) { - if (*argc == 1 && nmc->complete) { + if (argc == 1 && nmc->complete) { if (allow_setting_removal && g_str_has_prefix("remove", option)) nmc_print("remove\n"); complete_property_name(nmc, connection, modifier, option, NULL); @@ -5459,21 +5616,20 @@ nmc_process_connection_properties(NmCli *nmc, return FALSE; } - if (*argc == 1 && nmc->complete) + if (argc == 1 && nmc->complete) complete_property_name(nmc, connection, modifier, option, NULL); - (*argc)--; - (*argv)++; - if (!get_value(&value, argc, argv, option_orig, error)) + argc--; + argv++; + if (!get_value(&value, &argc, &argv, option_orig, error)) return FALSE; - if (!*argc && nmc->complete) + if (!argc && nmc->complete) complete_option(nmc, chosen, value ?: "", connection); if (!set_option(nmc, connection, chosen, value, TRUE, error)) return FALSE; - - } while (*argc); + } return TRUE; } @@ -5910,6 +6066,7 @@ nmc_add_connection(NmCli *nmc, NMConnection *connection, gboolean temporary) static void do_connection_add(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv) { + gs_unref_ptrarray GPtrArray *props = NULL; gs_unref_object NMConnection *connection = NULL; NMSettingConnection *s_con; gs_free_error GError *error = NULL; @@ -5928,16 +6085,21 @@ do_connection_add(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const s_con = (NMSettingConnection *) nm_setting_connection_new(); nm_connection_add_setting(connection, NM_SETTING(s_con)); -read_properties: - g_clear_error(&error); - /* Get the arguments from the command line if any */ - if (argc && !nmc_process_connection_properties(nmc, connection, &argc, &argv, FALSE, &error)) { - if (nm_streq0(*argv, "--") && !seen_dash_dash) { + props = g_ptr_array_new_full(sizeof(const char *) * (argc + 1), NULL); + + while (argc) { + if (nm_streq0(*argv, "--")) { /* This is for compatibility with older nmcli that required * options and properties to be separated with "--" */ - seen_dash_dash = TRUE; - next_arg(nmc, &argc, &argv, NULL); - goto read_properties; + if (seen_dash_dash) { + g_string_printf(nmc->return_text, + _("Error: argument '--' can only be passed once")); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto finish; + } else { + seen_dash_dash = TRUE; + next_arg(nmc, &argc, &argv, NULL); + } } else if (nm_streq0(*argv, "save")) { /* It would be better if "save" was a separate argument and not * mixed with properties, but there's not much we can do about it now. */ @@ -5950,16 +6112,31 @@ read_properties: nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; goto finish; } - g_clear_error(&error); if (!nmc_string_to_bool(*argv, &save_bool, &error)) { g_string_printf(nmc->return_text, _("Error: 'save': %s."), error->message); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; goto finish; } next_arg(nmc, &argc, &argv, NULL); - goto read_properties; + } else { + g_ptr_array_add(props, (gpointer) *argv); + argc--; + argv++; + if (argc > 0) { + g_ptr_array_add(props, (gpointer) *argv); + argc--; + argv++; + } } + } + g_ptr_array_add(props, NULL); /* Must be NULL terminated */ + if (!nmc_process_connection_properties(nmc, + connection, + props->len - 1, + (const char *const *) props->pdata, + FALSE, + &error)) { g_string_assign(nmc->return_text, error->message); nmc->return_value = error->code; goto finish; @@ -6073,7 +6250,7 @@ finish: /* Functions for readline TAB completion in editor */ #if HAVE_EDITLINE_READLINE -#define uuid_display_hook ((void (*)(void)) NULL) +#define uuid_display_hook ((void (*)(char **, int, int)) NULL) #else static void uuid_display_hook(char **array, int len, int max_len) @@ -6944,7 +7121,7 @@ load_history_cmds(const char *uuid) kf = g_key_file_new(); if (!g_key_file_load_from_file(kf, filename, G_KEY_FILE_KEEP_COMMENTS, &err)) { if (g_error_matches(err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE)) - nmc_print("Warning: %s parse error: %s\n", filename, err->message); + nmc_printerr("Warning: %s parse error: %s\n", filename, err->message); g_key_file_free(kf); g_free(filename); return; @@ -6983,7 +7160,7 @@ save_history_cmds(const char *uuid) if (!g_key_file_load_from_file(kf, filename, G_KEY_FILE_KEEP_COMMENTS, &error)) { if (!g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT) && !g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) { - nmc_print("Warning: %s parse error: %s\n", filename, error->message); + nmc_printerr("Warning: %s parse error: %s\n", filename, error->message); return; } g_clear_error(&error); @@ -7256,7 +7433,7 @@ editor_main_help(const char *command) "is not saved, the user is asked to confirm the action.\n")); break; default: - nmc_print(_("Unknown command: '%s'\n"), command); + nmc_printerr(_("Unknown command: '%s'\n"), command); break; } } @@ -7393,7 +7570,7 @@ editor_sub_usage(const char *command) "is not saved, the user is asked to confirm the action.\n")); break; default: - nmc_print(_("Unknown command: '%s'\n"), command); + nmc_printerr(_("Unknown command: '%s'\n"), command); break; } } @@ -7477,7 +7654,7 @@ progress_activation_editor_cb(gpointer user_data) } else if (ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED || dev_state == NM_DEVICE_STATE_FAILED) { nmc_terminal_erase_line(); - nmc_print(_("Error: Connection activation failed.\n")); + nmc_printerr(_("Error: Connection activation failed.\n")); goto finish; } @@ -7704,9 +7881,9 @@ property_edit_submenu(NmCli *nmc, prop_val_user, &tmp_err); if (!set_result) { - nmc_print(_("Error: failed to set '%s' property: %s\n"), - prop_name, - tmp_err->message); + nmc_printerr(_("Error: failed to set '%s' property: %s\n"), + prop_name, + tmp_err->message); g_clear_error(&tmp_err); } break; @@ -7723,9 +7900,9 @@ property_edit_submenu(NmCli *nmc, NM_META_ACCESSOR_MODIFIER_SET, prop_val_user, &tmp_err)) { - nmc_print(_("Error: failed to set '%s' property: %s\n"), - prop_name, - tmp_err->message); + nmc_printerr(_("Error: failed to set '%s' property: %s\n"), + prop_name, + tmp_err->message); g_clear_error(&tmp_err); } break; @@ -7738,7 +7915,7 @@ property_edit_submenu(NmCli *nmc, : NM_META_ACCESSOR_MODIFIER_SET), cmd_property_arg, &tmp_err)) { - nmc_print(_("Error: %s\n"), tmp_err->message); + nmc_printerr(_("Error: %s\n"), tmp_err->message); g_clear_error(&tmp_err); } break; @@ -7757,7 +7934,7 @@ property_edit_submenu(NmCli *nmc, || matches(cmd_property_arg, "all")) editor_show_connection(connection, nmc); else - nmc_print(_("Unknown command argument: '%s'\n"), cmd_property_arg); + nmc_printerr(_("Unknown command argument: '%s'\n"), cmd_property_arg); } else { gs_free char *prop_val = NULL; @@ -7785,7 +7962,7 @@ property_edit_submenu(NmCli *nmc, case NMC_EDITOR_SUB_CMD_UNKNOWN: default: - nmc_print(_("Unknown command: '%s'\n"), cmd_property_user); + nmc_printerr(_("Unknown command: '%s'\n"), cmd_property_user); break; } } @@ -7863,7 +8040,7 @@ ask_check_setting(const NmcConfig *nmc_config, valid_settings_main, valid_settings_port, &err))) { - nmc_print(_("Error: invalid setting name; %s\n"), err->message); + nmc_printerr(_("Error: invalid setting name; %s\n"), err->message); g_clear_error(&err); } return setting_name; @@ -7888,7 +8065,7 @@ ask_check_property(const NmcConfig *nmc_config, prop_name = nmc_string_is_valid(prop_name_user, valid_props, &tmp_err); if (!prop_name) - nmc_print(_("Error: property %s\n"), tmp_err->message); + nmc_printerr(_("Error: property %s\n"), tmp_err->message); return prop_name; } @@ -8098,15 +8275,15 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty NM_META_ACCESSOR_MODIFIER_ADD, prop_val_user, &tmp_err)) { - nmc_print(_("Error: failed to set '%s' property: %s\n"), - prop_name, - tmp_err->message); + nmc_printerr(_("Error: failed to set '%s' property: %s\n"), + prop_name, + tmp_err->message); g_clear_error(&tmp_err); } } else { - nmc_print(_("Error: no setting selected; valid are [%s]\n"), - valid_settings_str); - nmc_print(_("use 'goto <setting>' first, or 'set <setting>.<property>'\n")); + nmc_printerr(_("Error: no setting selected; valid are [%s]\n"), + valid_settings_str); + nmc_printerr(_("use 'goto <setting>' first, or 'set <setting>.<property>'\n")); } } else { gs_free char *prop_name = NULL; @@ -8126,9 +8303,10 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty valid_settings_port); ss = ss_created; if (!ss) { - nmc_print(_("Error: invalid setting argument '%s'; valid are [%s]\n"), - cmd_arg_s, - valid_settings_str); + nmc_printerr( + _("Error: invalid setting argument '%s'; valid are [%s]\n"), + cmd_arg_s, + valid_settings_str); break; } } @@ -8136,14 +8314,14 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty if (menu_ctx.curr_setting) ss = menu_ctx.curr_setting; else { - nmc_print(_("Error: missing setting for '%s' property\n"), cmd_arg_p); + nmc_printerr(_("Error: missing setting for '%s' property\n"), cmd_arg_p); break; } } prop_name = is_property_valid(ss, cmd_arg_p, &tmp_err); if (!prop_name) { - nmc_print(_("Error: invalid property: %s\n"), tmp_err->message); + nmc_printerr(_("Error: invalid property: %s\n"), tmp_err->message); g_clear_error(&tmp_err); break; } @@ -8173,9 +8351,9 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty : NM_META_ACCESSOR_MODIFIER_SET, cmd_arg_v, &tmp_err)) { - nmc_print(_("Error: failed to set '%s' property: %s\n"), - prop_name, - tmp_err->message); + nmc_printerr(_("Error: failed to set '%s' property: %s\n"), + prop_name, + tmp_err->message); g_clear_error(&tmp_err); } @@ -8206,7 +8384,7 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty setting_info = nm_meta_setting_info_editor_find_by_name(setting_name, FALSE); if (!setting_info) { - nmc_print(_("Error: unknown setting '%s'\n"), setting_name); + nmc_printerr(_("Error: unknown setting '%s'\n"), setting_name); break; } @@ -8278,13 +8456,14 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty NM_META_ACCESSOR_MODIFIER_SET, NULL, &tmp_err)) { - nmc_print(_("Error: failed to remove value of '%s': %s\n"), - prop_name, - tmp_err->message); + nmc_printerr(_("Error: failed to remove value of '%s': %s\n"), + prop_name, + tmp_err->message); g_clear_error(&tmp_err); } } else - nmc_print(_("Error: no argument given; valid are [%s]\n"), valid_settings_str); + nmc_printerr(_("Error: no argument given; valid are [%s]\n"), + valid_settings_str); } else { NMSetting *ss = NULL; gboolean descr_all; @@ -8306,9 +8485,10 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty nmc_print(_("Setting '%s' is not present in the connection.\n"), user_s); } else { - nmc_print(_("Error: invalid setting argument '%s'; valid are [%s]\n"), - user_s, - valid_settings_str); + nmc_printerr( + _("Error: invalid setting argument '%s'; valid are [%s]\n"), + user_s, + valid_settings_str); } break; } @@ -8340,9 +8520,9 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty : NM_META_ACCESSOR_MODIFIER_SET, cmd_arg_v ? cmd_arg_v : NULL, &tmp_err)) { - nmc_print(_("Error: failed to remove value of '%s': %s\n"), - prop_name, - tmp_err->message); + nmc_printerr(_("Error: failed to remove value of '%s': %s\n"), + prop_name, + tmp_err->message); } } else { NMSetting *s_tmp; @@ -8366,8 +8546,8 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty nmc_tab_completion.setting = NULL; /* for TAB completion */ } } else { - nmc_print(_("Error: %s properties, nor it is a setting name.\n"), - tmp_err->message); + nmc_printerr(_("Error: %s properties, nor it is a setting name.\n"), + tmp_err->message); } } } @@ -8390,9 +8570,9 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty /* Show property description */ print_property_description(menu_ctx.curr_setting, prop_name); } else { - nmc_print(_("Error: no setting selected; valid are [%s]\n"), - valid_settings_str); - nmc_print( + nmc_printerr(_("Error: no setting selected; valid are [%s]\n"), + valid_settings_str); + nmc_printerr( _("use 'goto <setting>' first, or 'describe <setting>.<property>'\n")); } } else { @@ -8414,9 +8594,10 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty valid_settings_main, valid_settings_port); if (!ss) { - nmc_print(_("Error: invalid setting argument '%s'; valid are [%s]\n"), - user_s, - valid_settings_str); + nmc_printerr( + _("Error: invalid setting argument '%s'; valid are [%s]\n"), + user_s, + valid_settings_str); break; } ss_free = ss; @@ -8425,9 +8606,9 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty ss = menu_ctx.curr_setting; if (!ss) { - nmc_print(_("Error: no setting selected; valid are [%s]\n"), - valid_settings_str); - nmc_print( + nmc_printerr(_("Error: no setting selected; valid are [%s]\n"), + valid_settings_str); + nmc_printerr( _("use 'goto <setting>' first, or 'describe <setting>.<property>'\n")); } else if (descr_all) { /* Show description for all properties */ @@ -8451,9 +8632,9 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty if (s_tmp) print_setting_description(s_tmp); else { - nmc_print(_("Error: invalid property: %s, " - "neither a valid setting name.\n"), - tmp_err->message); + nmc_printerr(_("Error: invalid property: %s, " + "neither a valid setting name.\n"), + tmp_err->message); } } } @@ -8481,13 +8662,13 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty valid_settings_port, NULL); if (!s_name) { - nmc_print(_("Error: unknown setting: '%s'\n"), user_s); + nmc_printerr(_("Error: unknown setting: '%s'\n"), user_s); break; } ss = nm_connection_get_setting_by_name(connection, s_name); if (!ss) { - nmc_print(_("Error: '%s' setting not present in the connection\n"), - s_name); + nmc_printerr(_("Error: '%s' setting not present in the connection\n"), + s_name); break; } } else @@ -8518,9 +8699,9 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty /* Print the whole setting */ editor_show_setting(s_tmp, nmc); } else - nmc_print(_("Error: invalid property: %s%s\n"), - err->message, - cmd_arg_s ? "" : _(", neither a valid setting name")); + nmc_printerr(_("Error: invalid property: %s%s\n"), + err->message, + cmd_arg_s ? "" : _(", neither a valid setting name")); g_clear_error(&err); } } @@ -8536,7 +8717,7 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty case NMC_EDITOR_MAIN_CMD_VERIFY: /* Verify current setting or the whole connection */ if (cmd_arg && !nm_streq(cmd_arg, "all") && !nm_streq(cmd_arg, "fix")) { - nmc_print(_("Invalid verify option: %s\n"), cmd_arg); + nmc_printerr(_("Invalid verify option: %s\n"), cmd_arg); break; } @@ -8544,9 +8725,9 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty gs_free_error GError *tmp_err = NULL; nm_setting_verify(menu_ctx.curr_setting, NULL, &tmp_err); - nmc_print(_("Verify setting '%s': %s\n"), - nm_setting_get_name(menu_ctx.curr_setting), - tmp_err ? tmp_err->message : "OK"); + nmc_printerr(_("Verify setting '%s': %s\n"), + nm_setting_get_name(menu_ctx.curr_setting), + tmp_err ? tmp_err->message : "OK"); } else { gs_free_error GError *tmp_err = NULL; gboolean fixed = TRUE; @@ -8559,9 +8740,15 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty g_clear_error(&tmp_err); fixed = nm_connection_normalize(connection, NULL, &modified, &tmp_err); } - nmc_print(_("Verify connection: %s\n"), tmp_err ? tmp_err->message : "OK"); + + if (tmp_err) { + nmc_printerr(_("Verify connection: %s\n"), tmp_err->message); + } else { + nmc_print(_("Verify connection: %s\n"), "OK"); + } + if (!fixed) - nmc_print(_("The error cannot be fixed automatically.\n")); + nmc_printerr(_("The error cannot be fixed automatically.\n")); } break; @@ -8581,7 +8768,7 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty else if (matches(cmd_arg, "persistent")) temporary = FALSE; else { - nmc_print(_("Error: invalid argument '%s'\n"), cmd_arg); + nmc_printerr(_("Error: invalid argument '%s'\n"), cmd_arg); break; } } @@ -8638,20 +8825,20 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty g_source_destroy(source); if (nmc_editor_error) { - nmc_print(_("Error: Failed to save '%s' (%s) connection: %s\n"), - nm_connection_get_id(connection), - nm_connection_get_uuid(connection), - nmc_editor_error->message); + nmc_printerr(_("Error: Failed to save '%s' (%s) connection: %s\n"), + nm_connection_get_id(connection), + nm_connection_get_uuid(connection), + nmc_editor_error->message); g_error_free(nmc_editor_error); } else if (timeout) { - nmc_print(_("Error: Timeout saving '%s' (%s) connection\n"), - nm_connection_get_id(connection), - nm_connection_get_uuid(connection)); + nmc_printerr(_("Error: Timeout saving '%s' (%s) connection\n"), + nm_connection_get_id(connection), + nm_connection_get_uuid(connection)); } else { - nmc_print(!rem_con ? _("Connection '%s' (%s) successfully saved.\n") - : _("Connection '%s' (%s) successfully updated.\n"), - nm_connection_get_id(connection), - nm_connection_get_uuid(connection)); + nmc_printerr(!rem_con ? _("Connection '%s' (%s) successfully saved.\n") + : _("Connection '%s' (%s) successfully updated.\n"), + nm_connection_get_id(connection), + nm_connection_get_uuid(connection)); con_tmp = nm_client_get_connection_by_uuid(nmc->client, nm_connection_get_uuid(connection)); @@ -8683,9 +8870,9 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty nmc_editor_cb_called = FALSE; nmc_editor_error = NULL; } else { - nmc_print(_("Error: connection verification failed: %s\n"), - err1 ? err1->message : _("(unknown error)")); - nmc_print(_("You may try running 'verify fix' to fix errors.\n")); + nmc_printerr(_("Error: connection verification failed: %s\n"), + err1 ? err1->message : _("(unknown error)")); + nmc_printerr(_("You may try running 'verify fix' to fix errors.\n")); } g_clear_error(&err1); @@ -8708,11 +8895,11 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty if (is_connection_dirty(connection, rem_con)) { /* TRANSLATORS: do not translate 'save', leave it as it is */ - nmc_print(_("Error: connection is not saved. Type 'save' first.\n")); + nmc_printerr(_("Error: connection is not saved. Type 'save' first.\n")); break; } if (!nm_connection_verify(NM_CONNECTION(rem_con), &tmp_err)) { - nmc_print(_("Error: connection is not valid: %s\n"), tmp_err->message); + nmc_printerr(_("Error: connection is not valid: %s\n"), tmp_err->message); g_clear_error(&tmp_err); break; } @@ -8728,7 +8915,7 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty NULL, activate_connection_editor_cb, &tmp_err)) { - nmc_print(_("Error: Cannot activate connection: %s.\n"), tmp_err->message); + nmc_printerr(_("Error: Cannot activate connection: %s.\n"), tmp_err->message); g_clear_error(&tmp_err); break; } @@ -8737,10 +8924,10 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty g_main_context_iteration(NULL, TRUE); if (nmc_editor_error) { - nmc_print(_("Error: Failed to activate '%s' (%s) connection: %s\n"), - nm_connection_get_id(connection), - nm_connection_get_uuid(connection), - nmc_editor_error->message); + nmc_printerr(_("Error: Failed to activate '%s' (%s) connection: %s\n"), + nm_connection_get_id(connection), + nm_connection_get_uuid(connection), + nmc_editor_error->message); g_error_free(nmc_editor_error); } else { nmc_readline(&nmc->nmc_config, @@ -8779,7 +8966,7 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty GError *tmp_err = NULL; gboolean bb; if (!nmc_string_to_bool(cmd_arg_v ? g_strstrip(cmd_arg_v) : "", &bb, &tmp_err)) { - nmc_print(_("Error: status-line: %s\n"), tmp_err->message); + nmc_printerr(_("Error: status-line: %s\n"), tmp_err->message); g_clear_error(&tmp_err); } else nmc->editor_status_line = bb; @@ -8787,7 +8974,7 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty GError *tmp_err = NULL; gboolean bb; if (!nmc_string_to_bool(cmd_arg_v ? g_strstrip(cmd_arg_v) : "", &bb, &tmp_err)) { - nmc_print(_("Error: save-confirmation: %s\n"), tmp_err->message); + nmc_printerr(_("Error: save-confirmation: %s\n"), tmp_err->message); g_clear_error(&tmp_err); } else nmc->editor_save_confirmation = bb; @@ -8795,7 +8982,7 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty GError *tmp_err = NULL; gboolean bb; if (!nmc_string_to_bool(cmd_arg_v ? g_strstrip(cmd_arg_v) : "", &bb, &tmp_err)) { - nmc_print(_("Error: show-secrets: %s\n"), tmp_err->message); + nmc_printerr(_("Error: show-secrets: %s\n"), tmp_err->message); g_clear_error(&tmp_err); } else nmc->nmc_config_mutable.show_secrets = bb; @@ -8811,9 +8998,9 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty nmc->editor_save_confirmation ? "yes" : "no", nmc->nmc_config.show_secrets ? "yes" : "no"); } else - nmc_print(_("Invalid configuration option '%s'; allowed [%s]\n"), - cmd_arg_v ?: "", - "status-line, save-confirmation, show-secrets"); + nmc_printerr(_("Invalid configuration option '%s'; allowed [%s]\n"), + cmd_arg_v ?: "", + "status-line, save-confirmation, show-secrets"); break; @@ -8827,7 +9014,7 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty case NMC_EDITOR_MAIN_CMD_UNKNOWN: default: - nmc_print(_("Unknown command: '%s'\n"), cmd_user); + nmc_printerr(_("Unknown command: '%s'\n"), cmd_user); break; } } @@ -9075,10 +9262,11 @@ do_connection_edit(const NMCCommand *cmd, NmCli *nmc, int argc, const char *cons connection_type = nm_setting_connection_get_connection_type(s_con); if (type) - nmc_print(_("Warning: editing existing connection '%s'; 'type' argument is ignored\n"), - nm_connection_get_id(connection)); + nmc_printerr( + _("Warning: editing existing connection '%s'; 'type' argument is ignored\n"), + nm_connection_get_id(connection)); if (con_name) - nmc_print( + nmc_printerr( _("Warning: editing existing connection '%s'; 'con-name' argument is ignored\n"), nm_connection_get_id(connection)); @@ -9106,9 +9294,9 @@ do_connection_edit(const NMCCommand *cmd, NmCli *nmc, int argc, const char *cons gs_free char *type_ask = NULL; if (!type) - nmc_print(_("Valid connection types: %s\n"), tmp_str); + nmc_printerr(_("Valid connection types: %s\n"), tmp_str); else - nmc_print(_("Error: invalid connection type; %s\n"), err1->message); + nmc_printerr(_("Error: invalid connection type; %s\n"), err1->message); g_clear_error(&err1); type_ask = nmc_readline(&nmc->nmc_config, EDITOR_PROMPT_CON_TYPE); @@ -9239,7 +9427,7 @@ do_connection_modify(const NMCCommand *cmd, NmCli *nmc, int argc, const char *co /* Don't insist on having argument if we're running in offline mode. */ if (!nmc->nmc_config.offline || argc > 0) { - if (!nmc_process_connection_properties(nmc, connection, &argc, &argv, TRUE, &error)) { + if (!nmc_process_connection_properties(nmc, connection, argc, argv, TRUE, &error)) { g_string_assign(nmc->return_text, error->message); nmc->return_value = error->code; return; diff --git a/src/nmcli/connections.h b/src/nmcli/connections.h index 48c98170..a343ca25 100644 --- a/src/nmcli/connections.h +++ b/src/nmcli/connections.h @@ -12,12 +12,12 @@ void nmc_monitor_connections(NmCli *nmc); const char *nmc_connection_check_deprecated(NMConnection *c); -gboolean nmc_process_connection_properties(NmCli *nmc, - NMConnection *connection, - int *argc, - const char *const **argv, - gboolean allow_remove_setting, - GError **error); +gboolean nmc_process_connection_properties(NmCli *nmc, + NMConnection *connection, + int argc, + const char *const *args, + gboolean allow_remove_setting, + GError **error); NMMetaColor nmc_active_connection_state_to_color(NMActiveConnection *ac); diff --git a/src/nmcli/devices.c b/src/nmcli/devices.c index b308e440..9a018113 100644 --- a/src/nmcli/devices.c +++ b/src/nmcli/devices.c @@ -2596,7 +2596,7 @@ modify_get_applied_cb(GObject *object, GAsyncResult *result, gpointer user_data) argc = info->argc; argv = (const char *const *) info->argv; - if (!nmc_process_connection_properties(info->nmc, connection, &argc, &argv, TRUE, &error)) { + if (!nmc_process_connection_properties(info->nmc, connection, argc, argv, TRUE, &error)) { g_string_assign(nmc->return_text, error->message); nmc->return_value = error->code; quit(); diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in index 77e6c427..67b14d4c 100644 --- a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in +++ b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in @@ -53,7 +53,7 @@ format="MAC address" special-values="preserve, permanent, random, stable, stable-ssid" /> <property name="generate-mac-address-mask" - nmcli-description="With "cloned-mac-address" setting "random" or "stable", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the "random" or "stable" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" will create a fully scrambled MAC address, randomly locally or globally administered." + nmcli-description="With "cloned-mac-address" setting "random" or "stable", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows one to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the "random" or "stable" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" will create a fully scrambled MAC address, randomly locally or globally administered." format="string" /> <property name="mac-address-blacklist" nmcli-description="A list of permanent MAC addresses of Wi-Fi devices to which this connection should never apply. Each MAC address should be given in the standard hex-digits-and-colons notation (eg "00:11:22:33:44:55")." @@ -362,7 +362,7 @@ format="MAC address" special-values="preserve, permanent, random, stable" /> <property name="generate-mac-address-mask" - nmcli-description="With "cloned-mac-address" setting "random" or "stable", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the "random" or "stable" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" will create a fully scrambled MAC address, randomly locally or globally administered." + nmcli-description="With "cloned-mac-address" setting "random" or "stable", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows one to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the "random" or "stable" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" will create a fully scrambled MAC address, randomly locally or globally administered." format="string" /> <property name="mac-address-blacklist" nmcli-description="If specified, this connection will never apply to the Ethernet device whose permanent MAC address matches an address in the list. Each MAC address is in the standard hex-digits-and-colons notation (00:11:22:33:44:55)." @@ -623,7 +623,7 @@ nmcli-description="The connection.uuid is the real identifier of a profile. It cannot change and it must be unique. It is therefore often best to refer to a profile by UUID, for example with `nmcli connection up uuid $UUID`. The UUID cannot be changed, except in offline mode. In that case, the special values "new", "generate" and "" are allowed to generate a new random UUID." format="string" /> <property name="stable-id" - nmcli-description="This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used to derive the DHCP client identifier with ipv4.dhcp-client-id=stable, the DHCPv6 DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid] and the DHCP IAID with ipv4.iaid=stable and ipv6.iaid=stable. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The per-host key is the identity of your machine and stored in /var/lib/NetworkManager/secret_key. See NetworkManager(8) manual about the secret-key and the host identity. The '$' character is treated special to perform dynamic substitutions at activation time. Currently, supported are "${CONNECTION}", "${DEVICE}", "${MAC}", "${NETWORK_SSID}", "${BOOT}", "${RANDOM}". These effectively create unique IDs per-connection, per-device, per-SSID, per-boot, or every time. The "${CONNECTION}" uses the profile's connection.uuid, the "${DEVICE}" uses the interface name of the device and "${MAC}" the permanent MAC address of the device. "${NETWORK_SSID}" uses the SSID for Wi-Fi networks and falls back to "${CONNECTION}" on other networks. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as "$$". For example, set it to "${CONNECTION}-${BOOT}-${DEVICE}" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is "default${CONNECTION}" go generate an ID unique per connection profile." + nmcli-description="This represents the identity of the connection used for various purposes. It allows configuring multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used to derive the DHCP client identifier with ipv4.dhcp-client-id=stable, the DHCPv6 DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid] and the DHCP IAID with ipv4.iaid=stable and ipv6.iaid=stable. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The per-host key is the identity of your machine and stored in /var/lib/NetworkManager/secret_key. See NetworkManager(8) manual about the secret-key and the host identity. The '$' character is treated special to perform dynamic substitutions at activation time. Currently, supported are "${CONNECTION}", "${DEVICE}", "${MAC}", "${NETWORK_SSID}", "${BOOT}", "${RANDOM}". These effectively create unique IDs per-connection, per-device, per-SSID, per-boot, or every time. The "${CONNECTION}" uses the profile's connection.uuid, the "${DEVICE}" uses the interface name of the device and "${MAC}" the permanent MAC address of the device. "${NETWORK_SSID}" uses the SSID for Wi-Fi networks and falls back to "${CONNECTION}" on other networks. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as "$$". For example, set it to "${CONNECTION}-${BOOT}-${DEVICE}" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is "default${CONNECTION}" go generate an ID unique per connection profile." format="string" /> <property name="type" alias="type" @@ -1402,6 +1402,10 @@ nmcli-description="If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the dhcp-hostname property is NULL and this property is TRUE, the current persistent hostname of the computer is sent. The default value is default (-1). In this case the global value from NetworkManager configuration is looked up. If it's not set, the value from dhcp-send-hostname-deprecated, which defaults to TRUE, is used for backwards compatibility. In the future this will change and, in absence of a global default, it will always fallback to TRUE." format="choice (NMTernary)" values="default (-1), false/no (0), true/yes (1)" /> + <property name="forwarding" + nmcli-description="Whether to configure sysctl interface-specific forwarding. When enabled, the interface will act as a router to forward the packet from one interface to another. When set to "default" (-1), the value from global configuration is used; if no global default is defined, "auto" (2) will be used. The "forwarding" property is ignored when "method" is set to "shared", because forwarding is always enabled in this case. The accepted values are: "default" (-1): use global default. "no" (0): disabled. "yes" (1): enabled. "auto" (2): enable if any shared connection is active, use kernel default otherwise." + format="choice (NMSettingIPConfigForwarding)" + values="default (-1), no (0), yes (1), auto (2)" /> <property name="dhcp-hostname" nmcli-description="If the "dhcp-send-hostname" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and "dhcp-fqdn" are mutually exclusive and cannot be set at the same time." format="string" /> @@ -1759,6 +1763,10 @@ nmcli-description="The tx queue size (number of tx descriptors) for DPDK ports. Must be zero or a power of 2 between 1 and 4096, and supported by the hardware. Defaults to zero which means to leave the parameter in OVS unspecified and effectively configures 2048 descriptors." format="integer" values="0 - 4096" /> + <property name="lsc-interrupt" + nmcli-description="Configures the Link State Change (LSC) detection mode for the OVS DPDK interface. When set to "ignore" (-1), NetworkManager doesn't change the default value configured by Open vSwitch. "enabled" (1) enables interrupts. "disabled" (0) disables interrupts, thus setting the interface in poll mode." + format="choice (NMSettingOvsDpdkLscInterrupt)" + values="ignore (-1), disabled (0), enabled (1)" /> </setting> <setting name="ovs-external-ids" > </setting> @@ -1904,6 +1912,12 @@ format="flags (NMSettingSecretFlags)" values="none (0x0), agent-owned (0x1), not-saved (0x2), not-required (0x4)" /> </setting> + <setting name="prefix-delegation" > + <property name="subnet-id" + nmcli-description="The subnet ID to use on the interface from the prefix delegation received via an upstream interface. Set to a value between 0 and 0xffffffff (2^32 - 1) to indicate a specific subnet ID; or set to -1 to automatically choose an available subnet ID." + format="integer" + values="-1 - 4294967295" /> + </setting> <setting name="proxy" > <property name="method" alias="method" @@ -1970,6 +1984,10 @@ nmcli-description="Select the eswitch encapsulation support. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to "preserve" (-1) (default) the eswitch encap-mode won't be modified by NetworkManager." format="choice (NMSriovEswitchEncapMode)" values="preserve (-1), none (0), basic (1)" /> + <property name="preserve-on-down" + nmcli-description="This controls whether NetworkManager preserves the SR-IOV parameters set on the device when the connection is deactivated, or whether it resets them to their default value. The SR-IOV parameters are those specified in this setting (the "sriov" setting), like the number of VFs to create, the eswitch configuration, etc. If set to "no" (0), NetworkManager resets the SR-IOV parameters when the connection is deactivated. When set to "yes" (1), NetworkManager preserves those parameters on the device. If the value is "default" (-1), NetworkManager looks up a global default value in the configuration; in case no such value is defined, it uses "no" (0) as fallback." + format="choice (NMSriovPreserveOnDown)" + values="default (-1), no (0), yes (1)" /> </setting> <setting name="tc" > <property name="qdiscs" diff --git a/src/nmcli/general.c b/src/nmcli/general.c index c6c266a2..2e9aad44 100644 --- a/src/nmcli/general.c +++ b/src/nmcli/general.c @@ -933,7 +933,7 @@ do_general_hostname(const NMCCommand *cmd, NmCli *nmc, int argc, const char *con hostname = *argv; if (next_arg(nmc, &argc, &argv, NULL) == 0) - nmc_print("Warning: ignoring extra garbage after '%s' hostname\n", hostname); + nmc_printerr("Warning: ignoring extra garbage after '%s' hostname\n", hostname); nmc->should_wait++; nm_client_save_hostname_async(nmc->client, hostname, NULL, save_hostname_cb, nmc); diff --git a/src/nmcli/nmcli-completion b/src/nmcli/nmcli-completion index f2de7b67..0c9b5156 100644 --- a/src/nmcli/nmcli-completion +++ b/src/nmcli/nmcli-completion @@ -49,7 +49,10 @@ _nmcli() cur='' fi - output="$(nmcli --complete-args "${words[@]}" 2>/dev/null)" + # If the user set an alias like `nmcli=nmcli --some-arguments`, then --complete-args + # might give unexpected behaviours. Use `command` to ensure that aliases are ignored + # and the nmcli binary is used directly. + output="$(command nmcli --complete-args "${words[@]}" 2>/dev/null)" # Bail out early if we're completing a file name if [ $? = 65 ]; then diff --git a/src/nmcli/settings.c b/src/nmcli/settings.c index 85f4ad83..458b03e5 100644 --- a/src/nmcli/settings.c +++ b/src/nmcli/settings.c @@ -246,10 +246,11 @@ wireless_band_channel_changed_cb(GObject *object, GParamSpec *pspec, gpointer us mode = nm_setting_wireless_get_mode(NM_SETTING_WIRELESS(object)); if (!mode || !*mode || strcmp(mode, NM_SETTING_WIRELESS_MODE_INFRA) == 0) { - nmc_print(_("Warning: %s.%s set to '%s', but it might be ignored in infrastructure mode\n"), - nm_setting_get_name(NM_SETTING(s_wireless)), - g_param_spec_get_name(pspec), - value); + nmc_printerr( + _("Warning: %s.%s set to '%s', but it might be ignored in infrastructure mode\n"), + nm_setting_get_name(NM_SETTING(s_wireless)), + g_param_spec_get_name(pspec), + value); } } @@ -266,9 +267,9 @@ connection_controller_changed_cb(GObject *object, GParamSpec *pspec, gpointer us s_ipv4 = nm_connection_get_setting_by_name(connection, NM_SETTING_IP4_CONFIG_SETTING_NAME); s_ipv6 = nm_connection_get_setting_by_name(connection, NM_SETTING_IP6_CONFIG_SETTING_NAME); if (s_ipv4 || s_ipv6) { - nmc_print(_("Warning: setting %s.%s requires removing ipv4 and ipv6 settings\n"), - nm_setting_get_name(NM_SETTING(s_con)), - g_param_spec_get_name(pspec)); + nmc_printerr(_("Warning: setting %s.%s requires removing ipv4 and ipv6 settings\n"), + nm_setting_get_name(NM_SETTING(s_con)), + g_param_spec_get_name(pspec)); tmp_str = nmc_get_user_input(_("Do you want to remove them? [yes] ")); if (!tmp_str || matches(tmp_str, "yes")) { if (s_ipv4) @@ -376,8 +377,8 @@ _set_fcn_precheck_connection_secondaries(NMClient *client, if (nm_utils_is_uuid(*iter)) { con = nmc_find_connection(connections, "uuid", *iter, NULL, FALSE); if (!con) { - nmc_print(_("Warning: %s is not an UUID of any existing connection profile\n"), - *iter); + nmc_printerr(_("Warning: %s is not an UUID of any existing connection profile\n"), + *iter); } else { /* Currently, NM only supports VPN connections as secondaries */ if (!nm_connection_is_type(con, NM_SETTING_VPN_SETTING_NAME)) { @@ -434,13 +435,13 @@ _env_warn_fcn_handle( switch (warn_level) { case NM_META_ENV_WARN_LEVEL_WARN: - nmc_print(_("Warning: %s\n"), m); + nmc_printerr(_("Warning: %s\n"), m); return; case NM_META_ENV_WARN_LEVEL_INFO: nmc_print(_("Info: %s\n"), m); return; } - nmc_print(_("Error: %s\n"), m); + nmc_printerr(_("Error: %s\n"), m); } static NMDevice *const * |