diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index c43663cb37..172b7f476d 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -14942,6 +14942,39 @@ typedef struct { NMDeviceManagedFlags managed_flags; } SetManagedData; +static gboolean +get_managed_by_mac(NMDevice *self, NMDeviceManagedFlags flags, GError **error) +{ + gboolean is_fake_hwaddr; + + if ((flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_MAC) + && (flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_NAME)) { + g_set_error_literal(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_ARGUMENT, + "cannot match both by 'mac' and by 'interface-name'"); + return FALSE; + } + + nm_device_get_permanent_hw_address_full(self, TRUE, &is_fake_hwaddr); + + if ((flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_MAC) && is_fake_hwaddr) { + g_set_error_literal( + error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_ARGUMENT, + "cannot match by 'mac': the device doesn't have a permanent MAC address"); + return FALSE; + } + + if (flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_MAC) + return TRUE; + else if (flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_NAME) + return FALSE; + else + return !is_fake_hwaddr; +} + /** * set_managed: * @self: the device @@ -14959,10 +14992,15 @@ static gboolean set_managed(NMDevice *self, NMDeviceManaged managed, NMDeviceManagedFlags flags, GError **error) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - gboolean managed_old, managed_new; - NMTernary managed_to_disk, managed_to_disk_old; if (flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT) { + NMTernary managed_to_disk, managed_to_disk_old; + gboolean by_mac; + + by_mac = get_managed_by_mac(self, flags, error); + if (*error) + return FALSE; + managed_to_disk = managed == NM_DEVICE_MANAGED_RESET ? NM_TERNARY_DEFAULT : !!managed; managed_to_disk_old = nm_config_get_device_managed(nm_manager_get_config(priv->manager), nm_device_get_iface(self)); @@ -14970,7 +15008,7 @@ set_managed(NMDevice *self, NMDeviceManaged managed, NMDeviceManagedFlags flags, if (!nm_config_set_device_managed(nm_manager_get_config(priv->manager), self, managed_to_disk, - flags & NM_DEVICE_MANAGED_FLAGS_BY_MAC, + by_mac, error)) return FALSE; @@ -14986,8 +15024,8 @@ set_managed(NMDevice *self, NMDeviceManaged managed, NMDeviceManagedFlags flags, nm_config_set_device_managed(nm_manager_get_config(priv->manager), self, managed_to_disk_old, - flags & NM_DEVICE_MANAGED_FLAGS_BY_MAC, - error); + by_mac, + NULL); g_set_error(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, @@ -14999,6 +15037,8 @@ set_managed(NMDevice *self, NMDeviceManaged managed, NMDeviceManagedFlags flags, } if (flags & NM_DEVICE_MANAGED_FLAGS_RUNTIME) { + gboolean managed_old, managed_new; + if (managed == NM_DEVICE_MANAGED_RESET) { nm_device_set_unmanaged_by_flags(self, NM_UNMANAGED_USER_EXPLICIT, diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h index 08405b7639..d63d05f341 100644 --- a/src/libnm-core-public/nm-dbus-interface.h +++ b/src/libnm-core-public/nm-dbus-interface.h @@ -1266,8 +1266,8 @@ typedef enum { * @NM_DEVICE_MANAGED_FLAGS_NONE: no flag set. * @NM_DEVICE_MANAGED_FLAGS_RUNTIME: to set the device managed state to the runtime value. * @NM_DEVICE_MANAGED_FLAGS_PERMANENT: to set the device managed state to the permanent (on disk) value. - * @NM_DEVICE_MANAGED_FLAGS_BY_MAC: to match the device by MAC address, not by name. - * This option only makes sense together with %NM_DEVICE_MANAGED_FLAGS_PERMANENT. + * @NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_NAME: to match the device by name, not by MAC address. + * @NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_MAC: to match the device by MAC address, not by name. * @NM_DEVICE_MANAGED_FLAGS_SET_ADMIN_STATE: to set the administrative state of the * device to up if the managed state is %NM_DEVICE_MANAGED_YES, and down if the managed state * is %NM_DEVICE_MANAGED_NO. If the flag is not set, the administrative state is not changed. @@ -1275,14 +1275,19 @@ typedef enum { * * Flags for the SetManaged() D-Bus call of a device and nm_device_set_managed_async(). * + * %NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_NAME and %NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_MAC + * are mutually exclusive, and they only make sense together with %NM_DEVICE_MANAGED_FLAGS_PERMANENT. + * If none is set, the matching criteria is selected automatically. + * * Since: 1.58 */ typedef enum /*< flags >*/ { - NM_DEVICE_MANAGED_FLAGS_NONE = 0, - NM_DEVICE_MANAGED_FLAGS_RUNTIME = 0x1, - NM_DEVICE_MANAGED_FLAGS_PERMANENT = 0x2, - NM_DEVICE_MANAGED_FLAGS_BY_MAC = 0x4, - NM_DEVICE_MANAGED_FLAGS_SET_ADMIN_STATE = 0x8, + NM_DEVICE_MANAGED_FLAGS_NONE = 0, + NM_DEVICE_MANAGED_FLAGS_RUNTIME = 0x1, + NM_DEVICE_MANAGED_FLAGS_PERMANENT = 0x2, + NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_NAME = 0x4, + NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_MAC = 0x8, + NM_DEVICE_MANAGED_FLAGS_SET_ADMIN_STATE = 0x10, } NMDeviceManagedFlags; /** diff --git a/src/nmcli/devices.c b/src/nmcli/devices.c index d30b434195..310baddd67 100644 --- a/src/nmcli/devices.c +++ b/src/nmcli/devices.c @@ -2903,10 +2903,9 @@ do_device_set(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *ar nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return; } else if (perm) { - flags |= NM_DEVICE_MANAGED_FLAGS_RUNTIME | NM_DEVICE_MANAGED_FLAGS_PERMANENT - | NM_DEVICE_MANAGED_FLAGS_BY_MAC; + flags |= NM_DEVICE_MANAGED_FLAGS_RUNTIME | NM_DEVICE_MANAGED_FLAGS_PERMANENT; } else if (perm_only) { - flags |= NM_DEVICE_MANAGED_FLAGS_PERMANENT | NM_DEVICE_MANAGED_FLAGS_BY_MAC; + 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. */