core: device: allow to reset the managed property

Previous commits added the capability to persist to disk the value of
'managed' received via the D-Bus API. Users might need to clear the
previous content, thus reseting it to its default.

Although this is specially useful for the PERMANENT flag, we need to be
consistent and reset the runtime state too.
This commit is contained in:
Íñigo Huguet 2026-02-23 16:02:49 +01:00
parent 60a77f0fab
commit b5bb4e578f
6 changed files with 52 additions and 24 deletions

View file

@ -396,7 +396,7 @@
<!--
SetManaged:
@managed: Whether the device is managed.
@managed:(<link linkend="NMDeviceState">NMDeviceManaged</link>) Whether the device is managed. Possible values are "no" (0), "yes" (1) and "reset" (2).
@flags: (<link linkend="NMDeviceManagedFlags">NMDeviceManagedFlags</link>) flags.
@since: 1.58
@ -404,7 +404,7 @@
behaviors can be achieved, like storing the new managed state to disk.
-->
<method name="SetManaged">
<arg name="managed" type="b" direction="in"/>
<arg name="managed" type="u" direction="in"/>
<arg name="flags" type="u" direction="in"/>
</method>

View file

@ -514,8 +514,8 @@ typedef struct _NMDevicePrivate {
char *firmware_version;
bool firmware_missing : 1;
bool nm_plugin_missing : 1;
bool
hw_addr_perm_fake : 1; /* whether the permanent HW address could not be read and is a fake */
bool hw_addr_perm_fake
: 1; /* whether the permanent HW address could not be read and is a fake */
guint8 in_state_changed : 4;
@ -14938,7 +14938,7 @@ impl_device_get_applied_connection(NMDBusObject *obj,
/*****************************************************************************/
typedef struct {
gboolean managed_state;
NMDeviceManaged managed_state;
NMDeviceManagedFlags managed_flags;
} SetManagedData;
@ -14956,19 +14956,20 @@ typedef struct {
* Returns: %TRUE if the managed state was set successfully, %FALSE otherwise.
*/
static gboolean
set_managed(NMDevice *self, gboolean managed, NMDeviceManagedFlags flags, GError **error)
set_managed(NMDevice *self, NMDeviceManaged managed, NMDeviceManagedFlags flags, GError **error)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
gboolean managed_old;
NMTernary managed_to_disk_old;
gboolean managed_old, managed_new;
NMTernary managed_to_disk, managed_to_disk_old;
if (flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT) {
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));
if (!nm_config_set_device_managed(nm_manager_get_config(priv->manager),
self,
managed,
managed_to_disk,
flags & NM_DEVICE_MANAGED_FLAGS_BY_MAC,
error))
return FALSE;
@ -14976,7 +14977,8 @@ set_managed(NMDevice *self, gboolean managed, NMDeviceManagedFlags flags, GError
/* Update the unmanaged flags after the change on disk */
nm_device_set_unmanaged_by_user_conf(self);
if (!!nm_device_get_unmanaged_flags(self, NM_UNMANAGED_USER_CONF) != !managed) {
if (managed_to_disk != NM_TERNARY_DEFAULT
&& managed_to_disk != !nm_device_get_unmanaged_flags(self, NM_UNMANAGED_USER_CONF)) {
/* We failed to make the new state effective on disk. Maybe the new config
* collides with other config. Try to revert and return error. Otherwise,
* we would set the runtime state correctly, but get an unexpected state
@ -14997,11 +14999,18 @@ set_managed(NMDevice *self, gboolean managed, NMDeviceManagedFlags flags, GError
}
if (flags & NM_DEVICE_MANAGED_FLAGS_RUNTIME) {
g_object_get(self, NM_DEVICE_MANAGED, &managed_old, NULL);
g_object_set(self, NM_DEVICE_MANAGED, !!managed, NULL);
g_object_get(self, NM_DEVICE_MANAGED, &managed, NULL);
if (managed_old != managed)
_notify(self, PROP_MANAGED);
if (managed == NM_DEVICE_MANAGED_RESET) {
nm_device_set_unmanaged_by_flags(self,
NM_UNMANAGED_USER_EXPLICIT,
NM_UNMAN_FLAG_OP_FORGET,
NM_DEVICE_STATE_REASON_UNMANAGED_USER_EXPLICIT);
} else {
g_object_get(self, NM_DEVICE_MANAGED, &managed_old, NULL);
g_object_set(self, NM_DEVICE_MANAGED, !!managed, NULL);
g_object_get(self, NM_DEVICE_MANAGED, &managed_new, NULL);
if (managed_old != managed_new)
_notify(self, PROP_MANAGED);
}
}
return TRUE;
@ -15015,7 +15024,7 @@ set_managed_cb(NMDevice *self,
gpointer user_data)
{
SetManagedData *set_managed_data = user_data;
gboolean managed;
NMDeviceManaged managed;
NMDeviceManagedFlags flags;
GError *local = NULL;
@ -15060,15 +15069,17 @@ impl_device_set_managed(NMDBusObject *obj,
{
NMDevice *self = NM_DEVICE(obj);
gs_free_error GError *error = NULL;
gboolean managed;
guint32 managed_u;
NMDeviceManaged managed;
guint32 flags_u;
NMDeviceManagedFlags flags;
SetManagedData *set_managed_data;
g_variant_get(parameters, "(bu)", &managed, &flags_u);
g_variant_get(parameters, "(uu)", &managed_u, &flags_u);
flags = flags_u;
nm_assert(flags == flags_u);
managed = managed_u;
flags = flags_u;
nm_assert(managed == managed_u && flags == flags_u);
set_managed_data = g_slice_new(SetManagedData);
*set_managed_data = (SetManagedData) {
@ -20052,7 +20063,7 @@ static const NMDBusInterfaceInfoExtended interface_info_device = {
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED(
NM_DEFINE_GDBUS_METHOD_INFO_INIT("SetManaged",
.in_args = NM_DEFINE_GDBUS_ARG_INFOS(
NM_DEFINE_GDBUS_ARG_INFO("managed", "b"),
NM_DEFINE_GDBUS_ARG_INFO("managed", "u"),
NM_DEFINE_GDBUS_ARG_INFO("flags", "u"), ), ),
.handle = impl_device_set_managed, ),
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED(NM_DEFINE_GDBUS_METHOD_INFO_INIT("Disconnect", ),

View file

@ -2107,6 +2107,7 @@ global:
libnm_1_58_0 {
global:
nm_device_managed_flags_get_type;
nm_device_managed_get_type;
nm_device_set_managed_async;
nm_device_set_managed_finish;
nm_ip_config_get_clat_address;

View file

@ -1484,7 +1484,7 @@ nm_device_set_managed(NMDevice *device, gboolean managed)
**/
void
nm_device_set_managed_async(NMDevice *device,
gboolean managed,
NMDeviceManaged managed,
NMDeviceManagedFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@ -1502,7 +1502,7 @@ nm_device_set_managed_async(NMDevice *device,
_nm_object_get_path(device),
NM_DBUS_INTERFACE_DEVICE,
"SetManaged",
g_variant_new("(bu)", managed, flags),
g_variant_new("(uu)", managed, flags),
G_VARIANT_TYPE("()"),
G_DBUS_CALL_FLAGS_NONE,
NM_DBUS_DEFAULT_TIMEOUT_MSEC,

View file

@ -152,7 +152,7 @@ _NM_DEPRECATED_SYNC_METHOD
void nm_device_set_managed(NMDevice *device, gboolean managed);
NM_AVAILABLE_IN_1_58
void nm_device_set_managed_async(NMDevice *device,
gboolean managed,
NMDeviceManaged managed,
NMDeviceManagedFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,

View file

@ -1245,6 +1245,22 @@ typedef enum /*< flags >*/ {
NM_DEVICE_REAPPLY_FLAGS_PRESERVE_EXTERNAL_IP = 0x1,
} NMDeviceReapplyFlags;
/**
* NMDeviceManaged:
* @NM_DEVICE_MANAGED_NO: the device is not managed.
* @NM_DEVICE_MANAGED_YES: the device is managed.
* @NM_DEVICE_MANAGED_RESET: reset the device managed state to the default value.
*
* Values for the SetManaged() D-Bus call of a device and nm_device_set_managed_async().
*
* Since: 1.58
*/
typedef enum {
NM_DEVICE_MANAGED_NO = 0,
NM_DEVICE_MANAGED_YES = 1,
NM_DEVICE_MANAGED_RESET = 2,
} NMDeviceManaged;
/**
* NMDeviceManagedFlags:
* @NM_DEVICE_MANAGED_FLAGS_NONE: no flag set.