diff options
| author | Michael Biebl <biebl@debian.org> | 2026-05-14 19:21:22 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2026-05-14 19:21:22 +0200 |
| commit | 869e9027026cdbb15d4e4a6327ff41d2697858eb (patch) | |
| tree | 52edec7f935ff1bbb425c3515c6e49e6b8b0e28b /src/nmcli/devices.c | |
| parent | 067fb576988f685e83ac8b0ae690334aff547c85 (diff) | |
New upstream version 1.56.1 upstream/1.56.1
Diffstat (limited to 'src/nmcli/devices.c')
| -rw-r--r-- | src/nmcli/devices.c | 214 |
1 files changed, 171 insertions, 43 deletions
diff --git a/src/nmcli/devices.c b/src/nmcli/devices.c index e81e710f..2787439e 100644 --- a/src/nmcli/devices.c +++ b/src/nmcli/devices.c @@ -854,7 +854,8 @@ usage(void) "delete | monitor | wifi | lldp }\n\n" " status\n\n" " show [<ifname>]\n\n" - " set [ifname] <ifname> [autoconnect yes|no] [managed yes|no]\n\n" + " set [ifname] <ifname> [autoconnect yes|no] [managed [--permanent|--permanent-only] " + "yes|no|up|down|reset]\n\n" " connect <ifname>\n\n" " reapply <ifname>\n\n" " modify <ifname> ([+|-]<setting>.<property> <value>)+\n\n" @@ -972,14 +973,15 @@ usage_device_delete(void) static void usage_device_set(void) { - nmc_printerr(_("Usage: nmcli device set { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := DEVICE { PROPERTY [ PROPERTY ... ] }\n" - "DEVICE := [ifname] <ifname> \n" - "PROPERTY := { autoconnect { yes | no } |\n" - " { managed { yes | no }\n" - "\n" - "Modify device properties.\n\n")); + nmc_printerr(_( + "Usage: nmcli device set { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := DEVICE { PROPERTY [ PROPERTY ... ] }\n" + "DEVICE := [ifname] <ifname> \n" + "PROPERTY := { autoconnect { yes | no } |\n" + " { managed [--permanent | --permanent-only] { yes | no | up | down | reset }\n" + "\n" + "Modify device properties.\n\n")); } static void @@ -2793,20 +2795,62 @@ do_devices_delete(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const } } +typedef struct { + NmCli *nmc; + GSource *timeout_source; +} DeviceSetCbInfo; + +static void +device_set_cb_info_finish(DeviceSetCbInfo *info) +{ + nm_clear_g_source_inst(&info->timeout_source); + g_slice_free(DeviceSetCbInfo, info); + quit(); +} + +static gboolean +device_set_timeout_cb(gpointer user_data) +{ + DeviceSetCbInfo *cb_info = user_data; + + timeout_cb(cb_info->nmc); + device_set_cb_info_finish(cb_info); + return G_SOURCE_REMOVE; +} + +static void +device_set_cb(GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMDevice *device = NM_DEVICE(object); + DeviceSetCbInfo *info = (DeviceSetCbInfo *) user_data; + NmCli *nmc = info->nmc; + gs_free_error GError *error = NULL; + + /* Only 'managed' is treated asynchronously, 'autoconnect' is treated synchronously */ + if (!nm_device_set_managed_finish(device, result, &error)) { + g_string_printf(nmc->return_text, _("Error: set managed failed: %s."), error->message); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + } + + device_set_cb_info_finish(info); +} + static void do_device_set(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv) { -#define DEV_SET_AUTOCONNECT 0 -#define DEV_SET_MANAGED 1 - NMDevice *device = NULL; - int i; + NMDevice *device = NULL; + DeviceSetCbInfo *cb_info = NULL; + int i; struct { int idx; gboolean value; - } values[2] = { - [DEV_SET_AUTOCONNECT] = {-1}, - [DEV_SET_MANAGED] = {-1}, - }; + } autoconnect_data = {-1}; + struct { + int idx; + NMDeviceManaged value; + guint32 flags; + } managed_data = {-1}; + gs_free_error GError *error = NULL; next_arg(nmc, &argc, &argv, NULL); @@ -2828,49 +2872,120 @@ do_device_set(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *ar i = 0; do { - gboolean flag; - if (argc == 1 && nmc->complete) nmc_complete_strings(*argv, "managed", "autoconnect"); if (matches(*argv, "managed")) { + NMDeviceManaged val; + guint32 flags = 0; + gboolean val_bool; + gboolean perm = FALSE, perm_only = FALSE; + argc--; argv++; + + if (argc == 1 && nmc->complete) { + nmc_complete_strings(*argv, + "true", + "yes", + "on", + "false", + "no", + "off", + "up", + "down", + "reset", + "--permanent", + "--permanent-only"); + } + + if (managed_data.idx != -1) { + g_string_printf(nmc->return_text, _("Error: 'managed' can only be set once.")); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + return; + } + + while (argc > 0) { + /* --perm matches with --permanent, the most common, + * but --permanent-only requires a exact match */ + if (nm_streq0(*argv, "--permanent-only")) + perm_only = TRUE; + else if (matches(*argv, "--permanent")) + perm = TRUE; + else + break; + argc--; + argv++; + } + + if (perm_only && perm) { + g_string_printf( + nmc->return_text, + _("Error: '--permanent-only' and '--permanent' cannot be used together.")); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + return; + } else if (perm) { + flags |= NM_DEVICE_MANAGED_FLAGS_RUNTIME | NM_DEVICE_MANAGED_FLAGS_PERMANENT; + } else if (perm_only) { + flags |= NM_DEVICE_MANAGED_FLAGS_PERMANENT; + } else { + /* If --permanent/--permanent-only are missing, set only the runtime flag, as this + * is how it used to work when these options didn't exist. */ + flags |= NM_DEVICE_MANAGED_FLAGS_RUNTIME; + } + if (!argc) { - g_string_printf(nmc->return_text, - _("Error: '%s' argument is missing."), - *(argv - 1)); + g_string_printf(nmc->return_text, _("Error: 'managed' argument is missing.")); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return; } - if (argc == 1 && nmc->complete) - nmc_complete_bool(*argv); - if (!nmc_string_to_bool(*argv, &flag, &error)) { - g_string_printf(nmc->return_text, _("Error: 'managed': %s."), error->message); + + if (matches(*argv, "up") || matches(*argv, "down")) { + flags |= NM_DEVICE_MANAGED_FLAGS_SET_ADMIN_STATE; + val = matches(*argv, "up") ? NM_DEVICE_MANAGED_YES : NM_DEVICE_MANAGED_NO; + } else if (matches(*argv, "reset")) { + val = NM_DEVICE_MANAGED_RESET; + } else if (nmc_string_to_bool(*argv, &val_bool, NULL)) { + val = val_bool ? NM_DEVICE_MANAGED_YES : NM_DEVICE_MANAGED_NO; + } else { + g_string_printf( + nmc->return_text, + _("Error: 'managed': '%s' is not valid, use 'yes/no/up/down/reset'."), + *argv); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return; } - values[DEV_SET_MANAGED].idx = ++i; - values[DEV_SET_MANAGED].value = flag; + + managed_data.idx = i++; + managed_data.value = val; + managed_data.flags = flags; } else if (matches(*argv, "autoconnect")) { + gboolean val; + argc--; argv++; + if (!argc) { - g_string_printf(nmc->return_text, - _("Error: '%s' argument is missing."), - *(argv - 1)); + g_string_printf(nmc->return_text, _("Error: 'autoconnect' argument is missing.")); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return; } + if (autoconnect_data.idx != -1) { + g_string_printf(nmc->return_text, _("Error: 'autoconnect' can only be set once.")); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + return; + } + if (argc == 1 && nmc->complete) nmc_complete_bool(*argv); - if (!nmc_string_to_bool(*argv, &flag, &error)) { + + if (!nmc_string_to_bool(*argv, &val, &error)) { g_string_printf(nmc->return_text, _("Error: 'autoconnect': %s."), error->message); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return; } - values[DEV_SET_AUTOCONNECT].idx = ++i; - values[DEV_SET_AUTOCONNECT].value = flag; + autoconnect_data.idx = i++; + autoconnect_data.value = val; } else { g_string_printf(nmc->return_text, _("Error: property '%s' is not known."), *argv); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; @@ -2883,15 +2998,28 @@ do_device_set(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *ar /* when multiple properties are specified, set them in the order as they * are specified on the command line. */ - if (values[DEV_SET_AUTOCONNECT].idx >= 0 && values[DEV_SET_MANAGED].idx >= 0 - && values[DEV_SET_MANAGED].idx < values[DEV_SET_AUTOCONNECT].idx) { - nm_device_set_managed(device, values[DEV_SET_MANAGED].value); - values[DEV_SET_MANAGED].idx = -1; - } - if (values[DEV_SET_AUTOCONNECT].idx >= 0) - nm_device_set_autoconnect(device, values[DEV_SET_AUTOCONNECT].value); - if (values[DEV_SET_MANAGED].idx >= 0) - nm_device_set_managed(device, values[DEV_SET_MANAGED].value); + for (i = 0; i < 2; i++) { + if (autoconnect_data.idx == i) { + nm_device_set_autoconnect(device, autoconnect_data.value); + } + if (managed_data.idx == i) { + cb_info = g_slice_new0(DeviceSetCbInfo); + cb_info->nmc = nmc; + if (nmc->timeout > 0) + cb_info->timeout_source = + nm_g_timeout_add_seconds_source(nmc->timeout, device_set_timeout_cb, cb_info); + + nmc->nowait_flag = (nmc->timeout == 0); + nmc->should_wait++; + + nm_device_set_managed_async(device, + managed_data.value, + managed_data.flags, + NULL, + device_set_cb, + cb_info); + } + } } static void |