mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-29 20:50:11 +01:00
device,cli: merge branch 'th/reapply-fixes-bgo765848'
https://bugzilla.gnome.org/show_bug.cgi?id=765848
(cherry picked from commit f5ae41656a)
This commit is contained in:
commit
acf9bad08a
10 changed files with 75 additions and 199 deletions
|
|
@ -1170,10 +1170,6 @@ nmc_set_in_readline (gboolean in_readline)
|
|||
pthread_mutex_unlock (&readline_mutex);
|
||||
}
|
||||
|
||||
/* Global variable defined in nmcli.c */
|
||||
extern NmCli nm_cli;
|
||||
|
||||
|
||||
static char *
|
||||
nmc_readline_helper (const char *prompt)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -261,9 +261,6 @@ typedef struct {
|
|||
} TabCompletionInfo;
|
||||
static TabCompletionInfo nmc_tab_completion = {NULL, NULL, NULL, NULL};
|
||||
|
||||
/* Global variable defined in nmcli.c - used for TAB completion */
|
||||
extern NmCli nm_cli;
|
||||
|
||||
static char *gen_connection_types (const char *text, int state);
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ usage (void)
|
|||
" show [<ifname>]\n\n"
|
||||
" set [ifname] <ifname> [autoconnect yes|no] [managed yes|no]\n\n"
|
||||
" connect <ifname>\n\n"
|
||||
" reapply <ifname> ...\n\n"
|
||||
" reapply <ifname>\n\n"
|
||||
" disconnect <ifname> ...\n\n"
|
||||
" delete <ifname> ...\n\n"
|
||||
" monitor <ifname> ...\n\n"
|
||||
|
|
@ -342,7 +342,7 @@ usage_device_reapply (void)
|
|||
{
|
||||
g_printerr (_("Usage: nmcli device reapply { ARGUMENTS | help }\n"
|
||||
"\n"
|
||||
"ARGUMENTS := <ifname> ...\n"
|
||||
"ARGUMENTS := <ifname>\n"
|
||||
"\n"
|
||||
"Attempts to update device with changes to the currently active connection\n"
|
||||
"made since it was last applied.\n\n"));
|
||||
|
|
@ -1835,11 +1835,10 @@ reapply_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
|||
GError *error = NULL;
|
||||
|
||||
if (!nm_device_reapply_finish (device, result, &error)) {
|
||||
g_string_printf (nmc->return_text, _("Error: not all connections reapplied."));
|
||||
g_printerr (_("Error: Reapplying connection to device '%s' (%s) failed: %s\n"),
|
||||
nm_device_get_iface (device),
|
||||
nm_object_get_path (NM_OBJECT (device)),
|
||||
error->message);
|
||||
g_string_printf (nmc->return_text, _("Error: Reapplying connection to device '%s' (%s) failed: %s"),
|
||||
nm_device_get_iface (device),
|
||||
nm_object_get_path (NM_OBJECT (device)),
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT;
|
||||
device_cb_info_finish (info, device);
|
||||
|
|
@ -1847,7 +1846,7 @@ reapply_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
|||
if (nmc->print_output == NMC_PRINT_PRETTY)
|
||||
nmc_terminal_erase_line ();
|
||||
g_print (_("Connection successfully reapplied to device '%s'.\n"),
|
||||
nm_device_get_iface (device));
|
||||
nm_device_get_iface (device));
|
||||
device_cb_info_finish (info, device);
|
||||
}
|
||||
}
|
||||
|
|
@ -1855,14 +1854,14 @@ reapply_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
|||
static NMCResultCode
|
||||
do_device_reapply (NmCli *nmc, int argc, char **argv)
|
||||
{
|
||||
NMDevice **devices;
|
||||
NMDevice *device;
|
||||
gs_free NMDevice **devices = NULL;
|
||||
NMDevice *device = NULL;
|
||||
DeviceCbInfo *info = NULL;
|
||||
GSList *queue = NULL, *iter;
|
||||
char **arg_arr = NULL;
|
||||
char **arg_ptr = argv;
|
||||
int arg_num = argc;
|
||||
int i;
|
||||
gs_free char *device_name_free = NULL;
|
||||
const char *device_name = NULL;
|
||||
|
||||
/* Set default timeout for reapply operation. */
|
||||
if (nmc->timeout == -1)
|
||||
|
|
@ -1870,69 +1869,48 @@ do_device_reapply (NmCli *nmc, int argc, char **argv)
|
|||
|
||||
if (argc == 0) {
|
||||
if (nmc->ask) {
|
||||
char *line = nmc_readline (PROMPT_INTERFACES);
|
||||
nmc_string_to_arg_array (line, NULL, FALSE, &arg_arr, &arg_num);
|
||||
g_free (line);
|
||||
arg_ptr = arg_arr;
|
||||
device_name_free = nmc_readline (PROMPT_INTERFACE);
|
||||
device_name = device_name_free;
|
||||
}
|
||||
if (arg_num == 0) {
|
||||
if (!device_name) {
|
||||
g_string_printf (nmc->return_text, _("Error: No interface specified."));
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
goto error;
|
||||
return nmc->return_value;
|
||||
}
|
||||
} else if (argc == 1) {
|
||||
device_name = arg_ptr[0];
|
||||
next_arg (&arg_num, &arg_ptr);
|
||||
} else {
|
||||
next_arg (&arg_num, &arg_ptr);
|
||||
g_string_printf (nmc->return_text, _("Error: unsupported argument '%s'."), *arg_ptr);
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
return nmc->return_value;
|
||||
}
|
||||
|
||||
devices = get_devices_sorted (nmc->client);
|
||||
while (arg_num > 0) {
|
||||
device = NULL;
|
||||
for (i = 0; devices[i]; i++) {
|
||||
if (!g_strcmp0 (nm_device_get_iface (devices[i]), *arg_ptr)) {
|
||||
device = devices[i];
|
||||
break;
|
||||
}
|
||||
for (i = 0; devices[i]; i++) {
|
||||
if (!g_strcmp0 (nm_device_get_iface (devices[i]), device_name)) {
|
||||
device = devices[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (device) {
|
||||
if (!g_slist_find (queue, device))
|
||||
queue = g_slist_prepend (queue, device);
|
||||
else
|
||||
g_printerr (_("Warning: argument '%s' is duplicated.\n"), *arg_ptr);
|
||||
} else {
|
||||
g_printerr (_("Error: Device '%s' not found.\n"), *arg_ptr);
|
||||
g_string_printf (nmc->return_text, _("Error: not all devices found."));
|
||||
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Take next argument */
|
||||
next_arg (&arg_num, &arg_ptr);
|
||||
}
|
||||
g_free (devices);
|
||||
|
||||
if (!queue) {
|
||||
g_string_printf (nmc->return_text, _("Error: no valid device provided."));
|
||||
if (!device) {
|
||||
g_string_printf (nmc->return_text, _("Error: device '%s' not found."), device_name);
|
||||
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
||||
goto error;
|
||||
return nmc->return_value;
|
||||
}
|
||||
queue = g_slist_reverse (queue);
|
||||
|
||||
info = g_slice_new0 (DeviceCbInfo);
|
||||
info->nmc = nmc;
|
||||
|
||||
nmc->nowait_flag = (nmc->timeout == 0);
|
||||
nmc->should_wait = TRUE;
|
||||
|
||||
for (iter = queue; iter; iter = g_slist_next (iter)) {
|
||||
device = iter->data;
|
||||
info = g_slice_new0 (DeviceCbInfo);
|
||||
info->nmc = nmc;
|
||||
info->queue = g_slist_prepend (info->queue, g_object_ref (device));
|
||||
|
||||
info->queue = g_slist_prepend (info->queue, g_object_ref (device));
|
||||
/* Now reapply the connection to the device */
|
||||
nm_device_reapply_async (device, NULL, 0, 0, NULL, reapply_device_cb, info);
|
||||
|
||||
/* Now reapply the connection to the device */
|
||||
nm_device_reapply_async (device, NULL, 0, 0, NULL, reapply_device_cb, info);
|
||||
}
|
||||
|
||||
error:
|
||||
g_strfreev (arg_arr);
|
||||
g_slist_free (queue);
|
||||
return nmc->return_value;
|
||||
}
|
||||
|
||||
|
|
@ -3594,9 +3572,6 @@ is_single_word (const char* line)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Global variable defined in nmcli.c */
|
||||
extern NmCli nm_cli;
|
||||
|
||||
static char *
|
||||
gen_func_ifnames (const char *text, int state)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1425,12 +1425,12 @@ _nmcli()
|
|||
fi
|
||||
;;
|
||||
sh|sho|show| \
|
||||
r|re|rea|reap|reapp|reappl|reapply| \
|
||||
c|co|con|conn|conne|connec|connect)
|
||||
if [[ ${#words[@]} -eq 3 ]]; then
|
||||
_nmcli_compl_COMMAND_nl "${words[2]}" "$(_nmcli_dev_status DEVICE)"
|
||||
fi
|
||||
;;
|
||||
r|re|rea|reap|reapp|reappl|reapply| \
|
||||
d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect| \
|
||||
de|del|dele|delet|delete| \
|
||||
m|mo|mon|moni|monit|monito|monitor)
|
||||
|
|
|
|||
|
|
@ -161,6 +161,8 @@ typedef struct _NmCli {
|
|||
NmcTermColor editor_prompt_color; /* Color of prompt in connection editor */
|
||||
} NmCli;
|
||||
|
||||
extern NmCli nm_cli;
|
||||
|
||||
/* Error quark for GError domain */
|
||||
#define NMCLI_ERROR (nmcli_error_quark ())
|
||||
GQuark nmcli_error_quark (void);
|
||||
|
|
@ -169,5 +171,4 @@ gboolean nmc_seen_sigint (void);
|
|||
void nmc_clear_sigint (void);
|
||||
void nmc_set_sigquit_internal (void);
|
||||
|
||||
|
||||
#endif /* NMC_NMCLI_H */
|
||||
|
|
|
|||
|
|
@ -2082,13 +2082,6 @@ typedef struct {
|
|||
NmcPropertyFuncsFields
|
||||
} NmcPropertyFuncs;
|
||||
|
||||
/*
|
||||
* We need NmCli in some _set_property functions, and they aren't passed NmCli.
|
||||
* So use the global variable.
|
||||
*/
|
||||
/* Global variable defined in nmcli.c */
|
||||
extern NmCli nm_cli;
|
||||
|
||||
NMSetting *
|
||||
nmc_setting_new_for_name (const char *name)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -181,60 +181,6 @@ ssid_to_hex (const char *str, gsize len)
|
|||
return printable_str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts IPv4 address from guint32 in network-byte order to text representation.
|
||||
* Returns: text form of the IP or NULL (then error is set)
|
||||
*/
|
||||
char *
|
||||
nmc_ip4_address_as_string (guint32 ip, GError **error)
|
||||
{
|
||||
guint32 tmp_addr;
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
memset (&buf, '\0', sizeof (buf));
|
||||
tmp_addr = ip;
|
||||
|
||||
if (inet_ntop (AF_INET, &tmp_addr, buf, INET_ADDRSTRLEN)) {
|
||||
return g_strdup (buf);
|
||||
} else {
|
||||
g_set_error (error, NMCLI_ERROR, 0, _("Error converting IP4 address '0x%X' to text form"),
|
||||
ntohl (tmp_addr));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts IPv6 address in in6_addr structure to text representation.
|
||||
* Returns: text form of the IP or NULL (then error is set)
|
||||
*/
|
||||
char *
|
||||
nmc_ip6_address_as_string (const struct in6_addr *ip, GError **error)
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
memset (&buf, '\0', sizeof (buf));
|
||||
|
||||
if (inet_ntop (AF_INET6, ip, buf, INET6_ADDRSTRLEN)) {
|
||||
return g_strdup (buf);
|
||||
} else {
|
||||
if (error) {
|
||||
int j;
|
||||
GString *ip6_str = g_string_new (NULL);
|
||||
g_string_append_printf (ip6_str, "%02X", ip->s6_addr[0]);
|
||||
for (j = 1; j < 16; j++)
|
||||
g_string_append_printf (ip6_str, " %02X", ip->s6_addr[j]);
|
||||
g_set_error (error, NMCLI_ERROR, 0, _("Error converting IP6 address '%s' to text form"),
|
||||
ip6_str->str);
|
||||
g_string_free (ip6_str, TRUE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Erase terminal line using ANSI escape sequences.
|
||||
* It prints <ESC>[2K sequence to erase the line and then \r to return back
|
||||
|
|
@ -706,23 +652,6 @@ finish:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert string array (char **) to GSList.
|
||||
*
|
||||
* Returns: pointer to newly created GSList. Caller should free it.
|
||||
*/
|
||||
GSList *
|
||||
nmc_util_strv_to_slist (char **strv)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
guint i = 0;
|
||||
|
||||
while (strv && strv[i])
|
||||
list = g_slist_prepend (list, g_strdup (strv[i++]));
|
||||
|
||||
return g_slist_reverse (list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert string array (char **) to description string in the form of:
|
||||
* "[string1, string2, ]"
|
||||
|
|
|
|||
|
|
@ -69,8 +69,6 @@ gboolean nmc_string_to_uint (const char *str,
|
|||
unsigned long int *value);
|
||||
gboolean nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error);
|
||||
gboolean nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error);
|
||||
char *nmc_ip4_address_as_string (guint32 ip, GError **error);
|
||||
char *nmc_ip6_address_as_string (const struct in6_addr *ip, GError **error);
|
||||
void nmc_terminal_erase_line (void);
|
||||
void nmc_terminal_show_progress (const char *str);
|
||||
const char *nmc_term_color_sequence (NmcTermColor color);
|
||||
|
|
@ -83,7 +81,6 @@ char *nmc_get_user_input (const char *ask_str);
|
|||
int nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote,
|
||||
char ***argv, int *argc);
|
||||
const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
|
||||
GSList *nmc_util_strv_to_slist (char **strv);
|
||||
char * nmc_util_strv_for_display (const char **strv, gboolean brackets);
|
||||
char **nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens);
|
||||
int nmc_string_screen_width (const char *start, const char *end);
|
||||
|
|
|
|||
|
|
@ -45,8 +45,7 @@ gint64
|
|||
_nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
|
||||
{
|
||||
gint64 v;
|
||||
size_t len;
|
||||
char buf[64], *s, *str_free = NULL;
|
||||
char *s = NULL;
|
||||
|
||||
if (str) {
|
||||
while (g_ascii_isspace (str[0]))
|
||||
|
|
@ -57,46 +56,24 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma
|
|||
return fallback;
|
||||
}
|
||||
|
||||
len = strlen (str);
|
||||
if (g_ascii_isspace (str[--len])) {
|
||||
/* backward search the first non-ws character.
|
||||
* We already know that str[0] is non-ws. */
|
||||
while (g_ascii_isspace (str[--len]))
|
||||
;
|
||||
|
||||
/* str[len] is now the last non-ws character... */
|
||||
len++;
|
||||
|
||||
if (len >= sizeof (buf))
|
||||
s = str_free = g_malloc (len + 1);
|
||||
else
|
||||
s = buf;
|
||||
|
||||
memcpy (s, str, len);
|
||||
s[len] = 0;
|
||||
|
||||
nm_assert (len > 0 && len < strlen (str) && len == strlen (s));
|
||||
nm_assert (!g_ascii_isspace (str[len-1]) && g_ascii_isspace (str[len]));
|
||||
nm_assert (strncmp (str, s, len) == 0);
|
||||
|
||||
str = s;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
v = g_ascii_strtoll (str, &s, base);
|
||||
|
||||
if (errno != 0)
|
||||
v = fallback;
|
||||
else if (s[0] != 0) {
|
||||
errno = EINVAL;
|
||||
v = fallback;
|
||||
} else if (v > max || v < min) {
|
||||
return fallback;
|
||||
if (s[0] != '\0') {
|
||||
while (g_ascii_isspace (s[0]))
|
||||
s++;
|
||||
if (s[0] != '\0') {
|
||||
errno = EINVAL;
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
if (v > max || v < min) {
|
||||
errno = ERANGE;
|
||||
v = fallback;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (str_free))
|
||||
g_free (str_free);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7178,22 +7178,25 @@ _hash_check_invalid_keys_impl (GHashTable *hash, const char *setting_name, GErro
|
|||
|
||||
g_hash_table_iter_init (&iter, hash);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &k, NULL)) {
|
||||
for (i = 0; argv[i]; i++) {
|
||||
if (!strcmp (argv[i], k)) {
|
||||
first_invalid_key = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (first_invalid_key)
|
||||
if (_nm_utils_strv_find_first ((char **) argv, -1, k) < 0) {
|
||||
first_invalid_key = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (setting_name) {
|
||||
g_set_error (error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
|
||||
"Can't reapply changes to '%s.%s' setting",
|
||||
setting_name,
|
||||
first_invalid_key);
|
||||
} else {
|
||||
g_set_error (error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
|
||||
"Can't reapply any changes to '%s' setting",
|
||||
first_invalid_key);
|
||||
}
|
||||
g_set_error (error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
|
||||
"Can't reapply changes to '%s%s%s' setting",
|
||||
setting_name ? : "",
|
||||
setting_name ? "." : "",
|
||||
first_invalid_key ? : "<UNKNOWN>");
|
||||
g_return_val_if_fail (first_invalid_key, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -7314,9 +7317,16 @@ reapply_connection (NMDevice *self,
|
|||
NM_SETTING_CONNECTION_SETTING_NAME))
|
||||
return FALSE;
|
||||
|
||||
/* whitelist allowed properties from "connection" setting which are allowed to differ.
|
||||
*
|
||||
* This includes UUID, there is no principal problem with reapplying a connection
|
||||
* and changing it's UUID. In fact, disallowing it makes it cumbersome for the user
|
||||
* to reapply any connection but the original settings-connection. */
|
||||
if (!_hash_check_invalid_keys (diffs ? g_hash_table_lookup (diffs, NM_SETTING_CONNECTION_SETTING_NAME) : NULL,
|
||||
NM_SETTING_CONNECTION_SETTING_NAME,
|
||||
error,
|
||||
NM_SETTING_CONNECTION_ID,
|
||||
NM_SETTING_CONNECTION_UUID,
|
||||
NM_SETTING_CONNECTION_ZONE,
|
||||
NM_SETTING_CONNECTION_METERED))
|
||||
return FALSE;
|
||||
|
|
@ -7345,6 +7355,7 @@ reapply_connection (NMDevice *self,
|
|||
con_old = applied_clone = nm_simple_connection_new_clone (applied);
|
||||
con_new = applied;
|
||||
nm_connection_replace_settings_from_connection (applied, connection);
|
||||
nm_connection_clear_secrets (applied);
|
||||
} else
|
||||
con_old = con_new = applied;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue