diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index b559b46c3e..e92f8be981 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -14942,6 +14942,43 @@ typedef struct { NMDeviceManagedFlags managed_flags; } SetManagedData; +static gboolean +get_managed_match_by_mac(NMDevice *self, NMDeviceManagedFlags flags, gboolean *out, GError **error) +{ + gboolean is_fake_hwaddr; + + nm_assert(out); + + 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) + *out = TRUE; + else if (flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT_BY_NAME) + *out = FALSE; + else + *out = !is_fake_hwaddr; + + return TRUE; +} + /** * set_managed: * @self: the device @@ -14959,7 +14996,6 @@ static gboolean set_managed(NMDevice *self, NMDeviceManaged managed, NMDeviceManagedFlags flags, GError **error) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMTernary managed_to_disk, old; if (!NM_FLAGS_ANY(flags, NM_DEVICE_MANAGED_FLAGS_PERMANENT | NM_DEVICE_MANAGED_FLAGS_RUNTIME)) { g_set_error_literal(error, @@ -14970,14 +15006,19 @@ set_managed(NMDevice *self, NMDeviceManaged managed, NMDeviceManagedFlags flags, } if (flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT) { + NMTernary managed_to_disk, old; + gboolean by_mac; + managed_to_disk = managed == NM_DEVICE_MANAGED_RESET ? NM_TERNARY_DEFAULT : !!managed; + if (!get_managed_match_by_mac(self, flags, &by_mac, error)) + return FALSE; if (!nm_config_get_device_managed(nm_manager_get_config(priv->manager), self, &old, error)) return FALSE; 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; @@ -14993,7 +15034,7 @@ set_managed(NMDevice *self, NMDeviceManaged managed, NMDeviceManagedFlags flags, nm_config_set_device_managed(nm_manager_get_config(priv->manager), self, old, - flags & NM_DEVICE_MANAGED_FLAGS_BY_MAC, + by_mac, NULL); g_set_error(error, NM_DEVICE_ERROR, 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; /**