diff options
| author | Michael Biebl <biebl@debian.org> | 2019-12-18 18:29:24 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2019-12-18 18:29:24 +0100 |
| commit | 28028b26b3371756811e95d894f709f4b1207c00 (patch) | |
| tree | 6fe7316fd743b51042db47601a8ef8814b3134ac /clients/cli | |
| parent | e22609983008e1a669196ad64ba3a59ae8c76e0d (diff) | |
New upstream version 1.22.0 upstream/1.22.0
Diffstat (limited to 'clients/cli')
| -rw-r--r-- | clients/cli/agent.c | 20 | ||||
| -rw-r--r-- | clients/cli/agent.h | 20 | ||||
| -rw-r--r-- | clients/cli/common.c | 150 | ||||
| -rw-r--r-- | clients/cli/common.h | 28 | ||||
| -rw-r--r-- | clients/cli/connections.c | 405 | ||||
| -rw-r--r-- | clients/cli/connections.h | 20 | ||||
| -rw-r--r-- | clients/cli/devices.c | 918 | ||||
| -rw-r--r-- | clients/cli/devices.h | 20 | ||||
| -rw-r--r-- | clients/cli/general.c | 176 | ||||
| -rw-r--r-- | clients/cli/general.h | 20 | ||||
| -rw-r--r-- | clients/cli/meson.build | 8 | ||||
| -rw-r--r-- | clients/cli/nmcli.c | 29 | ||||
| -rw-r--r-- | clients/cli/nmcli.h | 25 | ||||
| -rw-r--r-- | clients/cli/polkit-agent.c | 20 | ||||
| -rw-r--r-- | clients/cli/polkit-agent.h | 20 | ||||
| -rw-r--r-- | clients/cli/settings.c | 39 | ||||
| -rw-r--r-- | clients/cli/settings.h | 22 | ||||
| -rw-r--r-- | clients/cli/utils.c | 22 | ||||
| -rw-r--r-- | clients/cli/utils.h | 28 |
19 files changed, 1204 insertions, 786 deletions
diff --git a/clients/cli/agent.c b/clients/cli/agent.c index 6c116153..f4057df9 100644 --- a/clients/cli/agent.c +++ b/clients/cli/agent.c @@ -1,22 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * nmcli - command-line tool for controlling NetworkManager - * Functions for running NM secret agent. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2014 Red Hat, Inc. + * Copyright (C) 2014 Red Hat, Inc. */ #include "nm-default.h" diff --git a/clients/cli/agent.h b/clients/cli/agent.h index 70ea0d9b..aad56bba 100644 --- a/clients/cli/agent.h +++ b/clients/cli/agent.h @@ -1,22 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * nmcli - command-line tool for controlling NetworkManager - * Functions for running NM secret agent. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2014 Red Hat, Inc. + * Copyright (C) 2014 Red Hat, Inc. */ #ifndef __NMC_AGENT_H__ diff --git a/clients/cli/common.c b/clients/cli/common.c index 2fc8aaf6..04ccf8dc 100644 --- a/clients/cli/common.c +++ b/clients/cli/common.c @@ -1,22 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * nmcli - command-line tool for controlling NetworkManager - * Common functions and data shared between files. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2012 - 2018 Red Hat, Inc. + * Copyright (C) 2012 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -1201,14 +1185,13 @@ nmc_parse_lldp_capabilities (guint value) static void command_done (GObject *object, GAsyncResult *res, gpointer user_data) { - GSimpleAsyncResult *simple = (GSimpleAsyncResult *)res; + GTask *task = G_TASK (res); NmCli *nmc = user_data; - GError *error = NULL; + gs_free_error GError *error = NULL; - if (g_simple_async_result_propagate_error (simple, &error)) { + if (!g_task_propagate_boolean (task, &error)) { nmc->return_value = error->code; g_string_assign (nmc->return_text, error->message); - g_error_free (error); } if (!nmc->should_wait) @@ -1216,40 +1199,42 @@ command_done (GObject *object, GAsyncResult *res, gpointer user_data) } typedef struct { - NmCli *nmc; const NMCCommand *cmd; int argc; char **argv; - GSimpleAsyncResult *simple; + GTask *task; } CmdCall; static void -call_cmd (NmCli *nmc, GSimpleAsyncResult *simple, const NMCCommand *cmd, int argc, char **argv); +call_cmd (NmCli *nmc, GTask *task, const NMCCommand *cmd, int argc, char **argv); static void got_client (GObject *source_object, GAsyncResult *res, gpointer user_data) { - GError *error = NULL; + gs_unref_object GTask *task = NULL; + gs_free_error GError *error = NULL; CmdCall *call = user_data; - NmCli *nmc = call->nmc; + NmCli *nmc; + + task = g_steal_pointer (&call->task); + nmc = g_task_get_task_data (task); nmc->should_wait--; nmc->client = nm_client_new_finish (res, &error); if (!nmc->client) { - g_simple_async_result_set_error (call->simple, NMCLI_ERROR, NMC_RESULT_ERROR_UNKNOWN, - _("Error: Could not create NMClient object: %s."), error->message); - g_error_free (error); - g_simple_async_result_complete (call->simple); + g_task_return_new_error (task, NMCLI_ERROR, NMC_RESULT_ERROR_UNKNOWN, + _("Error: Could not create NMClient object: %s."), + error->message); } else { - call_cmd (nmc, call->simple, call->cmd, call->argc, call->argv); + call_cmd (nmc, g_steal_pointer (&task), call->cmd, call->argc, call->argv); } g_slice_free (CmdCall, call); } static void -call_cmd (NmCli *nmc, GSimpleAsyncResult *simple, const NMCCommand *cmd, int argc, char **argv) +call_cmd (NmCli *nmc, GTask *task, const NMCCommand *cmd, int argc, char **argv) { CmdCall *call; @@ -1257,20 +1242,23 @@ call_cmd (NmCli *nmc, GSimpleAsyncResult *simple, const NMCCommand *cmd, int arg /* Check whether NetworkManager is running */ if (cmd->needs_nm_running && !nm_client_get_nm_running (nmc->client)) { - g_simple_async_result_set_error (simple, NMCLI_ERROR, NMC_RESULT_ERROR_NM_NOT_RUNNING, - _("Error: NetworkManager is not running.")); - } else + g_task_return_new_error (task, NMCLI_ERROR, NMC_RESULT_ERROR_NM_NOT_RUNNING, + _("Error: NetworkManager is not running.")); + } else { nmc->return_value = cmd->func (nmc, argc, argv); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + g_task_return_boolean (task, TRUE); + } + + g_object_unref (task); } else { + nm_assert (nmc->client == NULL); + nmc->should_wait++; call = g_slice_new0 (CmdCall); - call->nmc = nmc; call->cmd = cmd; call->argc = argc; call->argv = argv; - call->simple = simple; + call->task = task; nm_client_new_async (NULL, got_client, call); } } @@ -1306,16 +1294,13 @@ void nmc_do_cmd (NmCli *nmc, const NMCCommand cmds[], const char *cmd, int argc, char **argv) { const NMCCommand *c; - GSimpleAsyncResult *simple; + gs_unref_object GTask *task = NULL; - simple = g_simple_async_result_new (NULL, - command_done, - nmc, - nmc_do_cmd); + task = nm_g_task_new (NULL, NULL, nmc_do_cmd, command_done, nmc); + g_task_set_task_data (task, nmc, NULL); if (argc == 0 && nmc->complete) { - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + g_task_return_boolean (task, TRUE); return; } @@ -1325,8 +1310,7 @@ nmc_do_cmd (NmCli *nmc, const NMCCommand cmds[], const char *cmd, int argc, char g_print ("%s\n", c->cmd); } nmc_complete_help (cmd); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + g_task_return_boolean (task, TRUE); return; } @@ -1341,32 +1325,26 @@ nmc_do_cmd (NmCli *nmc, const NMCCommand cmds[], const char *cmd, int argc, char nmc_complete_help (*(argv+1)); if (!nmc->complete && c->usage && nmc_arg_is_help (*(argv+1))) { c->usage (); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + g_task_return_boolean (task, TRUE); } else { - call_cmd (nmc, simple, c, argc, argv); + call_cmd (nmc, g_steal_pointer (&task), c, argc, argv); } } else if (cmd) { /* Not a known command. */ if (nmc_arg_is_help (cmd) && c->usage) { c->usage (); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + g_task_return_boolean (task, TRUE); } else { - g_simple_async_result_set_error (simple, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, - _("Error: argument '%s' not understood. Try passing --help instead."), cmd); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + g_task_return_new_error (task, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: argument '%s' not understood. Try passing --help instead."), cmd); } } else if (c->func) { /* No command, run the default handler. */ - call_cmd (nmc, simple, c, argc, argv); + call_cmd (nmc, g_steal_pointer (&task), c, argc, argv); } else { /* No command and no default handler. */ - g_simple_async_result_set_error (simple, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, - _("Error: missing argument. Try passing --help.")); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + g_task_return_new_error (task, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: missing argument. Try passing --help.")); } } @@ -1434,10 +1412,56 @@ nmc_error_get_simple_message (GError *error) /* Return a clear message instead of the obscure D-Bus policy error */ if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED)) return _("access denied"); + if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) + return _("NetworkManager is not running"); else return error->message; } +GVariant * +nmc_dbus_call_sync (NmCli *nmc, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GError **error) +{ + gs_unref_object GDBusConnection *connection = NULL; + gs_free_error GError *local = NULL; + GVariant *result; + + if (nmc->timeout == -1) + nmc->timeout = 90; + + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &local); + if (!connection) { + g_set_error (error, + NMCLI_ERROR, + NMC_RESULT_ERROR_UNKNOWN, + _("Error: error connecting to system bus: %s"), + local->message); + return NULL; + } + + result = g_dbus_connection_call_sync (connection, + "org.freedesktop.NetworkManager", + object_path, + interface_name, + method_name, + parameters, + reply_type, + G_DBUS_CALL_FLAGS_NONE, + nmc->timeout * 1000, + NULL, + error); + + if (error && *error) + g_dbus_error_strip_remote_error (*error); + + return result; +} + /*****************************************************************************/ NM_UTILS_LOOKUP_STR_DEFINE (nm_connectivity_to_string, NMConnectivityState, diff --git a/clients/cli/common.h b/clients/cli/common.h index 688f2819..f8fad8c6 100644 --- a/clients/cli/common.h +++ b/clients/cli/common.h @@ -1,22 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * nmcli - command-line tool for controlling NetworkManager - * Common functions and data shared between files. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2012 - 2014 Red Hat, Inc. + * Copyright (C) 2012 - 2014 Red Hat, Inc. */ #ifndef NMC_COMMON_H @@ -102,4 +86,12 @@ extern const NmcMetaGenericInfo *const metagen_dhcp_config[]; const char *nm_connectivity_to_string (NMConnectivityState connectivity); +GVariant *nmc_dbus_call_sync (NmCli *nmc, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GError **error); + #endif /* NMC_COMMON_H */ diff --git a/clients/cli/connections.c b/clients/cli/connections.c index e365980e..a77c2482 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -657,6 +643,7 @@ _metagen_con_active_general_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) case NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_UUID: return nm_active_connection_get_uuid (ac); case NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEVICES: + case NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_IP_IFACE: { GString *str = NULL; const GPtrArray *devices; @@ -665,10 +652,15 @@ _metagen_con_active_general_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) devices = nm_active_connection_get_devices (ac); if (devices) { for (i = 0; i < devices->len; i++) { - NMDevice *device = devices->pdata[i]; + NMDevice *device = g_ptr_array_index (devices, i); const char *iface; - iface = nm_device_get_iface (device); + if (info->info_type == NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEVICES) { + iface = nm_device_get_iface (device); + } else { + iface = nm_device_get_ip_iface (device); + } + if (!iface) continue; if (!s) { @@ -720,6 +712,7 @@ const NmcMetaGenericInfo *const metagen_con_active_general[_NMC_GENERIC_INFO_TYP _METAGEN_CON_ACTIVE_GENERAL (NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_NAME, "NAME"), _METAGEN_CON_ACTIVE_GENERAL (NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_UUID, "UUID"), _METAGEN_CON_ACTIVE_GENERAL (NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEVICES, "DEVICES"), + _METAGEN_CON_ACTIVE_GENERAL (NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_IP_IFACE, "IP-IFACE"), _METAGEN_CON_ACTIVE_GENERAL (NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_STATE, "STATE"), _METAGEN_CON_ACTIVE_GENERAL (NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEFAULT, "DEFAULT"), _METAGEN_CON_ACTIVE_GENERAL (NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEFAULT6, "DEFAULT6"), @@ -2933,7 +2926,8 @@ do_connection_up (NmCli *nmc, int argc, char **argv) pwds = *argv; } else if (!nmc->complete) { - g_printerr (_("Unknown parameter: %s\n"), *argv); + g_string_printf (nmc->return_text, _("Error: invalid extra argument '%s'."), *argv); + return NMC_RESULT_ERROR_USER_INPUT; } next_arg (nmc, &argc, &argv, NULL); @@ -3135,7 +3129,7 @@ do_connection_down (NmCli *nmc, int argc, char **argv) } if (arg_num == 0) { g_string_printf (nmc->return_text, _("Error: No connection specified.")); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } } @@ -3153,7 +3147,7 @@ do_connection_down (NmCli *nmc, int argc, char **argv) arg_ptr++; if (!arg_num) { g_string_printf (nmc->return_text, _("Error: %s argument is missing."), selector); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } } @@ -3174,7 +3168,7 @@ do_connection_down (NmCli *nmc, int argc, char **argv) if (!found_active_cons) { g_string_printf (nmc->return_text, _("Error: no active connection provided.")); - NMC_RETURN (nmc, NMC_RESULT_ERROR_NOT_FOUND); + return NMC_RESULT_ERROR_NOT_FOUND; } nm_assert (found_active_cons->len > 0); @@ -3320,6 +3314,21 @@ get_valid_settings_array (const char *con_type) return NULL; } +static char * +_construct_property_name (const char *setting_name, + const char *property_name, + NMMetaAccessorModifier modifier) +{ + return g_strdup_printf ("%s%s.%s\n", + ( modifier == NM_META_ACCESSOR_MODIFIER_ADD + ? "+" + : ( modifier == NM_META_ACCESSOR_MODIFIER_DEL + ? "-" + : "")), + setting_name, + property_name); +} + /* get_valid_properties_string: * @array: base properties for the current connection type * @array_slv: slave properties (or ipv4/ipv6 ones) for the current connection type @@ -3337,7 +3346,7 @@ get_valid_settings_array (const char *con_type) static char * get_valid_properties_string (const NMMetaSettingValidPartItem *const*array, const NMMetaSettingValidPartItem *const*array_slv, - char modifier, + NMMetaAccessorModifier modifier, const char *prefix, const char *postfix) { @@ -3379,32 +3388,26 @@ get_valid_properties_string (const NMMetaSettingValidPartItem *const*array, /* Search the array with the arguments of the current property */ for (j = 0; j < setting_info->properties_num; j++) { - char *new; + gs_free char *ss1 = NULL; const char *arg_name; arg_name = setting_info->properties[j]->property_name; /* If required, expand the alias too */ - if (!postfix && setting_info->alias) { - if (modifier) - g_string_append_c (str, modifier); - new = g_strdup_printf ("%s.%s\n", - setting_info->alias, - arg_name); - g_string_append (str, new); - g_free (new); + if ( !postfix + && setting_info->alias) { + gs_free char *ss2 = NULL; + + ss2 = _construct_property_name (setting_info->alias, arg_name, modifier); + g_string_append (str, ss2); } - if (postfix && !g_str_has_prefix (arg_name, postfix)) + if ( postfix + && !g_str_has_prefix (arg_name, postfix)) continue; - if (modifier) - g_string_append_c (str, modifier); - new = g_strdup_printf ("%s.%s\n", - prop_name, - arg_name); - g_string_append (str, new); - g_free (new); + ss1 = _construct_property_name (prop_name, arg_name, modifier); + g_string_append (str, ss1); } } } @@ -3723,50 +3726,56 @@ static char * unique_master_iface_ifname (const GPtrArray *connections, const char *try_name) { - NMConnection *connection; char *new_name; - unsigned num = 1; - int i = 0; - const char *ifname = NULL; + guint num = 0; + guint i; new_name = g_strdup (try_name); - while (i < connections->len) { - connection = NM_CONNECTION (connections->pdata[i]); - ifname = nm_connection_get_interface_name (connection); - if (g_strcmp0 (new_name, ifname) == 0) { + +again: + for (i = 0; i < connections->len; i++) { + NMConnection *connection = connections->pdata[i]; + + if (nm_streq0 (new_name, nm_connection_get_interface_name (connection))) { + num++; g_free (new_name); - new_name = g_strdup_printf ("%s%d", try_name, num++); - i = 0; - } else - i++; + new_name = g_strdup_printf ("%s%u", try_name, num); + goto again; + } } return new_name; } static void -set_default_interface_name (NmCli *nmc, NMSettingConnection *s_con) +set_default_interface_name (NmCli *nmc, + NMSettingConnection *s_con) { - const GPtrArray *connections; - char *ifname = NULL; - const char *con_type = nm_setting_connection_get_connection_type (s_con); + const char *default_name; + const char *con_type; if (nm_setting_connection_get_interface_name (s_con)) return; - connections = nm_client_get_connections (nmc->client); + con_type = nm_setting_connection_get_connection_type (s_con); /* Set a sensible bond/team/bridge interface name by default */ - if (g_strcmp0 (con_type, NM_SETTING_BOND_SETTING_NAME) == 0) - ifname = unique_master_iface_ifname (connections, "nm-bond"); - else if (g_strcmp0 (con_type, NM_SETTING_TEAM_SETTING_NAME) == 0) - ifname = unique_master_iface_ifname (connections, "nm-team"); - else if (g_strcmp0 (con_type, NM_SETTING_BRIDGE_SETTING_NAME) == 0) - ifname = unique_master_iface_ifname (connections, "nm-bridge"); + if (nm_streq0 (con_type, NM_SETTING_BOND_SETTING_NAME)) + default_name = "nm-bond"; + else if (nm_streq0 (con_type, NM_SETTING_TEAM_SETTING_NAME)) + default_name = "nm-team"; + else if (nm_streq0 (con_type, NM_SETTING_BRIDGE_SETTING_NAME)) + default_name = "nm-bridge"; else - return; + default_name = NULL; + + if (default_name) { + const GPtrArray *connections; + gs_free char *ifname = NULL; - g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, NULL); - g_free (ifname); + connections = nm_client_get_connections (nmc->client); + ifname = unique_master_iface_ifname (connections, default_name); + g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, NULL); + } } /*****************************************************************************/ @@ -4004,7 +4013,7 @@ set_property (NMClient *client, const char *setting_name, const char *property, const char *value, - char modifier, + NMMetaAccessorModifier modifier, GError **error) { gs_free char *property_name = NULL; @@ -4012,7 +4021,9 @@ set_property (NMClient *client, NMSetting *setting; nm_assert (setting_name && setting_name[0]); - nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); + nm_assert (NM_IN_SET (modifier, NM_META_ACCESSOR_MODIFIER_SET, + NM_META_ACCESSOR_MODIFIER_ADD, + NM_META_ACCESSOR_MODIFIER_DEL)); setting = nm_connection_get_setting_by_name (connection, setting_name); if (!setting) { @@ -4032,14 +4043,15 @@ set_property (NMClient *client, if (!nmc_setting_set_property (client, setting, property_name, - ( (modifier == '-' && !value) - ? '\0' + ( ( modifier == NM_META_ACCESSOR_MODIFIER_DEL + && !value) + ? NM_META_ACCESSOR_MODIFIER_SET : modifier), value, &local)) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("Error: failed to %s %s.%s: %s."), - ( modifier != '-' + ( modifier != NM_META_ACCESSOR_MODIFIER_DEL ? "modify" : "remove a value from"), setting_name, @@ -4069,8 +4081,15 @@ 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 (nmc->client, connection, setting_name, property_name, - value, inf_flags & NM_META_PROPERTY_INF_FLAG_MULTI ? '+' : '\0', error); + return set_property (nmc->client, + connection, + setting_name, + property_name, + value, + inf_flags & NM_META_PROPERTY_INF_FLAG_MULTI + ? NM_META_ACCESSOR_MODIFIER_ADD + : NM_META_ACCESSOR_MODIFIER_SET, + error); } else if (inf_flags & NM_META_PROPERTY_INF_FLAG_REQD) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("Error: '%s' is mandatory."), option_name); @@ -4191,9 +4210,13 @@ set_connection_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, co } if (slave_type) { - if (!set_property (nmc->client, con, NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, - '\0', error)) { + if (!set_property (nmc->client, + con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE, + slave_type, + NM_META_ACCESSOR_MODIFIER_SET, + error)) { return FALSE; } enable_options (NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_MASTER, master); @@ -4208,7 +4231,13 @@ set_connection_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, co NM_SETTING_CONNECTION_INTERFACE_NAME); } - if (!set_property (nmc->client, 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, + NM_META_ACCESSOR_MODIFIER_SET, + error)) return FALSE; if (!con_settings (con, &type_settings, &slv_settings, error)) @@ -4237,7 +4266,13 @@ set_connection_iface (NmCli *nmc, NMConnection *con, const OptionInfo *option, c } } - return set_property (nmc->client, 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, + NM_META_ACCESSOR_MODIFIER_SET, + error); } static gboolean @@ -4260,13 +4295,23 @@ 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 (nmc->client, con, NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, - '\0', error)) { + if (!set_property (nmc->client, + con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE, + slave_type, + NM_META_ACCESSOR_MODIFIER_SET, + error)) { return FALSE; } - return set_property (nmc->client, 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, + NM_META_ACCESSOR_MODIFIER_SET, + error); } static gboolean @@ -4380,7 +4425,13 @@ set_bluetooth_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, con return FALSE; } - return set_property (nmc->client, 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, + NM_META_ACCESSOR_MODIFIER_SET, + error); } static gboolean @@ -4399,8 +4450,13 @@ 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 (nmc->client, con, option->setting_info->general->setting_name, option->property, value, - '+', error); + return set_property (nmc->client, + con, + option->setting_info->general->setting_name, + option->property, + value, + NM_META_ACCESSOR_MODIFIER_ADD, + error); } static gboolean @@ -4419,8 +4475,13 @@ 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 (nmc->client, con, option->setting_info->general->setting_name, option->property, value, - '+', error); + return set_property (nmc->client, + con, + option->setting_info->general->setting_name, + option->property, + value, + NM_META_ACCESSOR_MODIFIER_ADD, + error); } /*****************************************************************************/ @@ -4492,7 +4553,7 @@ option_relevant (NMConnection *connection, const NMMetaAbstractInfo *abstract_in static void complete_property_name (NmCli *nmc, NMConnection *connection, - char modifier, + NMMetaAccessorModifier modifier, const char *prefix, const char *postfix) { @@ -4515,7 +4576,7 @@ complete_property_name (NmCli *nmc, NMConnection *connection, if (word_list) g_print ("%s", word_list); - if (modifier != '\0') + if (modifier != NM_META_ACCESSOR_MODIFIER_SET) return; for (s = 0; s < _NM_META_SETTING_TYPE_NUM; s++) { @@ -4644,20 +4705,18 @@ nmc_read_connection_properties (NmCli *nmc, char ***argv, GError **error) { - const char *option; - const char *value = NULL; - GError *local = NULL; - /* First check if we have a slave-type, as this would mean we will not * have ip properties but possibly others, slave-type specific. */ /* Go through arguments and set properties */ do { - const NMMetaAbstractInfo *chosen = NULL; - gs_strfreev char **strv = NULL; const NMMetaSettingValidPartItem *const*type_settings; const NMMetaSettingValidPartItem *const*slv_settings; - char modifier = '\0'; + NMMetaAccessorModifier modifier; + const char *option_orig; + const char *option; + const char *value = NULL; + const char *tmp; if (!con_settings (connection, &type_settings, &slv_settings, error)) return FALSE; @@ -4665,54 +4724,58 @@ nmc_read_connection_properties (NmCli *nmc, ensure_settings (connection, slv_settings); ensure_settings (connection, type_settings); - option = **argv; - if (!option) { + option_orig = **argv; + if (!option_orig) { g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("Error: <setting>.<property> argument is missing.")); return FALSE; } - if (option[0] == '+' || option[0] == '-') - modifier = *option; + switch (option_orig[0]) { + case '+': modifier = NM_META_ACCESSOR_MODIFIER_ADD; option = &option_orig[1]; break; + case '-': modifier = NM_META_ACCESSOR_MODIFIER_DEL; option = &option_orig[1]; break; + default: modifier = NM_META_ACCESSOR_MODIFIER_SET; option = option_orig; break; + } + + if ((tmp = strchr (option, '.'))) { + gs_free char *option_sett = g_strndup (option, tmp - option); + const char *option_prop = &tmp[1]; + const char *option_sett_expanded; + GError *local = NULL; - strv = g_strsplit (option, ".", 2); - if (g_strv_length (strv) == 2) { /* This seems like a <setting>.<property> (such as "connection.id" or "bond.mode"), * optionally prefixed with "+| or "-". */ - char *setting = strv[0]; - const char *setting_name; - if (modifier) - setting++; + if ( *argc == 1 + && nmc->complete) + complete_property_name (nmc, connection, modifier, option_sett, option_prop); - if (*argc == 1 && nmc->complete) - complete_property_name (nmc, connection, modifier, setting, strv[1]); - - setting_name = check_valid_name (setting, type_settings, slv_settings, &local); - if (!setting_name) { + option_sett_expanded = check_valid_name (option_sett, type_settings, slv_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."), - setting, local->message); + option_sett, local->message); g_clear_error (&local); return FALSE; } (*argc)--; (*argv)++; - if (!get_value (&value, argc, argv, option, error)) + if (!get_value (&value, argc, argv, option_orig, error)) return FALSE; if (!*argc && nmc->complete) { - complete_property (nmc, setting, strv[1], value ?: "", connection); + complete_property (nmc, option_sett, option_prop, value ?: "", connection); return TRUE; } - if (!set_property (nmc->client, connection, setting_name, strv[1], value, modifier, error)) + if (!set_property (nmc->client, connection, option_sett_expanded, option_prop, value, modifier, error)) return FALSE; } else { - NMMetaSettingType s; + const NMMetaAbstractInfo *chosen = NULL; const char *chosen_setting_name = NULL; const char *chosen_option = NULL; + NMMetaSettingType s; /* Let's see if this is an property alias (such as "id", "mode", "type" or "con-name")*/ for (s = 0; s < _NM_META_SETTING_TYPE_NUM; s++) { @@ -4768,8 +4831,6 @@ nmc_read_connection_properties (NmCli *nmc, } if (!chosen) { - if (modifier) - option++; if (*argc == 1 && nmc->complete) complete_property_name (nmc, connection, modifier, option, NULL); g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, @@ -4782,7 +4843,7 @@ nmc_read_connection_properties (NmCli *nmc, (*argc)--; (*argv)++; - if (!get_value (&value, argc, argv, option, error)) + if (!get_value (&value, argc, argv, option_orig, error)) return FALSE; if (!*argc && nmc->complete) @@ -5270,11 +5331,12 @@ read_properties: const char *ifname = nm_setting_connection_get_interface_name (s_con); const char *type = nm_setting_connection_get_connection_type (s_con); const char *slave_type = nm_setting_connection_get_slave_type (s_con); - char *try_name, *default_name; /* If only bother when there's a type, which is not guaranteed at this point. * Otherwise the validation will fail anyway. */ if (type) { + gs_free char *try_name = NULL; + gs_free char *default_name = NULL; const GPtrArray *connections; connections = nm_client_get_connections (nmc->client); @@ -5282,9 +5344,7 @@ read_properties: ? g_strdup_printf ("%s-%s", get_name_alias_toplevel (type, slave_type), ifname) : g_strdup (get_name_alias_toplevel (type, slave_type)); default_name = nmc_unique_connection_name (connections, try_name); - g_free (try_name); g_object_set (s_con, NM_SETTING_CONNECTION_ID, default_name, NULL); - g_free (default_name); } } @@ -6980,8 +7040,8 @@ property_edit_submenu (NmCli *nmc, curr_setting, prop_name, (cmdsub == NMC_EDITOR_SUB_CMD_SET) - ? '\0' - : '+', + ? NM_META_ACCESSOR_MODIFIER_SET + : NM_META_ACCESSOR_MODIFIER_ADD, prop_val_user, &tmp_err); if (!set_result) { @@ -6997,7 +7057,12 @@ property_edit_submenu (NmCli *nmc, _("Edit '%s' value: "), prop_name); - if (!nmc_setting_set_property (nmc->client, curr_setting, prop_name, '\0', prop_val_user, &tmp_err)) { + if (!nmc_setting_set_property (nmc->client, + curr_setting, + prop_name, + NM_META_ACCESSOR_MODIFIER_SET, + 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); } @@ -7008,8 +7073,8 @@ property_edit_submenu (NmCli *nmc, curr_setting, prop_name, ( cmd_property_arg - ? '-' - : '\0'), + ? NM_META_ACCESSOR_MODIFIER_DEL + : NM_META_ACCESSOR_MODIFIER_SET), cmd_property_arg, &tmp_err)) { g_print (_("Error: %s\n"), tmp_err->message); @@ -7363,7 +7428,12 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t _("Enter '%s' value: "), prop_name); - if (!nmc_setting_set_property (nmc->client, menu_ctx.curr_setting, prop_name, '+', prop_val_user, &tmp_err)) { + if (!nmc_setting_set_property (nmc->client, + menu_ctx.curr_setting, + prop_name, + NM_META_ACCESSOR_MODIFIER_ADD, + 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); } @@ -7427,7 +7497,9 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t if (!nmc_setting_set_property (nmc->client, ss, prop_name, - cmd_arg_v ? '+' : '\0', + cmd_arg_v + ? NM_META_ACCESSOR_MODIFIER_ADD + : NM_META_ACCESSOR_MODIFIER_SET, cmd_arg_v, &tmp_err)) { g_print (_("Error: failed to set '%s' property: %s\n"), @@ -7526,7 +7598,12 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t if (!prop_name) break; - if (!nmc_setting_set_property (nmc->client, menu_ctx.curr_setting, prop_name, '\0', NULL, &tmp_err)) { + if (!nmc_setting_set_property (nmc->client, + menu_ctx.curr_setting, + prop_name, + NM_META_ACCESSOR_MODIFIER_SET, + NULL, + &tmp_err)) { g_print (_("Error: failed to remove value of '%s': %s\n"), prop_name, tmp_err->message); g_clear_error (&tmp_err); @@ -7572,11 +7649,16 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t } } else { gs_free char *prop_name = NULL; - gs_free GError *tmp_err = NULL; + gs_free_error GError *tmp_err = NULL; prop_name = is_property_valid (ss, cmd_arg_p, &tmp_err); if (prop_name) { - if (!nmc_setting_set_property (nmc->client, ss, prop_name, '\0', NULL, &tmp_err)) { + if (!nmc_setting_set_property (nmc->client, + ss, + prop_name, + NM_META_ACCESSOR_MODIFIER_SET, + NULL, + &tmp_err)) { g_print (_("Error: failed to remove value of '%s': %s\n"), prop_name, tmp_err->message); @@ -7931,6 +8013,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t ap_nsp = ap_nsp && ap_nsp[0] == '/' ? ap_nsp + 1 : ap_nsp; if (is_connection_dirty (connection, rem_con)) { + /* TRANSLATORS: do not translate 'save', leave it as it is */ g_print (_("Error: connection is not saved. Type 'save' first.\n")); break; } @@ -8220,7 +8303,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) else { if (!nmc_parse_args (exp_args, TRUE, &argc, &argv, &error)) { g_string_assign (nmc->return_text, error->message); - NMC_RETURN (nmc, error->code); + return error->code; } } @@ -8250,7 +8333,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) } else { g_string_printf (nmc->return_text, _("Error: only one of 'id', 'filename', uuid, or 'path' can be provided.")); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } } @@ -8264,7 +8347,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) if (!found_con) { g_string_printf (nmc->return_text, _("Error: Unknown connection '%s'."), con); - NMC_RETURN (nmc, NMC_RESULT_ERROR_NOT_FOUND); + return NMC_RESULT_ERROR_NOT_FOUND; } /* Duplicate the connection and use that so that we need not @@ -8354,10 +8437,13 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) else g_print (_("Adding a new '%s' connection"), connection_type); g_print ("\n\n"); + /* TRANSLATORS: do not translate 'help', leave it as it is */ g_print (_("Type 'help' or '?' for available commands.")); g_print ("\n"); + /* TRANSLATORS: do not translate 'print', leave it as it is */ g_print (_("Type 'print' to show all the connection properties.")); g_print ("\n"); + /* TRANSLATORS: do not translate 'describe', leave it as it is */ g_print (_("Type 'describe [<setting>.<prop>]' for detailed property description.")); g_print ("\n\n"); @@ -8418,7 +8504,7 @@ do_connection_modify (NmCli *nmc, connection = get_connection (nmc, &argc, &argv, NULL, NULL, NULL, &error); if (!connection) { g_string_printf (nmc->return_text, _("Error: %s."), error->message); - NMC_RETURN (nmc, error->code); + return error->code; } rc = nm_client_get_connection_by_uuid (nmc->client, @@ -8426,12 +8512,12 @@ do_connection_modify (NmCli *nmc, if (!rc) { g_string_printf (nmc->return_text, _("Error: Unknown connection '%s'."), nm_connection_get_uuid (connection)); - NMC_RETURN (nmc, NMC_RESULT_ERROR_NOT_FOUND); + return NMC_RESULT_ERROR_NOT_FOUND; } if (!nmc_read_connection_properties (nmc, NM_CONNECTION (rc), &argc, &argv, &error)) { g_string_assign (nmc->return_text, error->message); - NMC_RETURN (nmc, error->code); + return error->code; } if (nmc->complete) @@ -8509,7 +8595,7 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) connection = get_connection (nmc, argc_ptr, argv_ptr, NULL, NULL, NULL, &error); if (!connection) { g_string_printf (nmc->return_text, _("Error: %s."), error->message); - NMC_RETURN (nmc, error->code); + return error->code; } if (nmc->complete) @@ -8522,12 +8608,12 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) _("New connection name: ")); } else { g_string_printf (nmc->return_text, _("Error: <new name> argument is missing.")); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } if (next_arg (nmc->ask ? NULL : nmc, argc_ptr, argv_ptr, NULL) == 0) { g_string_printf (nmc->return_text, _("Error: unknown extra argument: '%s'."), *argv); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } new_connection = nm_simple_connection_new_clone (connection); @@ -8769,17 +8855,24 @@ do_connection_monitor (NmCli *nmc, int argc, char **argv) static NMCResultCode do_connection_reload (NmCli *nmc, int argc, char **argv) { - GError *error = NULL; + gs_unref_variant GVariant *result = NULL; + gs_free_error GError *error = NULL; next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; - if (!nm_client_reload_connections (nmc->client, NULL, &error)) { + result = nmc_dbus_call_sync (nmc, + "/org/freedesktop/NetworkManager/Settings", + "org.freedesktop.NetworkManager.Settings", + "ReloadConnections", + g_variant_new ("()"), + G_VARIANT_TYPE("(b)"), + &error); + if (error) { g_string_printf (nmc->return_text, _("Error: failed to reload connections: %s."), nmc_error_get_simple_message (error)); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; - g_clear_error (&error); } return nmc->return_value; @@ -8858,7 +8951,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) filename = nm_strstrip (filename_ask); } else { g_string_printf (nmc->return_text, _("Error: No arguments provided.")); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } } @@ -8874,7 +8967,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) argv++; if (!argc) { g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1)); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } if ( argc == 1 @@ -8895,7 +8988,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) argv++; if (!argc) { g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1)); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } if (argc == 1 && nmc->complete) nmc->return_value = NMC_RESULT_COMPLETE_FILE; @@ -8904,8 +8997,8 @@ do_connection_import (NmCli *nmc, int argc, char **argv) else g_printerr (_("Warning: 'file' already specified, ignoring extra one.\n")); } else { - g_string_printf (nmc->return_text, _("Unknown parameter: %s"), *argv); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + g_string_printf (nmc->return_text, _("Error: invalid extra argument '%s'."), *argv); + return NMC_RESULT_ERROR_USER_INPUT; } next_arg (nmc, &argc, &argv, NULL); @@ -8916,11 +9009,11 @@ do_connection_import (NmCli *nmc, int argc, char **argv) if (!type) { g_string_printf (nmc->return_text, _("Error: 'type' argument is required.")); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } if (!filename) { g_string_printf (nmc->return_text, _("Error: 'file' argument is required.")); - NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); + return NMC_RESULT_ERROR_USER_INPUT; } if (nm_streq (type, "wireguard")) @@ -8929,7 +9022,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) 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); + return NMC_RESULT_ERROR_UNKNOWN; } /* Import VPN configuration */ @@ -8937,7 +9030,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) if (!plugin) { g_string_printf (nmc->return_text, _("Error: failed to load VPN plugin: %s."), error->message); - NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN); + return NMC_RESULT_ERROR_UNKNOWN; } connection = nm_vpn_editor_plugin_import (plugin, filename, &error); @@ -8946,7 +9039,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) if (!connection) { g_string_printf (nmc->return_text, _("Error: failed to import '%s': %s."), filename, error->message); - NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN); + return NMC_RESULT_ERROR_UNKNOWN; } add_connection (nmc->client, @@ -9169,7 +9262,7 @@ static const NMCCommand connection_cmds[] = { { "add", do_connection_add, usage_connection_add, TRUE, TRUE }, { "edit", do_connection_edit, usage_connection_edit, TRUE, TRUE }, { "delete", do_connection_delete, usage_connection_delete, TRUE, TRUE }, - { "reload", do_connection_reload, usage_connection_reload, TRUE, TRUE }, + { "reload", do_connection_reload, usage_connection_reload, FALSE, FALSE }, { "load", do_connection_load, usage_connection_load, TRUE, TRUE }, { "modify", do_connection_modify, usage_connection_modify, TRUE, TRUE }, { "clone", do_connection_clone, usage_connection_clone, TRUE, TRUE }, diff --git a/clients/cli/connections.h b/clients/cli/connections.h index 122a7e27..7fa9d448 100644 --- a/clients/cli/connections.h +++ b/clients/cli/connections.h @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #ifndef NMC_CONNECTIONS_H diff --git a/clients/cli/devices.c b/clients/cli/devices.c index c00d3191..c99efd0d 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -169,6 +155,8 @@ _metagen_device_detail_general_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) return nm_device_get_type_description (d); case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE: return G_OBJECT_TYPE_NAME (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DBUS_PATH: + return nm_object_get_path (NM_OBJECT (d)); case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR: return nm_device_get_vendor (d); case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT: @@ -250,6 +238,7 @@ const NmcMetaGenericInfo *const metagen_device_detail_general[_NMC_GENERIC_INFO_ _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE, "DEVICE"), _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE, "TYPE"), _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE, "NM-TYPE"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DBUS_PATH, "DBUS-PATH"), _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR, "VENDOR"), _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT, "PRODUCT"), _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER, "DRIVER"), @@ -539,6 +528,9 @@ _metagen_device_detail_wifi_properties_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_AR case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_MESH: return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_MESH), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_IBSS_RSN: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_IBSS_RSN), + get_type); default: break; } @@ -549,16 +541,55 @@ _metagen_device_detail_wifi_properties_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_AR const NmcMetaGenericInfo *const metagen_device_detail_wifi_properties[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_NUM + 1] = { #define _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(type, name) \ [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_wifi_properties_get_fcn) - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP, "WEP"), - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA, "WPA"), - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2, "WPA2"), - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP, "TKIP"), - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP, "CCMP"), - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP, "AP"), - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC, "ADHOC"), - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ, "2GHZ"), - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ, "5GHZ"), - _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_MESH, "MESH"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP, "WEP"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA, "WPA"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2, "WPA2"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP, "TKIP"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP, "CCMP"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP, "AP"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC, "ADHOC"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ, "2GHZ"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ, "5GHZ"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_MESH, "MESH"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_IBSS_RSN, "IBSS-RSN"), +}; + + +/*****************************************************************************/ + +static gconstpointer +_metagen_device_detail_interface_flags_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMDevice *d = target; + NMDeviceInterfaceFlags flags; + + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); + + flags = nm_device_get_interface_flags (d); + + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_UP: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (flags, NM_DEVICE_INTERFACE_FLAG_UP), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_LOWER_UP: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (flags, NM_DEVICE_INTERFACE_FLAG_LOWER_UP), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_CARRIER: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (flags, NM_DEVICE_INTERFACE_FLAG_CARRIER), + get_type); + default: + break; + } + + g_return_val_if_reached (NULL); +} + +const NmcMetaGenericInfo *const metagen_device_detail_interface_flags[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_NUM + 1] = { +#define _METAGEN_DEVICE_DETAIL_INTERFACE_FLAGS(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_interface_flags_get_fcn) + _METAGEN_DEVICE_DETAIL_INTERFACE_FLAGS (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_UP, "UP"), + _METAGEN_DEVICE_DETAIL_INTERFACE_FLAGS (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_LOWER_UP, "LOWER-UP"), + _METAGEN_DEVICE_DETAIL_INTERFACE_FLAGS (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_CARRIER, "CARRIER"), }; /*****************************************************************************/ @@ -593,7 +624,7 @@ const NmcMetaGenericInfo *const nmc_fields_dev_wifi_list[] = { NMC_META_GENERIC ("DBUS-PATH"), /* 16 */ NULL, }; -#define NMC_FIELDS_DEV_WIFI_LIST_COMMON "IN-USE,SSID,MODE,CHAN,RATE,SIGNAL,BARS,SECURITY" +#define NMC_FIELDS_DEV_WIFI_LIST_COMMON "IN-USE,BSSID,SSID,MODE,CHAN,RATE,SIGNAL,BARS,SECURITY" #define NMC_FIELDS_DEV_WIFI_LIST_FOR_DEV_LIST "NAME,"NMC_FIELDS_DEV_WIFI_LIST_COMMON const NmcMetaGenericInfo *const nmc_fields_dev_wimax_list[] = { @@ -641,23 +672,24 @@ const NmcMetaGenericInfo *const nmc_fields_dev_show_bluetooth[] = { /* Available sections for 'device show' */ const NmcMetaGenericInfo *const nmc_fields_dev_show_sections[] = { - NMC_META_GENERIC_WITH_NESTED ("GENERAL", metagen_device_detail_general), /* 0 */ - NMC_META_GENERIC_WITH_NESTED ("CAPABILITIES", metagen_device_detail_capabilities), /* 1 */ - NMC_META_GENERIC_WITH_NESTED ("WIFI-PROPERTIES", metagen_device_detail_wifi_properties), /* 2 */ - NMC_META_GENERIC_WITH_NESTED ("AP", nmc_fields_dev_wifi_list + 1), /* 3 */ - NMC_META_GENERIC_WITH_NESTED ("WIRED-PROPERTIES", metagen_device_detail_wired_properties), /* 4 */ - NMC_META_GENERIC_WITH_NESTED ("WIMAX-PROPERTIES", metagen_device_detail_wimax_properties), /* 5 */ - NMC_META_GENERIC_WITH_NESTED ("NSP", nmc_fields_dev_wimax_list + 1), /* 6 */ - NMC_META_GENERIC_WITH_NESTED ("IP4", metagen_ip4_config), /* 7 */ - NMC_META_GENERIC_WITH_NESTED ("DHCP4", metagen_dhcp_config), /* 8 */ - NMC_META_GENERIC_WITH_NESTED ("IP6", metagen_ip6_config), /* 9 */ - NMC_META_GENERIC_WITH_NESTED ("DHCP6", metagen_dhcp_config), /* 10 */ - NMC_META_GENERIC_WITH_NESTED ("BOND", nmc_fields_dev_show_master_prop + 1), /* 11 */ - NMC_META_GENERIC_WITH_NESTED ("TEAM", nmc_fields_dev_show_team_prop + 1), /* 12 */ - NMC_META_GENERIC_WITH_NESTED ("BRIDGE", nmc_fields_dev_show_master_prop + 1), /* 13 */ - NMC_META_GENERIC_WITH_NESTED ("VLAN", nmc_fields_dev_show_vlan_prop + 1), /* 14 */ - NMC_META_GENERIC_WITH_NESTED ("BLUETOOTH", nmc_fields_dev_show_bluetooth + 1), /* 15 */ - NMC_META_GENERIC_WITH_NESTED ("CONNECTIONS", metagen_device_detail_connections), /* 16 */ + NMC_META_GENERIC_WITH_NESTED ("GENERAL", metagen_device_detail_general), /* 0 */ + NMC_META_GENERIC_WITH_NESTED ("CAPABILITIES", metagen_device_detail_capabilities), /* 1 */ + NMC_META_GENERIC_WITH_NESTED ("INTERFACE-FLAGS", metagen_device_detail_interface_flags), /* 2 */ + NMC_META_GENERIC_WITH_NESTED ("WIFI-PROPERTIES", metagen_device_detail_wifi_properties), /* 3 */ + NMC_META_GENERIC_WITH_NESTED ("AP", nmc_fields_dev_wifi_list + 1), /* 4 */ + NMC_META_GENERIC_WITH_NESTED ("WIRED-PROPERTIES", metagen_device_detail_wired_properties), /* 5 */ + NMC_META_GENERIC_WITH_NESTED ("WIMAX-PROPERTIES", metagen_device_detail_wimax_properties), /* 6 */ + NMC_META_GENERIC_WITH_NESTED ("NSP", nmc_fields_dev_wimax_list + 1), /* 7 */ + NMC_META_GENERIC_WITH_NESTED ("IP4", metagen_ip4_config), /* 8 */ + NMC_META_GENERIC_WITH_NESTED ("DHCP4", metagen_dhcp_config), /* 9 */ + NMC_META_GENERIC_WITH_NESTED ("IP6", metagen_ip6_config), /* 10 */ + NMC_META_GENERIC_WITH_NESTED ("DHCP6", metagen_dhcp_config), /* 11 */ + NMC_META_GENERIC_WITH_NESTED ("BOND", nmc_fields_dev_show_master_prop + 1), /* 12 */ + NMC_META_GENERIC_WITH_NESTED ("TEAM", nmc_fields_dev_show_team_prop + 1), /* 13 */ + NMC_META_GENERIC_WITH_NESTED ("BRIDGE", nmc_fields_dev_show_master_prop + 1), /* 14 */ + NMC_META_GENERIC_WITH_NESTED ("VLAN", nmc_fields_dev_show_vlan_prop + 1), /* 15 */ + NMC_META_GENERIC_WITH_NESTED ("BLUETOOTH", nmc_fields_dev_show_bluetooth + 1), /* 16 */ + NMC_META_GENERIC_WITH_NESTED ("CONNECTIONS", metagen_device_detail_connections), /* 17 */ NULL, }; #define NMC_FIELDS_DEV_SHOW_SECTIONS_COMMON "GENERAL.DEVICE,GENERAL.TYPE,GENERAL.HWADDR,GENERAL.MTU,GENERAL.STATE,"\ @@ -706,6 +738,7 @@ usage (void) " [bssid <BSSID>] [name <name>] [private yes|no] [hidden yes|no]\n\n" " wifi hotspot [ifname <ifname>] [con-name <name>] [ssid <SSID>] [band a|bg] [channel <channel>] [password <password>]\n\n" " wifi rescan [ifname <ifname>] [[ssid <SSID to scan>] ...]\n\n" + " wifi show-password [ifname <ifname>]\n\n" " lldp [list [ifname <ifname>]]\n\n" )); } @@ -756,7 +789,7 @@ usage_device_reapply (void) "ARGUMENTS := <ifname>\n" "\n" "Attempts to update device with changes to the currently active connection\n" - "made since it was last applied.\n\n")); + "made since it was last applied.\n\n")); } static void @@ -1470,6 +1503,20 @@ show_device_info (NMDevice *device, NmCli *nmc) continue; } + if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_interface_flags) { + gs_free char *f = section_fld ? g_strdup_printf ("INTERFACE-FLAGS.%s", section_fld) : NULL; + + nmc_print (&nmc->nmc_config, + (gpointer[]) { device, NULL }, + NULL, + NULL, + NMC_META_GENERIC_GROUP ("INTERFACE-FLAGS", metagen_device_detail_interface_flags, N_("NAME")), + f, + NULL); + was_output = TRUE; + continue; + } + if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_wifi_properties) { if (NM_IS_DEVICE_WIFI (device)) { gs_free char *f = section_fld ? g_strdup_printf ("WIFI-PROPERTIES.%s", section_fld) : NULL; @@ -1493,7 +1540,7 @@ show_device_info (NMDevice *device, NmCli *nmc) GPtrArray *aps; /* section AP */ - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[3]->name)) { + if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[4]->name)) { NMC_OUTPUT_DATA_DEFINE_SCOPED (out); if (state == NM_DEVICE_STATE_ACTIVATED) { @@ -1551,42 +1598,42 @@ show_device_info (NMDevice *device, NmCli *nmc) dhcp6 = nm_device_get_dhcp6_config (device); /* IP4 */ - if (cfg4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[7]->name)) + if (cfg4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[8]->name)) was_output = print_ip_config (cfg4, AF_INET, &nmc->nmc_config, section_fld); /* DHCP4 */ - if (dhcp4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[8]->name)) + if (dhcp4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[9]->name)) was_output = print_dhcp_config (dhcp4, AF_INET, &nmc->nmc_config, section_fld); /* IP6 */ - if (cfg6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[9]->name)) + if (cfg6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[10]->name)) was_output = print_ip_config (cfg6, AF_INET6, &nmc->nmc_config, section_fld); /* DHCP6 */ - if (dhcp6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[10]->name)) + if (dhcp6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[11]->name)) was_output = print_dhcp_config (dhcp6, AF_INET6, &nmc->nmc_config, section_fld); /* Bond specific information */ if (NM_IS_DEVICE_BOND (device)) { - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[11]->name)) - was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[11]->name, section_fld); + if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[12]->name)) + was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[12]->name, section_fld); } /* Team specific information */ if (NM_IS_DEVICE_TEAM (device)) { - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[12]->name)) - was_output = print_team_info (device, nmc, nmc_fields_dev_show_sections[12]->name, section_fld); + if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[13]->name)) + was_output = print_team_info (device, nmc, nmc_fields_dev_show_sections[13]->name, section_fld); } /* Bridge specific information */ if (NM_IS_DEVICE_BRIDGE (device)) { - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[13]->name)) - was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[13]->name, section_fld); + if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[14]->name)) + was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[14]->name, section_fld); } /* VLAN-specific information */ if ((NM_IS_DEVICE_VLAN (device))) { - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[14]->name)) { + if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[15]->name)) { char * vlan_id_str = g_strdup_printf ("%u", nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device))); NMDevice *parent = nm_device_vlan_get_parent (NM_DEVICE_VLAN (device)); NMC_OUTPUT_DATA_DEFINE_SCOPED (out); @@ -1598,7 +1645,7 @@ show_device_info (NMDevice *device, NmCli *nmc) g_ptr_array_add (out.output_data, arr); arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, nmc_fields_dev_show_sections[14]->name); /* "VLAN" */ + set_val_strc (arr, 0, nmc_fields_dev_show_sections[15]->name); /* "VLAN" */ set_val_strc (arr, 1, parent ? nm_device_get_iface (parent) : NULL); set_val_str (arr, 2, vlan_id_str); g_ptr_array_add (out.output_data, arr); @@ -1611,7 +1658,7 @@ show_device_info (NMDevice *device, NmCli *nmc) } if (NM_IS_DEVICE_BT (device)) { - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[15]->name)) { + if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[16]->name)) { NMC_OUTPUT_DATA_DEFINE_SCOPED (out); tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_bluetooth; @@ -1621,7 +1668,7 @@ show_device_info (NMDevice *device, NmCli *nmc) g_ptr_array_add (out.output_data, arr); arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, nmc_fields_dev_show_sections[15]->name); /* "BLUETOOTH" */ + set_val_strc (arr, 0, nmc_fields_dev_show_sections[16]->name); /* "BLUETOOTH" */ set_val_str (arr, 1, bluetooth_caps_to_string (nm_device_bt_get_capabilities (NM_DEVICE_BT (device)))); g_ptr_array_add (out.output_data, arr); @@ -1681,9 +1728,9 @@ do_devices_status (NmCli *nmc, int argc, char **argv) if (nmc->complete) return nmc->return_value; - while (argc > 0) { - g_printerr (_("Unknown parameter: %s\n"), *argv); - next_arg (nmc, &argc, &argv, NULL); + if (argc) { + g_string_printf (nmc->return_text, _("Error: invalid extra argument '%s'."), *argv); + return NMC_RESULT_ERROR_USER_INPUT; } if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) @@ -1741,7 +1788,7 @@ do_device_show (NmCli *nmc, int argc, char **argv) int i; /* nmc_do_cmd() should not call this with argc=0. */ - g_assert (!nmc->complete); + nm_assert (!nmc->complete); /* Show details for all devices */ for (i = 0; devices[i]; i++) { @@ -1780,33 +1827,56 @@ progress_cb (gpointer user_data) return TRUE; } -static void connected_state_cb (NMDevice *device, NMActiveConnection *active); +typedef struct { + NmCli *nmc; + NMDevice *device; + NMActiveConnection *active; + char *specific_object; + bool hotspot:1; + bool create:1; +} AddAndActivateInfo; -static void -device_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) +static AddAndActivateInfo * +add_and_activate_info_new (NmCli *nmc, + NMDevice *device, + gboolean hotspot, + gboolean create, + const char *specific_object) { - NMActiveConnection *active = (NMActiveConnection *) user_data; + AddAndActivateInfo *info; - connected_state_cb (device, active); + info = g_slice_new (AddAndActivateInfo); + *info = (AddAndActivateInfo) { + .nmc = nmc, + .device = g_object_ref (device), + .hotspot = hotspot, + .create = create, + .specific_object = g_strdup (specific_object), + }; + return info; } static void -active_state_cb (NMActiveConnection *active, GParamSpec *pspec, gpointer user_data) +add_and_activate_info_free (AddAndActivateInfo *info) { - NMDevice *device = (NMDevice *) user_data; - - connected_state_cb (device, active); + g_object_unref (info->device); + g_clear_object (&info->active); + g_free (info->specific_object); + nm_g_slice_free (info); } +NM_AUTO_DEFINE_FCN0 (AddAndActivateInfo *, _nm_auto_free_add_and_activate_info, add_and_activate_info_free) +#define nm_auto_free_add_and_activate_info nm_auto (_nm_auto_free_add_and_activate_info) + static void -connected_state_cb (NMDevice *device, NMActiveConnection *active) +connected_state_cb (AddAndActivateInfo *info) { NMDeviceState state; NMDeviceStateReason reason; NMActiveConnectionState ac_state; - state = nm_device_get_state (device); - ac_state = nm_active_connection_get_state (active); + state = nm_device_get_state (info->device); + ac_state = nm_active_connection_get_state (info->active); if (ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING) return; @@ -1814,42 +1884,36 @@ connected_state_cb (NMDevice *device, NMActiveConnection *active) if (state == NM_DEVICE_STATE_ACTIVATED) { nmc_terminal_erase_line (); g_print (_("Device '%s' successfully activated with '%s'.\n"), - nm_device_get_iface (device), - nm_active_connection_get_uuid (active)); + nm_device_get_iface (info->device), + nm_active_connection_get_uuid (info->active)); + + if (info->hotspot) + g_print (_("Hint: \"nmcli dev wifi show-password\" shows the Wi-Fi name and password.\n")); } else if ( state <= NM_DEVICE_STATE_DISCONNECTED || state >= NM_DEVICE_STATE_DEACTIVATING) { - reason = nm_device_get_state_reason (device); + reason = nm_device_get_state_reason (info->device); g_print (_("Error: Connection activation failed: (%d) %s.\n"), reason, gettext (nmc_device_reason_to_string (reason))); - } else + } else { return; + } - g_signal_handlers_disconnect_by_func (active, G_CALLBACK (active_state_cb), device); - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_state_cb), active); - - g_object_unref (active); - g_object_unref (device); + g_signal_handlers_disconnect_by_func (info->active, G_CALLBACK (connected_state_cb), info); + g_signal_handlers_disconnect_by_func (info->device, G_CALLBACK (connected_state_cb), info); + add_and_activate_info_free (info); quit (); } -typedef struct { - NmCli *nmc; - NMDevice *device; - gboolean hotspot; - gboolean create; -} AddAndActivateInfo; - static void add_and_activate_cb (GObject *client, GAsyncResult *result, gpointer user_data) { - AddAndActivateInfo *info = (AddAndActivateInfo *) user_data; + nm_auto_free_add_and_activate_info AddAndActivateInfo *info = user_data; NmCli *nmc = info->nmc; - NMDevice *device = info->device; - NMActiveConnection *active; - GError *error = NULL; + gs_unref_object NMActiveConnection *active = NULL; + gs_free_error GError *error = NULL; if (info->create) active = nm_client_add_and_activate_connection_finish (NM_CLIENT (client), result, &error); @@ -1857,37 +1921,35 @@ add_and_activate_cb (GObject *client, active = nm_client_activate_connection_finish (NM_CLIENT (client), result, &error); if (error) { - if (info->hotspot) + if (info->hotspot) { g_string_printf (nmc->return_text, _("Error: Failed to setup a Wi-Fi hotspot: %s"), error->message); - else if (info->create) + } else if (info->create) { g_string_printf (nmc->return_text, _("Error: Failed to add/activate new connection: %s"), error->message); - else + } else { g_string_printf (nmc->return_text, _("Error: Failed to activate connection: %s"), error->message); - g_error_free (error); + } nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION; quit (); - } else { - if (nmc->nowait_flag) { - g_object_unref (active); - quit (); - } else { - g_object_ref (device); - g_signal_connect (device, "notify::state", G_CALLBACK (device_state_cb), active); - g_signal_connect (active, "notify::state", G_CALLBACK (active_state_cb), device); + return; + } - connected_state_cb (device, active); + if (nmc->nowait_flag) { + quit (); + return; + } - g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc); /* Exit if timeout expires */ + if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) + progress_id = g_timeout_add (120, progress_cb, info->device); - if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) - progress_id = g_timeout_add (120, progress_cb, device); - } - } + info->active = g_steal_pointer (&active); + g_signal_connect_swapped (info->device, "notify::state", G_CALLBACK (connected_state_cb), info); + g_signal_connect_swapped (info->active, "notify::state", G_CALLBACK (connected_state_cb), info); + connected_state_cb (g_steal_pointer (&info)); - g_free (info); + g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc); /* Exit if timeout expires */ } static void @@ -1916,12 +1978,10 @@ create_connect_connection_for_device (AddAndActivateInfo *info) static void connect_device_cb (GObject *client, GAsyncResult *result, gpointer user_data) { - AddAndActivateInfo *info = (AddAndActivateInfo *) user_data; + nm_auto_free_add_and_activate_info AddAndActivateInfo *info = user_data; NmCli *nmc = info->nmc; - NMActiveConnection *active; + gs_unref_object NMActiveConnection *active = NULL; GError *error = NULL; - const GPtrArray *devices; - NMDevice *device; active = nm_client_activate_connection_finish (NM_CLIENT (client), result, &error); @@ -1929,7 +1989,7 @@ connect_device_cb (GObject *client, GAsyncResult *result, gpointer user_data) /* If no connection existed for the device, create one and activate it */ if (g_error_matches (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION)) { info->create = TRUE; - create_connect_connection_for_device (info); + create_connect_connection_for_device (g_steal_pointer (&info)); return; } @@ -1938,42 +1998,30 @@ connect_device_cb (GObject *client, GAsyncResult *result, gpointer user_data) g_error_free (error); nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION; quit (); - } else { - g_assert (active); - devices = nm_active_connection_get_devices (active); - if (devices->len == 0) { - g_string_printf (nmc->return_text, _("Error: Device activation failed: device was disconnected")); - nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION; - g_object_unref (active); - quit (); - g_free (info); - return; - } + return; + } - device = g_ptr_array_index (devices, 0); + nm_assert (NM_IS_ACTIVE_CONNECTION (active)); - if (nmc->nowait_flag) { - g_object_unref (active); - quit (); - } else { - if (nmc->secret_agent) { - NMRemoteConnection *connection = nm_active_connection_get_connection (active); + if (nmc->nowait_flag) { + quit (); + return; + } - nm_secret_agent_simple_enable (nmc->secret_agent, - nm_connection_get_path (NM_CONNECTION (connection))); - } + if (nmc->secret_agent) { + NMRemoteConnection *connection = nm_active_connection_get_connection (active); - g_object_ref (device); - g_signal_connect (device, "notify::state", G_CALLBACK (device_state_cb), active); - g_signal_connect (active, "notify::state", G_CALLBACK (active_state_cb), device); + nm_secret_agent_simple_enable (nmc->secret_agent, + nm_connection_get_path (NM_CONNECTION (connection))); + } - connected_state_cb (device, active); + info->active = g_steal_pointer (&active); + g_signal_connect_swapped (info->device, "notify::state", G_CALLBACK (connected_state_cb), info); + g_signal_connect_swapped (info->active, "notify::state", G_CALLBACK (connected_state_cb), info); + connected_state_cb (g_steal_pointer (&info)); - /* Start timer not to loop forever if "notify::state" signal is not issued */ - g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc); - } - } - g_free (info); + /* Start timer not to loop forever if "notify::state" signal is not issued */ + g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc); } static NMCResultCode @@ -2018,10 +2066,7 @@ do_device_connect (NmCli *nmc, int argc, char **argv) nmc); } - info = g_malloc0 (sizeof (AddAndActivateInfo)); - info->nmc = nmc; - info->device = device; - info->hotspot = FALSE; + info = add_and_activate_info_new (nmc, device, FALSE, FALSE, NULL); nm_client_activate_connection_async (nmc->client, NULL, /* let NM find a connection automatically */ @@ -3004,7 +3049,7 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) nmc_complete_strings (rescan, "auto", "no", "yes"); break; default: - g_assert_not_reached(); + nm_assert_not_reached(); break; } } @@ -3027,8 +3072,10 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) if (nmc->complete) return nmc->return_value; - if (argc) - g_printerr (_("Unknown parameter: %s\n"), *argv); + if (argc) { + g_string_printf (nmc->return_text, _("Error: invalid extra argument '%s'."), *argv); + return NMC_RESULT_ERROR_USER_INPUT; + } if (rescan == NULL || strcmp (rescan, "auto") == 0) { rescan_cutoff = NM_MAX (nm_utils_get_timestamp_msec () - 30 * NM_UTILS_MSEC_PER_SECOND, 0); @@ -3116,18 +3163,78 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) return nmc->return_value; } +static void +activate_update2_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + NMRemoteConnection *remote_con = NM_REMOTE_CONNECTION (source_object); + AddAndActivateInfo *info = user_data; + NmCli *nmc = info->nmc; + gs_unref_variant GVariant *ret = NULL; + GError *error = NULL; + + ret = nm_remote_connection_update2_finish (remote_con, res, &error); + + if (!ret) { + g_string_printf (nmc->return_text, _("Error: %s."), error->message); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + g_error_free (error); + quit (); + add_and_activate_info_free (info); + return; + } + + nm_client_activate_connection_async (nmc->client, + NM_CONNECTION (remote_con), + info->device, + info->specific_object, + NULL, + add_and_activate_cb, + info); +} + +static void +save_and_activate_connection (NmCli *nmc, + NMDevice *device, + NMConnection *connection, + gboolean hotspot, + const char *specific_object) +{ + AddAndActivateInfo *info; + + info = add_and_activate_info_new (nmc, device, hotspot, + !NM_IS_REMOTE_CONNECTION (connection), + specific_object); + + if (NM_IS_REMOTE_CONNECTION (connection)) { + nm_remote_connection_update2 (NM_REMOTE_CONNECTION (connection), + nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL), + NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT, + NULL, + NULL, + activate_update2_cb, + info); + } else { + nm_client_add_and_activate_connection_async (nmc->client, + connection, + info->device, + info->specific_object, + NULL, + add_and_activate_cb, + info); + } +} + static NMCResultCode -do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) +do_device_wifi_connect (NmCli *nmc, int argc, char **argv) { NMDevice *device = NULL; NMAccessPoint *ap = NULL; NM80211ApFlags ap_flags; NM80211ApSecurityFlags ap_wpa_flags; NM80211ApSecurityFlags ap_rsn_flags; - NMConnection *connection = NULL; + gs_unref_object NMConnection *connection = NULL; NMSettingConnection *s_con; NMSettingWireless *s_wifi; - AddAndActivateInfo *info; const char *param_user = NULL; const char *ifname = NULL; const char *bssid = NULL; @@ -3144,7 +3251,6 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) char *passwd_ask = NULL; const GPtrArray *avail_cons; gboolean name_match = FALSE; - gboolean existing_con = FALSE; int i; /* Set default timeout waiting for operation completion. */ @@ -3165,7 +3271,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) next_arg (nmc, &argc, &argv, NULL); } else { /* nmc_do_cmd() should not call this with argc=0. */ - g_assert (!nmc->complete); + nm_assert (!nmc->complete); if (nmc->ask) { ssid_ask = nmc_readline (&nmc->nmc_config, _("SSID or BSSID: ")); @@ -3291,7 +3397,9 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) goto finish; } } else if (!nmc->complete) { - g_printerr (_("Unknown parameter: %s\n"), *argv); + g_string_printf (nmc->return_text, _("Error: invalid extra argument '%s'."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto finish; } next_arg (nmc, &argc, &argv, NULL); @@ -3377,7 +3485,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) avail_cons = nm_device_get_available_connections (device); for (i = 0; i < avail_cons->len; i++) { - NMRemoteConnection *avail_con = g_ptr_array_index (avail_cons, i); + NMConnection *avail_con = g_ptr_array_index (avail_cons, i); const char *id = nm_connection_get_id (NM_CONNECTION (avail_con)); if (con_name) { @@ -3391,22 +3499,21 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) /* ap has been checked against bssid1, bssid2 and the ssid * and now avail_con has been checked against ap. */ - connection = NM_CONNECTION (avail_con); - existing_con = TRUE; + connection = g_object_ref (avail_con); break; } } - if (name_match && !existing_con) { + if (name_match && !connection) { g_string_printf (nmc->return_text, _("Error: Connection '%s' exists but properties don't match."), con_name); nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; goto finish; } - if (!existing_con) { + if (!connection) { /* If there are some connection data from user, create a connection and * fill them into proper settings. */ - if (con_name || private || bssid2_arr || password || hidden) + if (con_name || private || bssid2_arr || hidden) connection = nm_simple_connection_new (); if (con_name || private) { @@ -3518,28 +3625,8 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) nmc->nowait_flag = (nmc->timeout == 0); nmc->should_wait++; - info = g_malloc0 (sizeof (AddAndActivateInfo)); - info->nmc = nmc; - info->device = device; - info->hotspot = FALSE; - info->create = !existing_con; - if (existing_con) { - nm_client_activate_connection_async (nmc->client, - connection, - device, - nm_object_get_path (NM_OBJECT (ap)), - NULL, - add_and_activate_cb, - info); - } else { - nm_client_add_and_activate_connection_async (nmc->client, - connection, - device, - nm_object_get_path (NM_OBJECT (ap)), - NULL, - add_and_activate_cb, - info); - } + save_and_activate_connection (nmc, device, connection, FALSE, + nm_object_get_path (NM_OBJECT (ap))); finish: if (bssid1_arr) @@ -3553,19 +3640,17 @@ finish: } static GBytes * -generate_ssid_for_hotspot (const char *ssid) +generate_ssid_for_hotspot (void) { GBytes *ssid_bytes; - char *hotspot_ssid = NULL; + char *ssid = NULL; - if (!ssid) { - hotspot_ssid = g_strdup_printf ("Hotspot-%s", g_get_host_name ()); - if (strlen (hotspot_ssid) > 32) - hotspot_ssid[32] = '\0'; - ssid = hotspot_ssid; - } + ssid = g_strdup_printf ("Hotspot-%s", g_get_host_name ()); + if (strlen (ssid) > 32) + ssid[32] = '\0'; ssid_bytes = g_bytes_new (ssid, strlen (ssid)); - g_free (hotspot_ssid); + g_free (ssid); + return ssid_bytes; } @@ -3679,30 +3764,125 @@ set_wireless_security_for_hotspot (NMSettingWirelessSecurity *s_wsec, return TRUE; } +static NMConnection * +find_hotspot_conn (NMDevice *device, + const GPtrArray *connections, + const char *con_name, + GBytes *ssid_bytes, + const char *wifi_mode, + const char *band, + gint64 channel_int) +{ + NMConnection *connection; + NMSettingWireless *s_wifi; + int i; + + for (i = 0; i < connections->len; i++) { + connection = NM_CONNECTION (connections->pdata[i]); + + s_wifi = nm_connection_get_setting_wireless (connection); + if (!s_wifi) + continue; + + if ( channel_int != -1 + && nm_setting_wireless_get_channel (s_wifi) != channel_int) + continue; + + if (g_strcmp0 (nm_setting_wireless_get_mode (s_wifi), wifi_mode) != 0) + continue; + + if (band && g_strcmp0 (nm_setting_wireless_get_band (s_wifi), band) != 0) + continue; + + if (ssid_bytes && !g_bytes_equal (nm_setting_wireless_get_ssid (s_wifi), ssid_bytes)) + continue; + + if (!nm_device_connection_compatible (device, connection, NULL)) + continue; + + return g_object_ref (connection); + } + + return NULL; +} + +static NMConnection * +create_hotspot_conn (const GPtrArray *connections, + const char *con_name, + GBytes *ssid_bytes, + const char *wifi_mode, + const char *band, + gint64 channel_int) +{ + char *default_name = NULL; + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSettingIPConfig *s_ip4, *s_ip6; + NMSettingProxy *s_proxy; + + connection = nm_simple_connection_new (); + s_con = (NMSettingConnection *) nm_setting_connection_new (); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + if (!con_name) + con_name = default_name = nmc_unique_connection_name (connections, "Hotspot"); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, con_name, + NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, + NULL); + g_free (default_name); + + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + g_object_set (s_wifi, NM_SETTING_WIRELESS_MODE, wifi_mode, + NM_SETTING_WIRELESS_SSID, ssid_bytes, + NULL); + + if (channel_int != -1) { + g_object_set (s_wifi, + NM_SETTING_WIRELESS_CHANNEL, (guint32) channel_int, + NM_SETTING_WIRELESS_BAND, band, + NULL); + } + + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_SHARED, NULL); + + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); + nm_connection_add_setting (connection, NM_SETTING (s_ip6)); + g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); + + s_proxy = (NMSettingProxy *) nm_setting_proxy_new (); + nm_connection_add_setting (connection, NM_SETTING (s_proxy)); + g_object_set (s_proxy, NM_SETTING_PROXY_METHOD, (int) NM_SETTING_PROXY_METHOD_NONE, NULL); + + return connection; +} + static NMCResultCode do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv) { - AddAndActivateInfo *info; const char *ifname = NULL; const char *con_name = NULL; - char *default_name = NULL; - const char *ssid = NULL; + gs_unref_bytes GBytes *ssid_bytes = NULL; const char *wifi_mode; const char *band = NULL; const char *channel = NULL; - unsigned long channel_int; + gint64 channel_int = -1; const char *password = NULL; gboolean show_password = FALSE; NMDevice *device = NULL; gs_free NMDevice **devices = NULL; NMDeviceWifiCapabilities caps; - NMConnection *connection = NULL; - NMSettingConnection *s_con; - NMSettingWireless *s_wifi; + gs_unref_object NMConnection *connection = NULL; + const GPtrArray *connections; NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig *s_ip4, *s_ip6; - NMSettingProxy *s_proxy; - GBytes *ssid_bytes; GError *error = NULL; /* Set default timeout waiting for operation completion. */ @@ -3743,11 +3923,11 @@ do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv) g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1)); return NMC_RESULT_ERROR_USER_INPUT; } - ssid = *argv; - if (strlen (ssid) > 32) { + if (strlen (*argv) > 32) { g_string_printf (nmc->return_text, _("Error: ssid is too long.")); return NMC_RESULT_ERROR_USER_INPUT; } + ssid_bytes = g_bytes_new (*argv, strlen (*argv)); } else if (strcmp (*argv, "band") == 0) { argc--; argv++; @@ -3784,7 +3964,7 @@ do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv) } else if (nmc_arg_is_option (*argv, "show-password")) { show_password = TRUE; } else { - g_string_printf (nmc->return_text, _("Error: Unknown parameter %s."), *argv); + g_string_printf (nmc->return_text, _("Error: invalid extra argument '%s'."), *argv); return NMC_RESULT_ERROR_USER_INPUT; } @@ -3803,21 +3983,24 @@ do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv) channel = "7"; } if (channel) { + unsigned long int value; + if (!band) { g_string_printf (nmc->return_text, _("Error: channel requires band too.")); return NMC_RESULT_ERROR_USER_INPUT; } - if ( !nmc_string_to_uint (channel, TRUE, 1, 5825, &channel_int) - || !nm_utils_wifi_is_channel_valid (channel_int, band)) { + if ( !nmc_string_to_uint (channel, TRUE, 1, 5825, &value) + || !nm_utils_wifi_is_channel_valid (value, band)) { g_string_printf (nmc->return_text, _("Error: channel '%s' not valid for band '%s'."), channel, band); return NMC_RESULT_ERROR_USER_INPUT; } + + channel_int = value; } /* Find Wi-Fi device. When no ifname is provided, the first Wi-Fi is used. */ device = find_wifi_device_by_iface (devices, ifname, NULL); - if (!device) { if (ifname) g_string_printf (nmc->return_text, _("Error: Device '%s' is not a Wi-Fi device."), ifname); @@ -3838,69 +4021,34 @@ do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv) return NMC_RESULT_ERROR_UNKNOWN; } - /* Create a connection with appropriate parameters */ - connection = nm_simple_connection_new (); - s_con = (NMSettingConnection *) nm_setting_connection_new (); - nm_connection_add_setting (connection, NM_SETTING (s_con)); - if (!con_name) - con_name = default_name = nmc_unique_connection_name (nm_client_get_connections (nmc->client), "Hotspot"); - g_object_set (s_con, - NM_SETTING_CONNECTION_ID, con_name, - NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, - NULL); - g_free (default_name); - - s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wifi)); - ssid_bytes = generate_ssid_for_hotspot (ssid); - g_object_set (s_wifi, NM_SETTING_WIRELESS_MODE, wifi_mode, - NM_SETTING_WIRELESS_SSID, ssid_bytes, - NULL); - g_bytes_unref (ssid_bytes); - if (channel) - g_object_set (s_wifi, - NM_SETTING_WIRELESS_CHANNEL, (guint32) channel_int, - NM_SETTING_WIRELESS_BAND, band, - NULL); - - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wsec)); - if (!set_wireless_security_for_hotspot (s_wsec, wifi_mode, caps, password, show_password, &error)) { - g_object_unref (connection); - g_string_printf (nmc->return_text, _("Error: Invalid 'password': %s."), error->message); - g_clear_error (&error); - return NMC_RESULT_ERROR_UNKNOWN; + connections = nm_client_get_connections (nmc->client); + connection = find_hotspot_conn (device, connections, con_name, ssid_bytes, + wifi_mode, band, channel_int); + if (!connection) { + /* Create a connection with appropriate parameters */ + if (!ssid_bytes) + ssid_bytes = generate_ssid_for_hotspot (); + connection = create_hotspot_conn (connections, con_name, ssid_bytes, + wifi_mode, band, channel_int); } - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); - nm_connection_add_setting (connection, NM_SETTING (s_ip4)); - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_SHARED, NULL); - - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); - nm_connection_add_setting (connection, NM_SETTING (s_ip6)); - g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); + if (password || !NM_IS_REMOTE_CONNECTION (connection)) { + s_wsec = nm_connection_get_setting_wireless_security (connection); + g_return_val_if_fail (s_wsec, NMC_RESULT_ERROR_UNKNOWN); - s_proxy = (NMSettingProxy *) nm_setting_proxy_new (); - nm_connection_add_setting (connection, NM_SETTING (s_proxy)); - g_object_set (s_proxy, NM_SETTING_PROXY_METHOD, (int) NM_SETTING_PROXY_METHOD_NONE, NULL); + if (!set_wireless_security_for_hotspot (s_wsec, wifi_mode, caps, password, show_password, &error)) { + g_object_unref (connection); + g_string_printf (nmc->return_text, _("Error: Invalid 'password': %s."), error->message); + g_clear_error (&error); + return NMC_RESULT_ERROR_UNKNOWN; + } + } /* Activate the connection now */ nmc->nowait_flag = (nmc->timeout == 0); nmc->should_wait++; - info = g_malloc0 (sizeof (AddAndActivateInfo)); - info->nmc = nmc; - info->device = device; - info->hotspot = TRUE; - info->create = TRUE; - - nm_client_add_and_activate_connection_async (nmc->client, - connection, - device, - NULL, - NULL, - add_and_activate_cb, - info); + save_and_activate_connection (nmc, device, connection, TRUE, NULL); return nmc->return_value; } @@ -3966,8 +4114,11 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv) goto finish; } g_ptr_array_add (ssids, *argv); - } else if (!nmc->complete) - g_printerr (_("Unknown parameter: %s\n"), *argv); + } else if (!nmc->complete) { + g_string_printf (nmc->return_text, _("Error: invalid extra argument '%s'."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto finish; + } next_arg (nmc, &argc, &argv, NULL); } @@ -4012,12 +4163,221 @@ finish: return nmc->return_value; } +static void +string_append_mecard (GString *string, const char *tag, const char *text) +{ + const char *p; + bool is_hex = TRUE; + int start; + + if (!text) + return; + + g_string_append (string, tag); + start = string->len; + + for (p = text; *p; p++) { + if (!g_ascii_isxdigit (*p)) + is_hex = FALSE; + if (strchr ("\\\":;,", *p)) + g_string_append_c (string, '\\'); + g_string_append_c (string, *p); + } + + if (is_hex) { + g_string_insert_c (string, start, '\"'); + g_string_append_c (string, '\"'); + } + g_string_append_c (string, ';'); +} + +static void +print_wifi_connection (const NmcConfig *nmc_config, NMConnection *connection) +{ + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wsec; + const char *key_mgmt = NULL; + const char *psk = NULL; + const char *type = NULL; + GBytes *ssid_bytes; + char *ssid; + GString *string; + + s_wireless = nm_connection_get_setting_wireless (connection); + g_return_if_fail (s_wireless); + + ssid_bytes = nm_setting_wireless_get_ssid (s_wireless); + g_return_if_fail (ssid_bytes); + ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid_bytes, NULL), + g_bytes_get_size (ssid_bytes)); + g_return_if_fail (ssid); + g_print ("SSID: %s\n", ssid); + + string = g_string_sized_new (64); + g_string_append (string, "WIFI:"); + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (s_wsec) { + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + psk = nm_setting_wireless_security_get_psk (s_wsec); + } + + if (key_mgmt == NULL) { + type = "nopass"; + g_print ("%s: %s\n", _("Security"), _("None")); + } else if ( strcmp (key_mgmt, "none") == 0 + || strcmp (key_mgmt, "ieee8021x") == 0) { + type = "WEP"; + g_print ("%s: WEP\n", _("Security")); + } else if ( strcmp (key_mgmt, "wpa-none") == 0 + || strcmp (key_mgmt, "wpa-psk") == 0 + || strcmp (key_mgmt, "sae") == 0) { + type = "WPA"; + g_print ("%s: WPA\n", _("Security")); + } + + if (psk) + g_print ("%s: %s\n", _("Password"), psk); + + string_append_mecard(string, "T:", type); + string_append_mecard(string, "S:", ssid); + string_append_mecard(string, "P:", psk); + + if (nm_setting_wireless_get_hidden (s_wireless)) + g_string_append (string, "H:true;"); + + g_string_append_c (string, ';'); + if (nmc_config->use_colors) + nmc_print_qrcode (string->str); + g_string_free (string, TRUE); + + g_print ("\n"); +} + +static gboolean +wifi_show_device (const NmcConfig *nmc_config, NMDevice *device, GError **error) +{ + NMActiveConnection *active_conn; + gs_unref_object NMConnection *connection = NULL; + gs_unref_variant GVariant *secrets = NULL; + + if (!NM_IS_DEVICE_WIFI (device)) { + g_set_error (error, NMCLI_ERROR, 0, + _("Error: Device '%s' is not a Wi-Fi device."), + nm_device_get_iface (device)); + return FALSE; + } + + connection = nm_device_get_applied_connection (device, 0, NULL, NULL, error); + if (!connection) + return FALSE; + + active_conn = nm_device_get_active_connection (device); + if (!active_conn) { + g_set_error (error, NMCLI_ERROR, 0, + _("no active connection on device '%s'"), + nm_device_get_iface (device)); + return FALSE; + } + + secrets = nm_remote_connection_get_secrets (nm_active_connection_get_connection (active_conn), + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL, + NULL); + if (secrets && !nm_connection_update_secrets (connection, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + secrets, + error)) { + return FALSE; + } + + print_wifi_connection (nmc_config, connection); + + return TRUE; +} + +static NMCResultCode +do_device_wifi_show_password (NmCli *nmc, int argc, char **argv) +{ + const char *ifname = NULL; + gs_free NMDevice **devices = NULL; + gs_free_error GError *error = NULL; + gboolean found = FALSE; + int i; + + devices = nmc_get_devices_sorted (nmc->client); + + next_arg (nmc, &argc, &argv, NULL); + while (argc > 0) { + if (argc == 1 && nmc->complete) + nmc_complete_strings (*argv, "ifname"); + + if (strcmp (*argv, "ifname") == 0) { + if (ifname) { + g_string_printf (nmc->return_text, + _("Error: '%s' cannot repeat."), + *(argv-1)); + return NMC_RESULT_ERROR_USER_INPUT; + } + argc--; + argv++; + if (!argc) { + g_string_printf (nmc->return_text, + _("Error: %s argument is missing."), + *(argv-1)); + return NMC_RESULT_ERROR_USER_INPUT; + } + ifname = *argv; + if (argc == 1 && nmc->complete) + complete_device (devices, ifname, TRUE); + } else if (!nmc->complete) { + g_string_printf (nmc->return_text, + _("Error: invalid extra argument '%s'."), + *argv); + return NMC_RESULT_ERROR_USER_INPUT; + } + + next_arg (nmc, &argc, &argv, NULL); + } + + if (nmc->complete) + return nmc->return_value; + + for (i = 0; devices[i]; i++) { + if (ifname && g_strcmp0 (nm_device_get_iface (devices[i]), ifname) != 0) + continue; + + if (wifi_show_device (&nmc->nmc_config, devices[i], &error)) { + found = TRUE; + } else { + if (ifname) { + g_string_printf (nmc->return_text, + _("%s"), error->message); + return NMC_RESULT_ERROR_UNKNOWN; + } + g_clear_error (&error); + } + + if (ifname) + break; + } + + if (!found) { + g_string_printf (nmc->return_text, + _("Error: No Wi-Fi device found.")); + return NMC_RESULT_ERROR_UNKNOWN; + } + + return nmc->return_value; +} + static NMCCommand device_wifi_cmds[] = { - { "list", do_device_wifi_list, NULL, TRUE, TRUE }, - { "connect", do_device_wifi_connect_network, NULL, TRUE, TRUE }, - { "hotspot", do_device_wifi_hotspot, NULL, TRUE, TRUE }, - { "rescan", do_device_wifi_rescan, NULL, TRUE, TRUE }, - { NULL, do_device_wifi_list, NULL, TRUE, TRUE }, + { "list", do_device_wifi_list, NULL, TRUE, TRUE }, + { "connect", do_device_wifi_connect, NULL, TRUE, TRUE }, + { "hotspot", do_device_wifi_hotspot, NULL, TRUE, TRUE }, + { "rescan", do_device_wifi_rescan, NULL, TRUE, TRUE }, + { "show-password", do_device_wifi_show_password, NULL, TRUE, TRUE }, + { NULL, do_device_wifi_list, NULL, TRUE, TRUE }, }; static NMCResultCode diff --git a/clients/cli/devices.h b/clients/cli/devices.h index 7a05b50b..055d56e7 100644 --- a/clients/cli/devices.h +++ b/clients/cli/devices.h @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #ifndef NMC_DEVICES_H diff --git a/clients/cli/general.c b/clients/cli/general.c index e2ce639e..123cc5b4 100644 --- a/clients/cli/general.c +++ b/clients/cli/general.c @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -367,6 +353,38 @@ usage_general_permissions (void) } static void +usage_general_reload (void) +{ + g_printerr (_("Usage: nmcli general reload { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [<flag>[,<flag>...]]\n" + "\n" + "Reload NetworkManager's configuration and perform certain updates, like\n" + "flushing caches or rewriting external state to disk. This is similar to\n" + "sending SIGHUP to NetworkManager but it allows for more fine-grained\n" + "control over what to reload through the flags argument. It also allows\n" + "non-root access via PolicyKit and contrary to signals it is synchronous.\n" + "\n" + "Available flags are:\n" + "\n" + " 'conf' Reload the NetworkManager.conf configuration from\n" + " disk. Note that this does not include connections, which\n" + " can be reloaded through 'nmcli connection reload' instead.\n" + "\n" + " 'dns-rc' Update DNS configuration, which usually involves writing\n" + " /etc/resolv.conf anew.\n" + "\n" + " 'dns-full' Restart the DNS plugin. This is for example useful when\n" + " using dnsmasq plugin, which uses additional configuration\n" + " in /etc/NetworkManager/dnsmasq.d. If you edit those files,\n" + " you can restart the DNS plugin. This action shortly\n" + " interrupts name resolution.\n" + "\n" + "With no flags, everything that is supported is reloaded, which is\n" + "identical to sending a SIGHUP.\n")); +} + +static void usage_general_logging (void) { g_printerr (_("Usage: nmcli general logging { ARGUMENTS | help }\n" @@ -582,6 +600,9 @@ permission_changed (NMClient *client, if (got_permissions (nmc)) { /* Defer the printing, so that we have a chance to process the other * permission-changed signals. */ + g_signal_handlers_disconnect_by_func (nmc->client, + G_CALLBACK (permission_changed), + nmc); g_idle_remove_by_data (nmc); g_idle_add (print_permissions, nmc); } @@ -598,7 +619,7 @@ show_nm_permissions (NmCli *nmc) /* The client didn't get the permissions reply yet. Subscribe to changes. */ g_signal_connect (nmc->client, NM_CLIENT_PERMISSION_CHANGED, - G_CALLBACK (permission_changed), nmc); + G_CALLBACK (permission_changed), nmc); if (nmc->timeout == -1) nmc->timeout = 10; @@ -609,6 +630,70 @@ show_nm_permissions (NmCli *nmc) } static NMCResultCode +do_general_reload (NmCli *nmc, int argc, char **argv) +{ + gs_unref_variant GVariant *result = NULL; + gs_free_error GError *error = NULL; + gs_free const char **values = NULL; + gs_free char *err_token = NULL; + gs_free char *joined = NULL; + int flags = 0; + + next_arg (nmc, &argc, &argv, NULL); + + if (nmc->complete) { + if (argc == 0) + return nmc->return_value; + + if (argc == 1) { + values = nm_utils_enum_get_values (nm_manager_reload_flags_get_type (), + NM_MANAGER_RELOAD_FLAG_CONF, + NM_MANAGER_RELOAD_FLAG_ALL); + nmc_complete_strv (*argv, -1, values); + } + return nmc->return_value; + } + + if (argc > 0) { + if (!nm_utils_enum_from_str (nm_manager_reload_flags_get_type (), *argv, &flags, &err_token)) { + values = nm_utils_enum_get_values (nm_manager_reload_flags_get_type (), + NM_MANAGER_RELOAD_FLAG_CONF, + NM_MANAGER_RELOAD_FLAG_ALL); + joined = g_strjoinv (",", (char **) values); + g_string_printf (nmc->return_text, + _("Error: invalid reload flag '%s'. Allowed flags are: %s"), + err_token, + joined); + return NMC_RESULT_ERROR_USER_INPUT; + } + argc--; + argv++; + } + + if (argc > 0) { + g_string_printf (nmc->return_text, _("Error: extra argument '%s'"), *argv); + return NMC_RESULT_ERROR_USER_INPUT; + } + + result = nmc_dbus_call_sync (nmc, + "/org/freedesktop/NetworkManager", + "org.freedesktop.NetworkManager", + "Reload", + g_variant_new ("(u)", flags), + G_VARIANT_TYPE("()"), + &error); + + if (error) { + g_string_printf (nmc->return_text, + _("Error: failed to reload: %s"), + nmc_error_get_simple_message (error)); + return NMC_RESULT_ERROR_UNKNOWN; + } + + return nmc->return_value; +} + +static NMCResultCode do_general_permissions (NmCli *nmc, int argc, char **argv) { next_arg (nmc, &argc, &argv, NULL); @@ -785,6 +870,7 @@ static const NMCCommand general_cmds[] = { { "hostname", do_general_hostname, usage_general_hostname, TRUE, TRUE }, { "permissions", do_general_permissions, usage_general_permissions, TRUE, TRUE }, { "logging", do_general_logging, usage_general_logging, TRUE, TRUE }, + { "reload", do_general_reload, usage_general_reload, FALSE, FALSE }, { NULL, do_general_status, usage_general, TRUE, TRUE }, }; @@ -1158,6 +1244,41 @@ device_overview (NmCli *nmc, NMDevice *device) g_string_append_printf (outbuf, "%s, ", tmp); g_free (tmp); } + + switch (nm_device_get_device_type (device)) { + case NM_DEVICE_TYPE_WIFI: + case NM_DEVICE_TYPE_OLPC_MESH: + case NM_DEVICE_TYPE_WIFI_P2P: + if (!nm_client_wireless_get_enabled (nmc->client)) { + tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_DISABLED, _("sw disabled")); + g_string_append_printf (outbuf, "%s, ", tmp); + g_free (tmp); + } + if (!nm_client_wireless_hardware_get_enabled (nmc->client)) { + tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_DISABLED, _("hw disabled")); + g_string_append_printf (outbuf, "%s, ", tmp); + g_free (tmp); + } + break; + case NM_DEVICE_TYPE_MODEM: + if ( nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device)) + & (NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS | NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO)) { + if (!nm_client_wwan_get_enabled (nmc->client)) { + tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_DISABLED, _("sw disabled")); + g_string_append_printf (outbuf, "%s, ", tmp); + g_free (tmp); + } + if (!nm_client_wwan_hardware_get_enabled (nmc->client)) { + tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_DISABLED, _("hw disabled")); + g_string_append_printf (outbuf, "%s, ", tmp); + g_free (tmp); + } + } + break; + default: + break; + } + if (nm_device_is_software (device)) g_string_append_printf (outbuf, "%s, ", _("sw")); else @@ -1296,11 +1417,20 @@ do_overview (NmCli *nmc, int argc, char **argv) state = nm_device_get_state (devices[i]); color = nmc_device_state_to_color (state); - tmp = nmc_colorize (&nmc->nmc_config, color, "%s: %s%s%s", - nm_device_get_iface (devices[i]), - gettext (nmc_device_state_to_string (state)), - ac ? " to " : "", - ac ? nm_active_connection_get_id (ac) : ""); + if (ac) { + /* TRANSLATORS: prints header line for activated device in plain `nmcli` overview output as + * "<interface-name>: <device-state> to <connection-id>" */ + tmp = nmc_colorize (&nmc->nmc_config, color, C_("nmcli-overview", "%s: %s to %s"), + nm_device_get_iface (devices[i]), + gettext (nmc_device_state_to_string (state)), + nm_active_connection_get_id (ac)); + } else { + /* TRANSLATORS: prints header line for not active device in plain `nmcli` overview output as + * "<interface-name>: <device-state>" */ + tmp = nmc_colorize (&nmc->nmc_config, color, C_("nmcli-overview", "%s: %s"), + nm_device_get_iface (devices[i]), + gettext (nmc_device_state_to_string (state))); + } g_print ("%s\n", tmp); g_free (tmp); diff --git a/clients/cli/general.h b/clients/cli/general.h index 05caffea..dd63e43f 100644 --- a/clients/cli/general.h +++ b/clients/cli/general.h @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2014 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2014 Red Hat, Inc. */ #ifndef NMC_GENERAL_H diff --git a/clients/cli/meson.build b/clients/cli/meson.build index 396466a2..56202063 100644 --- a/clients/cli/meson.build +++ b/clients/cli/meson.build @@ -19,17 +19,11 @@ sources = files( ) deps = [ - libnm_dep, libnmc_base_dep, libnmc_dep, - libnm_core_dep, readline_dep, ] -cflags = clients_cflags + [ - '-DG_LOG_DOMAIN="@0@"'.format(name), -] - if enable_polkit_agent sources += nm_polkit_listener @@ -40,7 +34,7 @@ executable( name, sources, dependencies: deps, - c_args: cflags, + c_args: clients_c_flags + ['-DG_LOG_DOMAIN="@0@"'.format(name)], link_args: ldflags_linker_script_binary, link_depends: linker_script_binary, install: true, diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index ad45f179..5fbd6d72 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -1,22 +1,7 @@ -/* nmcli - command-line tool to control NetworkManager - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Jiri Klimes <jklimes@redhat.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2018 Red Hat, Inc. + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -65,6 +50,7 @@ [NM_META_COLOR_DEVICE_FIRMWARE_MISSING] = "31", \ [NM_META_COLOR_DEVICE_PLUGIN_MISSING] = "31", \ [NM_META_COLOR_DEVICE_UNAVAILABLE] = "2", \ + [NM_META_COLOR_DEVICE_DISABLED] = "31", \ [NM_META_COLOR_MANAGER_RUNNING] = "32", \ [NM_META_COLOR_MANAGER_STARTING] = "33", \ [NM_META_COLOR_MANAGER_STOPPED] = "31", \ @@ -470,6 +456,12 @@ check_colors (NmcColorOption color_option, return FALSE; } + if ( color_option == NMC_USE_COLOR_AUTO + && g_getenv ("NO_COLOR")) { + /* https://no-color.org/ */ + return FALSE; + } + term = g_getenv ("TERM"); if (color_option == NMC_USE_COLOR_AUTO) { @@ -571,6 +563,7 @@ parse_color_scheme (char *palette_buffer, [NM_META_COLOR_DEVICE_FIRMWARE_MISSING] = "device-firmware-missing", [NM_META_COLOR_DEVICE_PLUGIN_MISSING] = "device-plugin-missing", [NM_META_COLOR_DEVICE_UNAVAILABLE] = "device-unavailable", + [NM_META_COLOR_DEVICE_DISABLED] = "device-disabled", [NM_META_COLOR_DEVICE_UNKNOWN] = "device-unknown", [NM_META_COLOR_MANAGER_RUNNING] = "manager-running", [NM_META_COLOR_MANAGER_STARTING] = "manager-starting", diff --git a/clients/cli/nmcli.h b/clients/cli/nmcli.h index cd50333a..4615b046 100644 --- a/clients/cli/nmcli.h +++ b/clients/cli/nmcli.h @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #ifndef NMC_NMCLI_H @@ -149,11 +135,6 @@ typedef struct _NmCli { char *palette_buffer; /* Buffer with sequences for terminal-colors.d(5)-based coloring. */ } NmCli; -#define NMC_RETURN(nmc, rvalue) \ - G_STMT_START { \ - return ((nmc)->return_value = (rvalue)); \ - } G_STMT_END - extern NmCli nm_cli; /* Error quark for GError domain */ diff --git a/clients/cli/polkit-agent.c b/clients/cli/polkit-agent.c index accb567f..69bfb68d 100644 --- a/clients/cli/polkit-agent.c +++ b/clients/cli/polkit-agent.c @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2014 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 Red Hat, Inc. */ #include "nm-default.h" diff --git a/clients/cli/polkit-agent.h b/clients/cli/polkit-agent.h index e2902dc0..722d6d33 100644 --- a/clients/cli/polkit-agent.h +++ b/clients/cli/polkit-agent.h @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2014 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 Red Hat, Inc. */ #ifndef __NMC_POLKIT_AGENT_H__ diff --git a/clients/cli/settings.c b/clients/cli/settings.c index 2446cb08..698471d7 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2015 Red Hat, Inc. */ #include "nm-default.h" @@ -532,7 +518,7 @@ gboolean nmc_setting_set_property (NMClient *client, NMSetting *setting, const char *prop, - char modifier, + NMMetaAccessorModifier modifier, const char *value, GError **error) { @@ -542,20 +528,14 @@ nmc_setting_set_property (NMClient *client, g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (NM_IN_SET (modifier, '\0', '-', '+'), FALSE); + g_return_val_if_fail (NM_IN_SET (modifier, NM_META_ACCESSOR_MODIFIER_SET, NM_META_ACCESSOR_MODIFIER_DEL, NM_META_ACCESSOR_MODIFIER_ADD), FALSE); if (!(property_info = nm_meta_property_info_find_by_setting (setting, prop))) goto out_fail_read_only; if (!property_info->property_type->set_fcn) goto out_fail_read_only; - if ( NM_IN_SET (modifier, '+', '-') - && !value) { - /* nothing to do. */ - return TRUE; - } - - if ( modifier == '-' + if ( modifier == NM_META_ACCESSOR_MODIFIER_DEL && !property_info->property_type->set_supports_remove) { /* The property is a plain property. It does not support '-'. * @@ -578,6 +558,13 @@ nmc_setting_set_property (NMClient *client, } } + if ( NM_IN_SET (modifier, NM_META_ACCESSOR_MODIFIER_ADD, NM_META_ACCESSOR_MODIFIER_DEL) + && ( !value + || !value[0])) { + /* nothing to do. */ + return TRUE; + } + g_object_freeze_notify (G_OBJECT (setting)); success = property_info->property_type->set_fcn (property_info, nmc_meta_environment, diff --git a/clients/cli/settings.h b/clients/cli/settings.h index 1ff93685..59ad5e87 100644 --- a/clients/cli/settings.h +++ b/clients/cli/settings.h @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2014 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2014 Red Hat, Inc. */ #ifndef NMC_SETTINGS_H @@ -45,7 +31,7 @@ char *nmc_setting_get_property_parsable (NMSetting *setting, gboolean nmc_setting_set_property (NMClient *client, NMSetting *setting, const char *prop, - char modifier, + NMMetaAccessorModifier modifier, const char *val, GError **error); diff --git a/clients/cli/utils.c b/clients/cli/utils.c index a822dd89..2e3a38f7 100644 --- a/clients/cli/utils.c +++ b/clients/cli/utils.c @@ -1,21 +1,7 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 Lennart Poettering - * Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 Lennart Poettering + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/clients/cli/utils.h b/clients/cli/utils.h index 82b186b7..e699a641 100644 --- a/clients/cli/utils.h +++ b/clients/cli/utils.h @@ -1,20 +1,6 @@ -/* nmcli - command-line tool to control NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #ifndef NMC_UTILS_H @@ -144,6 +130,7 @@ typedef enum { NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_NAME = 0, NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_UUID, NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEVICES, + NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_IP_IFACE, NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_STATE, NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEFAULT, NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEFAULT6, @@ -177,6 +164,7 @@ typedef enum { NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE = 0, NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE, NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DBUS_PATH, NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR, NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT, NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER, @@ -226,8 +214,14 @@ typedef enum { NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ, NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ, NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_MESH, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_IBSS_RSN, _NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_NUM, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_UP = 0, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_LOWER_UP, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_CARRIER, + _NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_NUM, + } NmcGenericInfoType; #define NMC_HANDLE_COLOR(color) \ |