diff --git a/introspection/org.freedesktop.NetworkManager.Device.xml b/introspection/org.freedesktop.NetworkManager.Device.xml index e694fcda3c..ae626a8eb5 100644 --- a/introspection/org.freedesktop.NetworkManager.Device.xml +++ b/introspection/org.freedesktop.NetworkManager.Device.xml @@ -322,7 +322,7 @@ Reapply: @connection: The optional connection settings that will be reapplied on the device. If empty, the currently active settings-connection will be used. The connection cannot arbitrarily differ from the current applied-connection otherwise the call will fail. Only certain changes are supported, like adding or removing IP addresses. @version_id: If non-zero, the current version id of the applied-connection must match. The current version id can be retrieved via GetAppliedConnection. This optional argument allows to catch concurrent modifications between the GetAppliedConnection call and Reapply. - @flags: Flags which would modify the behavior of the Reapply call. There are no flags defined currently and the users should use the value of 0. + @flags: Flags which would modify the behavior of the Reapply call. Invalid flags are rejected. Attempts to update the configuration of a device without deactivating it. NetworkManager has the concept of connections, which are profiles that @@ -344,6 +344,9 @@ Reapply can make the applied-connection different from the settings-connection, just like updating the settings-connection can make them different. + + Since 1.42, 1.40.10, "preserve-external-ip" flag (0x1) is supported to not + remove externally added IP addresses and routes on the device during reapply. --> diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 922579b234..594274d691 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -12791,6 +12791,7 @@ reapply_connection(NMDevice *self, NMConnection *con_old, NMConnection *con_new) * the current settings connection * @version_id: either zero, or the current version id for the applied * connection. + * @reapply_flags: the #NMDeviceReapplyFlags. * @audit_args: on return, a string representing the changes * @error: the error if %FALSE is returned * @@ -12800,11 +12801,12 @@ reapply_connection(NMDevice *self, NMConnection *con_old, NMConnection *con_new) * Return: %FALSE if the new configuration can not be reapplied. */ static gboolean -check_and_reapply_connection(NMDevice *self, - NMConnection *connection, - guint64 version_id, - char **audit_args, - GError **error) +check_and_reapply_connection(NMDevice *self, + NMConnection *connection, + guint64 version_id, + NMDeviceReapplyFlags reapply_flags, + char **audit_args, + GError **error) { NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); @@ -12972,7 +12974,12 @@ check_and_reapply_connection(NMDevice *self, reactivate_proxy_config(self); - nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_REAPPLY, FALSE); + nm_device_l3cfg_commit( + self, + NM_FLAGS_HAS(reapply_flags, NM_DEVICE_REAPPLY_FLAGS_PRESERVE_EXTERNAL_IP) + ? NM_L3_CFG_COMMIT_TYPE_UPDATE + : NM_L3_CFG_COMMIT_TYPE_REAPPLY, + FALSE); } if (priv->state >= NM_DEVICE_STATE_IP_CHECK) @@ -12989,12 +12996,18 @@ nm_device_reapply(NMDevice *self, NMConnection *connection, GError **error) { g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); - return check_and_reapply_connection(self, connection, 0, NULL, error); + return check_and_reapply_connection(self, + connection, + 0, + NM_DEVICE_REAPPLY_FLAGS_NONE, + NULL, + error); } typedef struct { - NMConnection *connection; - guint64 version_id; + NMConnection *connection; + guint64 version_id; + NMDeviceReapplyFlags reapply_flags; } ReapplyData; static void @@ -13005,16 +13018,16 @@ reapply_cb(NMDevice *self, gpointer user_data) { ReapplyData *reapply_data = user_data; - guint64 version_id = 0; - gs_unref_object NMConnection *connection = NULL; - GError *local = NULL; - gs_free char *audit_args = NULL; + guint64 version_id; + gs_unref_object NMConnection *connection = NULL; + NMDeviceReapplyFlags reapply_flags; + GError *local = NULL; + gs_free char *audit_args = NULL; - if (reapply_data) { - connection = reapply_data->connection; - version_id = reapply_data->version_id; - g_slice_free(ReapplyData, reapply_data); - } + connection = reapply_data->connection; + version_id = reapply_data->version_id; + reapply_flags = reapply_data->reapply_flags; + nm_g_slice_free(reapply_data); if (error) { nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY, @@ -13034,6 +13047,7 @@ reapply_cb(NMDevice *self, connection ?: nm_device_get_settings_connection_get_connection(self), version_id, + reapply_flags, &audit_args, &local)) { nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY, @@ -13067,12 +13081,12 @@ impl_device_reapply(NMDBusObject *obj, ReapplyData *reapply_data; gs_unref_variant GVariant *settings = NULL; guint64 version_id; - guint32 flags; + guint32 reapply_flags_u; + NMDeviceReapplyFlags reapply_flags; - g_variant_get(parameters, "(@a{sa{sv}}tu)", &settings, &version_id, &flags); + g_variant_get(parameters, "(@a{sa{sv}}tu)", &settings, &version_id, &reapply_flags_u); - /* No flags supported as of now. */ - if (flags != 0) { + if (NM_FLAGS_ANY(reapply_flags_u, ~((guint32) NM_DEVICE_REAPPLY_FLAGS_PRESERVE_EXTERNAL_IP))) { error = g_error_new_literal(NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "Invalid flags specified"); nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY, @@ -13085,6 +13099,9 @@ impl_device_reapply(NMDBusObject *obj, return; } + reapply_flags = reapply_flags_u; + nm_assert(reapply_flags_u == reapply_flags); + if (priv->state < NM_DEVICE_STATE_PREPARE || priv->state > NM_DEVICE_STATE_ACTIVATED) { error = g_error_new_literal(NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE, @@ -13122,12 +13139,12 @@ impl_device_reapply(NMDBusObject *obj, nm_connection_clear_secrets(connection); } - if (connection || version_id) { - reapply_data = g_slice_new(ReapplyData); - reapply_data->connection = connection; - reapply_data->version_id = version_id; - } else - reapply_data = NULL; + reapply_data = g_slice_new(ReapplyData); + *reapply_data = (ReapplyData){ + .connection = connection, + .version_id = version_id, + .reapply_flags = reapply_flags, + }; nm_device_auth_request(self, invocation, diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver index 2478defa34..4aa5631166 100644 --- a/src/libnm-client-impl/libnm.ver +++ b/src/libnm-client-impl/libnm.ver @@ -1878,3 +1878,7 @@ global: nm_utils_ip_routes_to_variant; nm_vpn_plugin_info_supports_multiple; } libnm_1_40_0; + +libnm_1_40_10 { + nm_device_reapply_flags_get_type; +} libnm_1_40_4; diff --git a/src/libnm-client-impl/nm-device.c b/src/libnm-client-impl/nm-device.c index 238e7c1709..0e971d39b5 100644 --- a/src/libnm-client-impl/nm-device.c +++ b/src/libnm-client-impl/nm-device.c @@ -2496,7 +2496,7 @@ nm_device_reapply_finish(NMDevice *device, GAsyncResult *result, GError **error) /** * nm_device_get_applied_connection: * @device: a #NMDevice - * @flags: the flags argument. Currently, this value must always be zero. + * @flags: the flags argument. See #NMDeviceReapplyFlags. * @version_id: (out) (allow-none): returns the current version id of * the applied connection * @cancellable: a #GCancellable, or %NULL @@ -2559,7 +2559,7 @@ nm_device_get_applied_connection(NMDevice *device, /** * nm_device_get_applied_connection_async: * @device: a #NMDevice - * @flags: the flags argument. Currently, this value must always be zero. + * @flags: the flags argument. See #NMDeviceReapplyFlags. * @cancellable: a #GCancellable, or %NULL * @callback: callback to be called when the reapply operation completes * @user_data: caller-specific data passed to @callback diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h index 6e1a84a1dd..064fb0f435 100644 --- a/src/libnm-core-public/nm-dbus-interface.h +++ b/src/libnm-core-public/nm-dbus-interface.h @@ -1144,6 +1144,22 @@ typedef enum /*< flags >*/ { NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY = 0x40, } NMSettingsUpdate2Flags; +/** + * NMDeviceReapplyFlags: + * @NM_DEVICE_REAPPLY_FLAGS_NONE: no flag set. + * @NM_DEVICE_REAPPLY_FLAGS_PRESERVE_EXTERNAL_IP: during reapply, + * preserve external IP addresses and routes. + * + * Flags for the Reapply() D-Bus call of a device and + * nm_device_reapply_async(). + * + * Since: 1.42, 1.40.10 + */ +typedef enum /*< flags >*/ { + NM_DEVICE_REAPPLY_FLAGS_NONE = 0, + NM_DEVICE_REAPPLY_FLAGS_PRESERVE_EXTERNAL_IP = 0x1, +} NMDeviceReapplyFlags; + /** * NMTernary: * @NM_TERNARY_DEFAULT: use the globally-configured default value.