You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
NetworkManager/SOURCES/1002-allow-rollback-on-inte...

236 lines
10 KiB

From ba47f23b08bb59ec2daf6bce73a94182d8028c82 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
Date: Wed, 13 Mar 2024 20:52:37 +0800
Subject: [PATCH] checkpoint: Allow rollback on internal global DNS
With `NM_CHECKPOINT_CREATE_FLAG_TRACK_INTERNAL_GLOBAL_DNS` flag set on
checkpoint creation, the checkpoint rollback will restore the
global DNS in internal configure file
`/var/lib/NetworkManager/NetworkManager-intern.conf`.
If user has set global DNS in /etc folder, this flag will not take any
effect.
Resolves: https://issues.redhat.com/browse/RHEL-23446
Signed-off-by: Gris Ge <fge@redhat.com>
(cherry picked from commit 86d67da28dd047a08a01687d8154b377d1c25b4c)
(cherry picked from commit 69d5761fa87bb85df037ad9044c03dd1922d3ee4)
---
src/core/nm-checkpoint.c | 28 ++++++++++++++
src/core/nm-config-data.c | 47 +++++++++++++++++++++++
src/core/nm-config-data.h | 3 +-
src/core/nm-manager.c | 11 +++++-
src/core/nm-manager.h | 3 ++
src/libnm-core-public/nm-dbus-interface.h | 6 +++
6 files changed, 96 insertions(+), 2 deletions(-)
diff --git a/src/core/nm-checkpoint.c b/src/core/nm-checkpoint.c
index 74adf48477..cc5c189bf9 100644
--- a/src/core/nm-checkpoint.c
+++ b/src/core/nm-checkpoint.c
@@ -13,6 +13,7 @@
#include "nm-core-utils.h"
#include "nm-dbus-interface.h"
#include "devices/nm-device.h"
+#include "nm-config.h"
#include "nm-manager.h"
#include "settings/nm-settings.h"
#include "settings/nm-settings-connection.h"
@@ -55,6 +56,8 @@ struct _NMCheckpointPrivate {
NMCheckpointTimeoutCallback timeout_cb;
gpointer timeout_data;
+
+ NMGlobalDnsConfig *global_dns_config;
};
struct _NMCheckpointClass {
@@ -491,6 +494,17 @@ next_dev:
}
}
}
+ if (NM_FLAGS_HAS(priv->flags, NM_CHECKPOINT_CREATE_FLAG_TRACK_INTERNAL_GLOBAL_DNS)
+ && priv->global_dns_config) {
+ gs_free_error GError *error = NULL;
+ NMConfig *config;
+
+ config = nm_manager_get_config(priv->manager);
+ nm_assert(config);
+ if (!nm_config_set_global_dns(config, priv->global_dns_config, &error)) {
+ _LOGE("set global DNS failed with error: %s", error->message);
+ }
+ }
return g_variant_new("(a{su})", &builder);
}
@@ -742,6 +756,19 @@ nm_checkpoint_new(NMManager *manager,
NM_MANAGER_DEVICE_REMOVED,
G_CALLBACK(_device_removed),
self);
+ if (NM_FLAGS_HAS(flags, NM_CHECKPOINT_CREATE_FLAG_TRACK_INTERNAL_GLOBAL_DNS)) {
+ NMConfigData *config_data;
+ NMGlobalDnsConfig *dns_config = NULL;
+
+ config_data = nm_config_get_data(nm_manager_get_config(manager));
+ if (config_data) {
+ dns_config = nm_config_data_get_global_dns_config(config_data);
+ if (!dns_config || nm_global_dns_config_is_internal(dns_config)) {
+ priv->global_dns_config = nm_global_dns_config_clone(dns_config);
+ }
+ }
+ }
+
return self;
}
@@ -756,6 +783,7 @@ dispose(GObject *object)
nm_clear_pointer(&priv->devices, g_hash_table_unref);
nm_clear_pointer(&priv->connection_uuids, g_hash_table_unref);
nm_clear_pointer(&priv->removed_devices, g_ptr_array_unref);
+ nm_global_dns_config_free(priv->global_dns_config);
nm_clear_g_signal_handler(priv->manager, &priv->dev_removed_id);
g_clear_object(&priv->manager);
diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c
index 468e56b821..d4498edd88 100644
--- a/src/core/nm-config-data.c
+++ b/src/core/nm-config-data.c
@@ -2436,3 +2436,50 @@ nm_config_data_class_init(NMConfigDataClass *config_class)
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
}
+
+static NMGlobalDnsDomain *
+nm_global_dns_domain_clone(NMGlobalDnsDomain *old_domain)
+{
+ if (old_domain) {
+ NMGlobalDnsDomain *new_domain = g_malloc0(sizeof(NMGlobalDnsDomain));
+ new_domain->name = g_strdup(old_domain->name);
+ new_domain->servers = (char **) nm_strv_dup(old_domain->servers, -1, TRUE);
+ new_domain->options = (char **) nm_strv_dup(old_domain->options, -1, TRUE);
+ return new_domain;
+ } else {
+ return NULL;
+ }
+}
+
+NMGlobalDnsConfig *
+nm_global_dns_config_clone(NMGlobalDnsConfig *old_dns_config)
+{
+ NMGlobalDnsConfig *new_dns_config;
+ gpointer key, value;
+ NMGlobalDnsDomain *old_domain;
+ GHashTableIter iter;
+
+ new_dns_config = g_malloc0(sizeof(NMGlobalDnsConfig));
+ new_dns_config->internal = TRUE;
+
+ if (old_dns_config) {
+ new_dns_config->internal = old_dns_config->internal;
+ new_dns_config->searches = nm_strv_dup(old_dns_config->searches, -1, TRUE);
+ new_dns_config->options = nm_strv_dup(old_dns_config->options, -1, TRUE);
+ new_dns_config->domains = g_hash_table_new_full(nm_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) global_dns_domain_free);
+ if (old_dns_config->domains) {
+ g_hash_table_iter_init(&iter, old_dns_config->domains);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ old_domain = value;
+ g_hash_table_insert(new_dns_config->domains,
+ g_strdup(key),
+ nm_global_dns_domain_clone(old_domain));
+ }
+ }
+ global_dns_config_seal_domains(new_dns_config);
+ }
+ return new_dns_config;
+}
diff --git a/src/core/nm-config-data.h b/src/core/nm-config-data.h
index 9e7a50fc24..0344ce9055 100644
--- a/src/core/nm-config-data.h
+++ b/src/core/nm-config-data.h
@@ -280,7 +280,8 @@ int nm_global_dns_config_cmp(const NMGlobalDnsConfig *a,
const NMGlobalDnsConfig *b,
gboolean check_internal);
void nm_global_dns_config_update_checksum(const NMGlobalDnsConfig *dns_config, GChecksum *sum);
-void nm_global_dns_config_free(NMGlobalDnsConfig *dns_config);
+NMGlobalDnsConfig *nm_global_dns_config_clone(NMGlobalDnsConfig *dns_config);
+void nm_global_dns_config_free(NMGlobalDnsConfig *dns_config);
NMGlobalDnsConfig *nm_global_dns_config_from_dbus(const GValue *value, GError **error);
void nm_global_dns_config_to_dbus(const NMGlobalDnsConfig *dns_config, GValue *value);
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index 730ba4763b..6739e5599e 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -8458,7 +8458,8 @@ impl_manager_checkpoint_create(NMDBusObject *obj,
| NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS
| NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES
| NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING
- | NM_CHECKPOINT_CREATE_FLAG_NO_PRESERVE_EXTERNAL_PORTS)))) {
+ | NM_CHECKPOINT_CREATE_FLAG_NO_PRESERVE_EXTERNAL_PORTS
+ | NM_CHECKPOINT_CREATE_FLAG_TRACK_INTERNAL_GLOBAL_DNS)))) {
g_dbus_method_invocation_return_error_literal(invocation,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_INVALID_ARGUMENTS,
@@ -9765,3 +9766,11 @@ nm_manager_class_init(NMManagerClass *manager_class)
1,
NM_TYPE_DEVICE);
}
+
+NMConfig *
+nm_manager_get_config(NMManager *self)
+{
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
+
+ return priv->config;
+}
diff --git a/src/core/nm-manager.h b/src/core/nm-manager.h
index 3028eb7ebe..3c5213c4f2 100644
--- a/src/core/nm-manager.h
+++ b/src/core/nm-manager.h
@@ -10,6 +10,7 @@
#include "settings/nm-settings-connection.h"
#include "c-list/src/c-list.h"
#include "nm-dbus-manager.h"
+#include "nm-config-data.h"
#define NM_TYPE_MANAGER (nm_manager_get_type())
#define NM_MANAGER(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_MANAGER, NMManager))
@@ -266,4 +267,6 @@ gboolean nm_manager_devcon_autoconnect_blocked_reason_set(NMManager *
NMSettingsAutoconnectBlockedReason value,
gboolean set);
+NMConfig *nm_manager_get_config(NMManager *self);
+
#endif /* __NETWORKMANAGER_MANAGER_H__ */
diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h
index 66cd590d6c..ab94244c21 100644
--- a/src/libnm-core-public/nm-dbus-interface.h
+++ b/src/libnm-core-public/nm-dbus-interface.h
@@ -991,6 +991,11 @@ typedef enum {
* With this flag, the rollback detaches all external ports.
* This only has an effect for bridge ports. Before 1.38, this was the default
* behavior. Since: 1.38.
+ * @NM_CHECKPOINT_CREATE_FLAG_TRACK_INTERNAL_GLOBAL_DNS: during rollback,
+ * by default changes to global DNS via D-BUS interface are preserved.
+ * With this flag, the rollback reverts the global DNS changes made via D-Bus
+ * interface. Global DNS defined in [global-dns] section of
+ * NetworkManager.conf is not impacted by this flag. Since: 1.48.
*
* The flags for CheckpointCreate call
*
@@ -1003,6 +1008,7 @@ typedef enum /*< flags >*/ {
NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES = 0x04,
NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING = 0x08,
NM_CHECKPOINT_CREATE_FLAG_NO_PRESERVE_EXTERNAL_PORTS = 0x10,
+ NM_CHECKPOINT_CREATE_FLAG_TRACK_INTERNAL_GLOBAL_DNS = 0x20,
} NMCheckpointCreateFlags;
/**
--
2.44.0