about summary refs log tree commit diff
path: root/src/nmcli
diff options
context:
space:
mode:
Diffstat (limited to 'src/nmcli')
-rw-r--r--src/nmcli/connections.c18
-rw-r--r--src/nmcli/devices.c214
-rw-r--r--src/nmcli/gen-metadata-nm-settings-nmcli.xml.in32
3 files changed, 213 insertions, 51 deletions
diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c
index d93e16f0..a3b03efe 100644
--- a/src/nmcli/connections.c
+++ b/src/nmcli/connections.c
@@ -4,6 +4,7 @@
  */
 
 #include "libnm-client-aux-extern/nm-default-client.h"
+#include "nmcli.h"
 
 #include "connections.h"
 
@@ -1070,13 +1071,13 @@ const NmcMetaGenericInfo
     "," NM_SETTING_DCB_SETTING_NAME "," NM_SETTING_TUN_SETTING_NAME                    \
     "," NM_SETTING_IP_TUNNEL_SETTING_NAME "," NM_SETTING_MACSEC_SETTING_NAME           \
     "," NM_SETTING_MACVLAN_SETTING_NAME "," NM_SETTING_VXLAN_SETTING_NAME              \
-    "," NM_SETTING_VRF_SETTING_NAME "," NM_SETTING_WPAN_SETTING_NAME                   \
-    "," NM_SETTING_6LOWPAN_SETTING_NAME "," NM_SETTING_WIREGUARD_SETTING_NAME          \
-    "," NM_SETTING_LINK_SETTING_NAME "," NM_SETTING_PROXY_SETTING_NAME                 \
-    "," NM_SETTING_TC_CONFIG_SETTING_NAME "," NM_SETTING_SRIOV_SETTING_NAME            \
-    "," NM_SETTING_ETHTOOL_SETTING_NAME "," NM_SETTING_OVS_DPDK_SETTING_NAME           \
-    "," NM_SETTING_HOSTNAME_SETTING_NAME "," NM_SETTING_HSR_SETTING_NAME               \
-    "," NM_SETTING_IPVLAN_SETTING_NAME
+    "," NM_SETTING_GENEVE_SETTING_NAME "," NM_SETTING_VRF_SETTING_NAME                 \
+    "," NM_SETTING_WPAN_SETTING_NAME "," NM_SETTING_6LOWPAN_SETTING_NAME               \
+    "," NM_SETTING_WIREGUARD_SETTING_NAME "," NM_SETTING_LINK_SETTING_NAME             \
+    "," NM_SETTING_PROXY_SETTING_NAME "," NM_SETTING_TC_CONFIG_SETTING_NAME            \
+    "," NM_SETTING_SRIOV_SETTING_NAME "," NM_SETTING_ETHTOOL_SETTING_NAME              \
+    "," NM_SETTING_OVS_DPDK_SETTING_NAME "," NM_SETTING_HOSTNAME_SETTING_NAME          \
+    "," NM_SETTING_HSR_SETTING_NAME "," NM_SETTING_IPVLAN_SETTING_NAME
 /* NM_SETTING_DUMMY_SETTING_NAME NM_SETTING_WIMAX_SETTING_NAME */
 
 const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = {
@@ -1306,6 +1307,9 @@ usage_connection_add(void)
           "                  [source-port-min <0-65535>]\n"
           "                  [source-port-max <0-65535>]\n"
           "                  [destination-port <0-65535>]\n\n"
+          "    geneve:       id <GENEVE ID>\n"
+          "                  remote <IP address>\n"
+          "                  [destination-port <0-65535>]\n\n"
           "    wpan:         [short-addr <0x0000-0xffff>]\n"
           "                  [pan-id <0x0000-0xffff>]\n"
           "                  [page <default|0-31>]\n"
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
diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
index 881c41ca..7a9f4e9c 100644
--- a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
+++ b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
@@ -629,7 +629,7 @@
                   alias="type"
                   nmcli-description="Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, &quot;802-3-ethernet&quot; or &quot;802-11-wireless&quot; or &quot;bluetooth&quot;, etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, &quot;vpn&quot; or &quot;bridge&quot;, etc)."
                   format="string"
-                  values="6lowpan, 802-11-olpc-mesh, 802-11-wireless, 802-3-ethernet, adsl, bluetooth, bond, bridge, cdma, dummy, generic, gsm, hsr, infiniband, ip-tunnel, ipvlan, loopback, macsec, macvlan, ovs-bridge, ovs-interface, ovs-port, pppoe, team, tun, veth, vlan, vpn, vrf, vxlan, wifi-p2p, wimax, wireguard, wpan" />
+                  values="6lowpan, 802-11-olpc-mesh, 802-11-wireless, 802-3-ethernet, adsl, bluetooth, bond, bridge, cdma, dummy, generic, geneve, gsm, hsr, infiniband, ip-tunnel, ipvlan, loopback, macsec, macvlan, ovs-bridge, ovs-interface, ovs-port, pppoe, team, tun, veth, vlan, vpn, vrf, vxlan, wifi-p2p, wimax, wireguard, wpan" />
         <property name="interface-name"
                   alias="ifname"
                   nmcli-description="The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface."
@@ -1110,6 +1110,36 @@
                   nmcli-description="Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and &apos;-&apos;, &apos;_&apos;, &apos;.&apos;. It cannot start with &apos;.&apos;. See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler. By setting this property the generic connection becomes &quot;virtual&quot;, meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler."
                   format="string" />
     </setting>
+    <setting name="geneve" >
+        <property name="id"
+                  alias="id"
+                  nmcli-description="Specifies the GENEVE Network Identifier (or GENEVE Segment Identifier) to use."
+                  format="integer"
+                  values="0 - 16777215" />
+        <property name="remote"
+                  alias="remote"
+                  nmcli-description="Specifies the unicast destination IP address to use in outgoing packets when communicating with the remote GENEVE tunnel endpoint."
+                  format="string" />
+        <property name="destination-port"
+                  alias="destination-port"
+                  nmcli-description="Specifies the UDP destination port to communicate to the remote GENEVE tunnel endpoint."
+                  format="integer"
+                  values="0 - 65535" />
+        <property name="tos"
+                  nmcli-description="Specifies the TOS value to use in outgoing packets. The special value &quot;inherit&quot; (1) means inherit from outer packet."
+                  format="integer"
+                  values="0 - 255"
+                  special-values="inherit (1)" />
+        <property name="ttl"
+                  nmcli-description="Specifies the time-to-live value to use in outgoing packets. The special value &quot;inherit&quot; (-1) means inherit from outer packet, 0 means auto, 1-255 are fixed values."
+                  format="integer"
+                  values="-1 - 255"
+                  special-values="inherit (-1)" />
+        <property name="df"
+                  nmcli-description="Specifies how the Don&apos;t Fragment (DF) flag should be handled in the outer IP header of GENEVE tunnel packets. &quot;unset&quot; (0) (0): Don&apos;t set the DF flag, packets may be fragmented. &quot;set&quot; (1) (1): Always set the DF flag, packets will not be fragmented. &quot;inherit&quot; (2) (2): Inherit the DF flag from the inner IP header."
+                  format="choice (NMSettingGeneveDf)"
+                  values="unset (0), set (1), inherit (2)" />
+    </setting>
     <setting name="gsm" >
         <property name="auto-config"
                   nmcli-description="When TRUE, the settings such as APN, username, or password will default to values that match the network the modem will register to in the Mobile Broadband Provider database."