parent
7383cd1c4c
commit
c2a779fbed
@ -1 +1 @@
|
||||
3c11d700a2e81a7abce285ab94d015ac966f59d3 SOURCES/NetworkManager-1.46.0.tar.xz
|
||||
6423adef5f4bb2c0cc20c2173e03a7ac8b8565ca SOURCES/NetworkManager-1.48.10.tar.xz
|
||||
|
@ -1 +1 @@
|
||||
SOURCES/NetworkManager-1.46.0.tar.xz
|
||||
SOURCES/NetworkManager-1.48.10.tar.xz
|
||||
|
@ -1,25 +0,0 @@
|
||||
From 6e84d852487f070ab3f61c24d78fc05338f171f6 Mon Sep 17 00:00:00 2001
|
||||
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
Date: Wed, 20 Mar 2024 19:10:45 +0100
|
||||
Subject: [PATCH] cloud: drop PrivateUsers directive from nm-cloud-setup
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-27503
|
||||
---
|
||||
src/nm-cloud-setup/nm-cloud-setup.service.in | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/src/nm-cloud-setup/nm-cloud-setup.service.in b/src/nm-cloud-setup/nm-cloud-setup.service.in
|
||||
index e73654d892..4aa6017e48 100644
|
||||
--- a/src/nm-cloud-setup/nm-cloud-setup.service.in
|
||||
+++ b/src/nm-cloud-setup/nm-cloud-setup.service.in
|
||||
@@ -28,7 +28,6 @@ MemoryDenyWriteExecute=yes
|
||||
NoNewPrivileges=yes
|
||||
PrivateDevices=yes
|
||||
PrivateTmp=yes
|
||||
-PrivateUsers=yes
|
||||
ProtectClock=yes
|
||||
ProtectControlGroups=yes
|
||||
ProtectHome=yes
|
||||
--
|
||||
2.44.0
|
||||
|
@ -1,235 +0,0 @@
|
||||
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
|
||||
|
@ -1,127 +0,0 @@
|
||||
From cf230074965216c94bb25bc3c3fff7f1d698c250 Mon Sep 17 00:00:00 2001
|
||||
From: Gris Ge <fge@redhat.com>
|
||||
Date: Fri, 15 Mar 2024 15:46:02 +0800
|
||||
Subject: [PATCH] ovs: Do not allow OVS bridge and port to be parent
|
||||
|
||||
When creating VLAN over OVS internal interface which holding the same
|
||||
name as its controller OVS bridge, NetworkManager will fail with error:
|
||||
|
||||
Error: Connection activation failed: br0.101 failed to create
|
||||
resources: cannot retrieve ifindex of interface br0 (Open vSwitch
|
||||
Bridge)
|
||||
|
||||
Expanded the `find_device_by_iface()` with additional argument
|
||||
`child: NmConnection *` which will validate whether candidate is
|
||||
suitable to be parent device.
|
||||
|
||||
In `nm_device_check_parent_connection_compatible()`, we only not allow OVS
|
||||
bridge and OVS port being parent.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-26753
|
||||
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
(cherry picked from commit 7096f52a5967ef053a4cf8e5ca8a71c1495578f9)
|
||||
(cherry picked from commit d3329f0599f5fdfc2ef9f2c1395b5eb7bcc3c2a5)
|
||||
---
|
||||
src/core/devices/nm-device.c | 11 +++++++++++
|
||||
src/core/devices/nm-device.h | 1 +
|
||||
src/core/nm-manager.c | 14 +++++++++-----
|
||||
3 files changed, 21 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
|
||||
index 30c38ba990..78b0e618be 100644
|
||||
--- a/src/core/devices/nm-device.c
|
||||
+++ b/src/core/devices/nm-device.c
|
||||
@@ -9508,6 +9508,17 @@ nm_device_check_slave_connection_compatible(NMDevice *self, NMConnection *slave)
|
||||
return nm_streq(connection_type, slave_type);
|
||||
}
|
||||
|
||||
+gboolean
|
||||
+nm_device_can_be_parent(NMDevice *self)
|
||||
+{
|
||||
+ NMDeviceType device_type = nm_device_get_device_type(self);
|
||||
+
|
||||
+ if ((device_type == NM_DEVICE_TYPE_OVS_BRIDGE) || (device_type == NM_DEVICE_TYPE_OVS_PORT))
|
||||
+ return FALSE;
|
||||
+ else
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* nm_device_can_assume_connections:
|
||||
* @self: #NMDevice instance
|
||||
diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h
|
||||
index b096d23ac1..7353a3f327 100644
|
||||
--- a/src/core/devices/nm-device.h
|
||||
+++ b/src/core/devices/nm-device.h
|
||||
@@ -550,6 +550,7 @@ gboolean nm_device_check_connection_compatible(NMDevice *device,
|
||||
GError **error);
|
||||
|
||||
gboolean nm_device_check_slave_connection_compatible(NMDevice *device, NMConnection *connection);
|
||||
+gboolean nm_device_can_be_parent(NMDevice *device);
|
||||
|
||||
gboolean nm_device_can_assume_connections(NMDevice *self);
|
||||
gboolean nm_device_unmanage_on_quit(NMDevice *self);
|
||||
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
|
||||
index 6739e5599e..7f94f7cd9c 100644
|
||||
--- a/src/core/nm-manager.c
|
||||
+++ b/src/core/nm-manager.c
|
||||
@@ -1914,7 +1914,8 @@ find_device_by_ip_iface(NMManager *self, const char *iface)
|
||||
* is given, this function will only return master devices and will ensure
|
||||
* @slave, when activated, can be a slave of the returned master device. If
|
||||
* @connection is given, this function will only consider devices that are
|
||||
- * compatible with @connection.
|
||||
+ * compatible with @connection. If @child is given, this function will only
|
||||
+ * return parent device.
|
||||
*
|
||||
* Returns: the matching #NMDevice
|
||||
*/
|
||||
@@ -1922,7 +1923,8 @@ static NMDevice *
|
||||
find_device_by_iface(NMManager *self,
|
||||
const char *iface,
|
||||
NMConnection *connection,
|
||||
- NMConnection *slave)
|
||||
+ NMConnection *slave,
|
||||
+ NMConnection *child)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
|
||||
NMDevice *fallback = NULL;
|
||||
@@ -1941,6 +1943,8 @@ find_device_by_iface(NMManager *self,
|
||||
if (!nm_device_check_slave_connection_compatible(candidate, slave))
|
||||
continue;
|
||||
}
|
||||
+ if (child && !nm_device_can_be_parent(candidate))
|
||||
+ continue;
|
||||
|
||||
if (nm_device_is_real(candidate))
|
||||
return candidate;
|
||||
@@ -2405,7 +2409,7 @@ find_parent_device_for_connection(NMManager *self,
|
||||
NM_SET_OUT(out_parent_spec, parent_name);
|
||||
|
||||
/* Try as an interface name of a parent device */
|
||||
- parent = find_device_by_iface(self, parent_name, NULL, NULL);
|
||||
+ parent = find_device_by_iface(self, parent_name, NULL, NULL, connection);
|
||||
if (parent)
|
||||
return parent;
|
||||
|
||||
@@ -5003,7 +5007,7 @@ find_master(NMManager *self,
|
||||
}
|
||||
|
||||
if (!master_connection) {
|
||||
- master_device = find_device_by_iface(self, master, NULL, connection);
|
||||
+ master_device = find_device_by_iface(self, master, NULL, connection, NULL);
|
||||
if (!master_device) {
|
||||
g_set_error(error,
|
||||
NM_MANAGER_ERROR,
|
||||
@@ -6445,7 +6449,7 @@ validate_activation_request(NMManager *self,
|
||||
if (!iface)
|
||||
return NULL;
|
||||
|
||||
- device = find_device_by_iface(self, iface, connection, NULL);
|
||||
+ device = find_device_by_iface(self, iface, connection, NULL, NULL);
|
||||
if (!device) {
|
||||
g_set_error_literal(error,
|
||||
NM_MANAGER_ERROR,
|
||||
--
|
||||
2.44.0
|
||||
|
@ -1,50 +0,0 @@
|
||||
From e4fb80046cf36a7e210e8660ef50c93ef8971a5e Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Wed, 13 Mar 2024 10:47:31 +0100
|
||||
Subject: [PATCH 1/2] nm-dispatcher: fix crash when parsing output dictionary
|
||||
|
||||
'stdout' is NULL when the script didn't write anything or failed.
|
||||
|
||||
Fixes the following crash detected by NMCI in test
|
||||
'dispatcher_device_handler_dummy'.
|
||||
|
||||
nm-dispatcher[936339]: g_strsplit: assertion 'string != NULL' failed
|
||||
|
||||
build_result_options (nm-dispatcher)
|
||||
complete_request (nm-dispatcher)
|
||||
complete_script (nm-dispatcher)
|
||||
script_watch_cb (nm-dispatcher)
|
||||
g_child_watch_dispatch (libglib-2.0.so.0)
|
||||
g_main_dispatch (libglib-2.0.so.0)
|
||||
g_main_context_iterate (libglib-2.0.so.0)
|
||||
g_main_context_iteration (libglib-2.0.so.0)
|
||||
main (nm-dispatcher)
|
||||
__libc_start_main (libc.so.6)
|
||||
_start (nm-dispatcher)
|
||||
|
||||
Fixes: d72f26b87528 ('dispatcher: read device-handler's stdout into a dictionary')
|
||||
|
||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1889
|
||||
(cherry picked from commit e5c2c5f1c2f55c139f39830651df2c901c3a0bf9)
|
||||
(cherry picked from commit 669bf33de38a8a15e77662daadf94d6395838eee)
|
||||
---
|
||||
src/nm-dispatcher/nm-dispatcher.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/nm-dispatcher/nm-dispatcher.c b/src/nm-dispatcher/nm-dispatcher.c
|
||||
index efb4ec0087..ce252b92bf 100644
|
||||
--- a/src/nm-dispatcher/nm-dispatcher.c
|
||||
+++ b/src/nm-dispatcher/nm-dispatcher.c
|
||||
@@ -306,6 +306,9 @@ build_result_options(char *stdout)
|
||||
char *key;
|
||||
char *value;
|
||||
|
||||
+ if (!stdout)
|
||||
+ return NULL;
|
||||
+
|
||||
lines = g_strsplit(stdout, "\n", 65);
|
||||
|
||||
for (i = 0; lines[i] && i < 64; i++) {
|
||||
--
|
||||
2.41.0
|
||||
|
@ -1,66 +0,0 @@
|
||||
From 8ff08068342d1d8efe1e6d6c9a241e3395641a76 Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Thu, 21 Mar 2024 09:45:15 +0100
|
||||
Subject: [PATCH 2/2] manager: fix race condition while enumerating devices at
|
||||
startup
|
||||
|
||||
While enumerating devices at startup, we take a snapshot of existing
|
||||
links from platform and we start creating device instances for
|
||||
them. It's possible that in the meantime, while processing netlink
|
||||
events in platform_link_added(), a link gets renamed. If that happens,
|
||||
then we have two different views of the same ifindex: the cached link
|
||||
from `links` and the link in platform.
|
||||
|
||||
This can cause issues: in platform_link_added() we create the device
|
||||
with the cached name; then in NMDevice's constructor(), we look up
|
||||
from platform the ifindex for the given name. Because of the rename,
|
||||
this lookup can match a newly created, different link.
|
||||
|
||||
The end result is that the ifindex from the initial snapshot doesn't
|
||||
get a NMDevice and is not handled by NetworkManager.
|
||||
|
||||
Fix this problem by fetching the latest version of the link from
|
||||
platform to make sure we have a consistent view of the state.
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-25808
|
||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1897
|
||||
(cherry picked from commit de130df3e2207dc015c4fa82ecf766be2851532c)
|
||||
(cherry picked from commit 6f3739e76f1f31d71bc3fbd7a4b0955071d59cc4)
|
||||
---
|
||||
src/core/nm-manager.c | 17 ++++++++++++++++-
|
||||
1 file changed, 16 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
|
||||
index 7f94f7cd9c..a77ba9d3b1 100644
|
||||
--- a/src/core/nm-manager.c
|
||||
+++ b/src/core/nm-manager.c
|
||||
@@ -4438,10 +4438,25 @@ platform_query_devices(NMManager *self)
|
||||
links = nm_platform_link_get_all(priv->platform);
|
||||
if (!links)
|
||||
return;
|
||||
+
|
||||
for (i = 0; i < links->len; i++) {
|
||||
- const NMPlatformLink *link = NMP_OBJECT_CAST_LINK(links->pdata[i]);
|
||||
+ const NMPlatformLink *elem = NMP_OBJECT_CAST_LINK(links->pdata[i]);
|
||||
+ const NMPlatformLink *link;
|
||||
const NMConfigDeviceStateData *dev_state;
|
||||
|
||||
+ /*
|
||||
+ * @links is an immutable snapshot of the platform links captured before
|
||||
+ * the loop was started. It's possible that in the meantime, while
|
||||
+ * processing netlink events in platform_link_added(), a link was
|
||||
+ * renamed. If that happens, we have 2 different views of the same
|
||||
+ * ifindex: the one from @links and the one from platform. This can
|
||||
+ * cause race conditions; make sure to use the latest known version of
|
||||
+ * the link.
|
||||
+ */
|
||||
+ link = nm_platform_link_get(priv->platform, elem->ifindex);
|
||||
+ if (!link)
|
||||
+ continue;
|
||||
+
|
||||
dev_state = nm_config_device_state_get(priv->config, link->ifindex);
|
||||
platform_link_added(self,
|
||||
link->ifindex,
|
||||
--
|
||||
2.41.0
|
||||
|
@ -1,40 +0,0 @@
|
||||
From 6394c2b262d86824a41ca82ad76288c06bfd1989 Mon Sep 17 00:00:00 2001
|
||||
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
Date: Tue, 26 Mar 2024 12:53:27 +0100
|
||||
Subject: [PATCH] libnm-lldp: use ETH_P_ALL instead of NM_ETHERTYPE_LLDP for
|
||||
the socket
|
||||
|
||||
When creating the socket for listening to LLDP frames we are setting
|
||||
NM_ETHERTYPE_LLDP (0x88cc) as protocol. In most of the cases, that is
|
||||
correct but when the interface is attached as a port to a OVS bridge,
|
||||
kernel is not matching the protocol correctly. The reason might be that
|
||||
some metadata is added to the packet, but we are not completely sure
|
||||
about it.
|
||||
|
||||
Instead, we should use ETH_P_ALL to match all the protocols. Later, we
|
||||
have a eBPF filter to drop the packet by multicast MAC address or
|
||||
protocol. This is how lldpd is doing it for example.
|
||||
|
||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1903
|
||||
(cherry picked from commit 9ac1d6e22bfac7f576dec034a26ac7c9012e5b80)
|
||||
(cherry picked from commit 2fac176986f3afaa84242e069613cc543bfcc58c)
|
||||
---
|
||||
src/libnm-lldp/nm-lldp-network.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/libnm-lldp/nm-lldp-network.c b/src/libnm-lldp/nm-lldp-network.c
|
||||
index 811c3a7291..28cc745249 100644
|
||||
--- a/src/libnm-lldp/nm-lldp-network.c
|
||||
+++ b/src/libnm-lldp/nm-lldp-network.c
|
||||
@@ -46,7 +46,7 @@ nm_lldp_network_bind_raw_socket(int ifindex)
|
||||
|
||||
assert(ifindex > 0);
|
||||
|
||||
- fd = socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, htobe16(NM_ETHERTYPE_LLDP));
|
||||
+ fd = socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, htobe16(ETH_P_ALL));
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
--
|
||||
2.44.0
|
||||
|
@ -1,210 +0,0 @@
|
||||
From ed5cbbc5847527ed0cfc33f521f7c724975c846b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
|
||||
Date: Tue, 30 Apr 2024 12:45:04 +0200
|
||||
Subject: [PATCH] platform: avoid routes resync for routes that we don't track
|
||||
|
||||
When we recibe a Netlink message with a "route change" event, normally
|
||||
we just ignore it if it's a route that we don't track (i.e. because of
|
||||
the route protocol).
|
||||
|
||||
However, it's not that easy if it has the NLM_F_REPLACE flag because
|
||||
that means that it might be replacing another route. If the kernel has
|
||||
similar routes which are candidates for the replacement, it's hard for
|
||||
NM to guess which one of those is being replaced (as the kernel doesn't
|
||||
have a "route ID" or similar field to indicate it). Moreover, the kernel
|
||||
might choose to replace a route that we don't have on cache, so we know
|
||||
nothing about it.
|
||||
|
||||
It is important to note that we cannot just discard Netlink messages of
|
||||
routes that we don't track if they has the NLM_F_REPLACE. For example,
|
||||
if we are tracking a route with proto=static, we might receive a replace
|
||||
message, changing that route to proto=other_proto_that_we_dont_track. We
|
||||
need to process that message and remove the route from our cache.
|
||||
|
||||
As NM doesn't know what route is being replaced, trying to guess will
|
||||
lead to errors that will leave the cache in an inconsistent state.
|
||||
Because of that, it just do a cache resync for the routes.
|
||||
|
||||
For IPv4 there was an optimization to this: if we don't have in the
|
||||
cache any route candidate for the replacement there are only 2 possible
|
||||
options: either add the new route to the cache or discard it if we are
|
||||
not interested on it. We don't need a resync for that.
|
||||
|
||||
This commit is extending that optimization to IPv6 routes. There is no
|
||||
reason why it shouldn't work in the same way than with IPv4. This
|
||||
optimization will only work well as long as we find potential candidate
|
||||
routes in the same way than the kernel (comparing the same fields). NM
|
||||
calls to this "comparing by WEAK_ID". But this can also happen with IPv4
|
||||
routes.
|
||||
|
||||
It is worth it to enable this optimization because there are routing
|
||||
daemons using custom routing protocols that makes tens or hundreds of
|
||||
updates per second. If they use NLM_F_REPLACE, this caused NM to do a
|
||||
resync hundreds of times per second leading to a 100% CPU usage:
|
||||
https://issues.redhat.com/browse/RHEL-26195
|
||||
|
||||
An additional but smaller optimization is done in this commit: if we
|
||||
receive a route message for routes that we don't track AND doesn't have
|
||||
the NLM_F_REPLACE flag, we can ignore the entire message, thus avoiding
|
||||
the memory allocation of the nmp_object. That nmp_object was going to be
|
||||
ignored later, anyway, so better to avoid these allocations that, with
|
||||
the routing daemon of the above's example, can happen hundreds of times
|
||||
per second.
|
||||
|
||||
With this changes, the CPU usage doing `ip route replace` 300 times/s
|
||||
drops from 100% to 1%. Doing `ip route replace` as fast as possible,
|
||||
without any rate limitting, still keeps NM with a 3% CPU usage in the
|
||||
system that I have used to test.
|
||||
|
||||
(cherry picked from commit 4d426f581de402e0aebd2ab273ff6649a0a6fee6)
|
||||
(cherry picked from commit 15ffa8ec6ff7bf43ed1eb123c0d419d6fab8b268)
|
||||
---
|
||||
src/libnm-platform/nm-linux-platform.c | 69 ++++++++++++++++----------
|
||||
src/libnm-platform/nmp-object.c | 22 +++++---
|
||||
2 files changed, 57 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c
|
||||
index 9ecac2d9b3..5b595a9b71 100644
|
||||
--- a/src/libnm-platform/nm-linux-platform.c
|
||||
+++ b/src/libnm-platform/nm-linux-platform.c
|
||||
@@ -3903,6 +3903,34 @@ _new_from_nl_addr(const struct nlmsghdr *nlh, gboolean id_only)
|
||||
return g_steal_pointer(&obj);
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+ip_route_is_tracked(guint8 proto, guint8 type)
|
||||
+{
|
||||
+ if (proto > RTPROT_STATIC && !NM_IN_SET(proto, RTPROT_DHCP, RTPROT_RA)) {
|
||||
+ /* We ignore certain rtm_protocol, because NetworkManager would only ever
|
||||
+ * configure certain protocols. Other routes are not configured by NetworkManager
|
||||
+ * and we don't track them in the platform cache.
|
||||
+ *
|
||||
+ * This is to help with the performance overhead of a huge number of
|
||||
+ * routes, for example with the bird BGP software, that adds routes
|
||||
+ * with RTPROT_BIRD protocol. */
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (!NM_IN_SET(type,
|
||||
+ RTN_UNICAST,
|
||||
+ RTN_LOCAL,
|
||||
+ RTN_BLACKHOLE,
|
||||
+ RTN_UNREACHABLE,
|
||||
+ RTN_PROHIBIT,
|
||||
+ RTN_THROW)) {
|
||||
+ /* Certain route types are ignored and not placed into the cache. */
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
/* Copied and heavily modified from libnl3's rtnl_route_parse() and parse_multipath(). */
|
||||
static NMPObject *
|
||||
_new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter *parse_nlmsg_iter)
|
||||
@@ -3963,6 +3991,16 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter
|
||||
* only handle ~supported~ routes.
|
||||
*****************************************************************/
|
||||
|
||||
+ /* If it's a route that we don't need to track, abort here to avoid unnecessary
|
||||
+ * memory allocations to create the nmp_object. However, if the message has the
|
||||
+ * NLM_F_REPLACE flag, it might be replacing a route that we were tracking so we
|
||||
+ * have to stop tracking it. That means that we have to process all messages with
|
||||
+ * NLM_F_REPLACE. See nmp_cache_update_netlink_route().
|
||||
+ */
|
||||
+ if (!ip_route_is_tracked(rtm->rtm_protocol, rtm->rtm_type)
|
||||
+ && !(nlh->nlmsg_flags & NLM_F_REPLACE))
|
||||
+ return NULL;
|
||||
+
|
||||
addr_family = rtm->rtm_family;
|
||||
|
||||
if (addr_family == AF_INET)
|
||||
@@ -5519,39 +5557,18 @@ ip_route_get_lock_flag(const NMPlatformIPRoute *route)
|
||||
static gboolean
|
||||
ip_route_is_alive(const NMPlatformIPRoute *route)
|
||||
{
|
||||
- guint8 prot;
|
||||
+ guint8 proto, type;
|
||||
|
||||
nm_assert(route);
|
||||
nm_assert(route->rt_source >= NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC
|
||||
&& route->rt_source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST);
|
||||
|
||||
- prot = route->rt_source - 1;
|
||||
-
|
||||
- nm_assert(nmp_utils_ip_config_source_from_rtprot(prot) == route->rt_source);
|
||||
-
|
||||
- if (prot > RTPROT_STATIC && !NM_IN_SET(prot, RTPROT_DHCP, RTPROT_RA)) {
|
||||
- /* We ignore certain rtm_protocol, because NetworkManager would only ever
|
||||
- * configure certain protocols. Other routes are not configured by NetworkManager
|
||||
- * and we don't track them in the platform cache.
|
||||
- *
|
||||
- * This is to help with the performance overhead of a huge number of
|
||||
- * routes, for example with the bird BGP software, that adds routes
|
||||
- * with RTPROT_BIRD protocol. */
|
||||
- return FALSE;
|
||||
- }
|
||||
+ proto = route->rt_source - 1;
|
||||
+ type = nm_platform_route_type_uncoerce(route->type_coerced);
|
||||
|
||||
- if (!NM_IN_SET(nm_platform_route_type_uncoerce(route->type_coerced),
|
||||
- RTN_UNICAST,
|
||||
- RTN_LOCAL,
|
||||
- RTN_BLACKHOLE,
|
||||
- RTN_UNREACHABLE,
|
||||
- RTN_PROHIBIT,
|
||||
- RTN_THROW)) {
|
||||
- /* Certain route types are ignored and not placed into the cache. */
|
||||
- return FALSE;
|
||||
- }
|
||||
+ nm_assert(nmp_utils_ip_config_source_from_rtprot(proto) == route->rt_source);
|
||||
|
||||
- return TRUE;
|
||||
+ return ip_route_is_tracked(proto, type);
|
||||
}
|
||||
|
||||
/* Copied and modified from libnl3's build_route_msg() and rtnl_route_build_msg(). */
|
||||
diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c
|
||||
index 4090da71a3..cb4e9764d1 100644
|
||||
--- a/src/libnm-platform/nmp-object.c
|
||||
+++ b/src/libnm-platform/nmp-object.c
|
||||
@@ -2988,6 +2988,13 @@ nmp_cache_update_netlink_route(NMPCache *cache,
|
||||
* Since we don't cache all routes (see "route_is_alive"), we cannot know
|
||||
* with certainty which route was replaced.
|
||||
*
|
||||
+ * For example, the kernel might have 3 similar routes (same WEAK_ID), one
|
||||
+ * of which is not tracked by us so we don't have it into the cache. If we
|
||||
+ * receive a route replace message, we don't know to what of the 3 routes
|
||||
+ * it affects (one of the 3 we don't even know that exists). Moreover, if
|
||||
+ * we only have one route on cache, we don't know if the replace is for a
|
||||
+ * different one that we don't track.
|
||||
+ *
|
||||
* Even if we would cache *all* routes (which we cannot, if kernel adds new
|
||||
* routing features that modify the known nmp_object_id_equal()), it would
|
||||
* be hard to find the right route that was replaced. Well, probably we
|
||||
@@ -3002,15 +3009,14 @@ nmp_cache_update_netlink_route(NMPCache *cache,
|
||||
* [2] https://bugzilla.redhat.com/show_bug.cgi?id=1337860
|
||||
*
|
||||
* We need to resync.
|
||||
+ *
|
||||
+ * However, a resync is expensive. Think of a routing daemon that updates
|
||||
+ * hundreds of routes per second, the performance penalty is huge. We can
|
||||
+ * optimize it: if we don't have any matching route on cache (by WEAK_ID),
|
||||
+ * we don't have anything to replace and we don't need a full resync, but
|
||||
+ * only to add or discard the new route as usual.
|
||||
*/
|
||||
- if (NMP_OBJECT_GET_TYPE(obj_hand_over) == NMP_OBJECT_TYPE_IP4_ROUTE
|
||||
- && !nmp_cache_lookup_all(cache, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, obj_hand_over)) {
|
||||
- /* For IPv4, we can do a small optimization. We skip the resync, if we have
|
||||
- * no conflicting routes (by weak-id).
|
||||
- *
|
||||
- * This optimization does not work for IPv6 (maybe should be fixed).
|
||||
- */
|
||||
- } else {
|
||||
+ if (nmp_cache_lookup_all(cache, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, obj_hand_over)) {
|
||||
entry_replace = NULL;
|
||||
resync_required = TRUE;
|
||||
goto out;
|
||||
--
|
||||
2.44.0
|
||||
|
@ -1,487 +0,0 @@
|
||||
From d6837f0bd30da069d327099cb555854630cd4584 Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Thu, 2 May 2024 16:40:26 +0200
|
||||
Subject: [PATCH 1/2] settings: add
|
||||
nm_settings_connection_persist_mode_to_string()
|
||||
|
||||
(cherry picked from commit a48b7fe7b9d8adf4902c7b3cfcc4d89bc46cbbef)
|
||||
(cherry picked from commit e5837aa1d3960b743adcff0a5041445ccd65fb93)
|
||||
---
|
||||
src/core/settings/nm-settings-connection.c | 23 ++++++++++++++++++++++
|
||||
src/core/settings/nm-settings-connection.h | 4 ++++
|
||||
2 files changed, 27 insertions(+)
|
||||
|
||||
diff --git a/src/core/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c
|
||||
index 176cc2c252..459c60ad1e 100644
|
||||
--- a/src/core/settings/nm-settings-connection.c
|
||||
+++ b/src/core/settings/nm-settings-connection.c
|
||||
@@ -226,6 +226,29 @@ static guint _get_seen_bssids(NMSettingsConnection *self,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
+char *
|
||||
+nm_settings_connection_persist_mode_to_string(NMSettingsConnectionPersistMode mode)
|
||||
+{
|
||||
+ switch (mode) {
|
||||
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY:
|
||||
+ return "in-memory";
|
||||
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED:
|
||||
+ return "in-memory-detached";
|
||||
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY:
|
||||
+ return "in-memory-only";
|
||||
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP:
|
||||
+ return "keep";
|
||||
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST:
|
||||
+ return "no-persist";
|
||||
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK:
|
||||
+ return "to-disk";
|
||||
+ }
|
||||
+
|
||||
+ return nm_assert_unreachable_val(NULL);
|
||||
+}
|
||||
+
|
||||
+/*****************************************************************************/
|
||||
+
|
||||
NMSettings *
|
||||
nm_settings_connection_get_settings(NMSettingsConnection *self)
|
||||
{
|
||||
diff --git a/src/core/settings/nm-settings-connection.h b/src/core/settings/nm-settings-connection.h
|
||||
index 835a978e40..d15a75b749 100644
|
||||
--- a/src/core/settings/nm-settings-connection.h
|
||||
+++ b/src/core/settings/nm-settings-connection.h
|
||||
@@ -379,4 +379,8 @@ void _nm_settings_connection_emit_signal_updated_internal(
|
||||
|
||||
void _nm_settings_connection_cleanup_after_remove(NMSettingsConnection *self);
|
||||
|
||||
+/*****************************************************************************/
|
||||
+
|
||||
+char *nm_settings_connection_persist_mode_to_string(NMSettingsConnectionPersistMode mode);
|
||||
+
|
||||
#endif /* __NETWORKMANAGER_SETTINGS_CONNECTION_H__ */
|
||||
--
|
||||
2.41.0
|
||||
|
||||
From c6f9d0a6d5c864ba0141b6e985727cd69c5560fa Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Mon, 15 Apr 2024 10:51:24 +0200
|
||||
Subject: [PATCH 2/2] checkpoint: preserve in-memory state of connections
|
||||
|
||||
If a connection is in-memory (i.e. has flag "unsaved"), after a
|
||||
checkpoint and rollback it can be wrongly persisted to disk:
|
||||
|
||||
- if the connection was modified and written to disk after the
|
||||
rollback, during the rollback we update it again with persist mode
|
||||
"keep", which keeps it on disk;
|
||||
|
||||
- if the connection was deleted after the rollback, during the
|
||||
rollback we add it again with persist mode "to-disk".
|
||||
|
||||
Instead, remember whether the connection had the "unsaved" flag set
|
||||
and try to restore the previous state.
|
||||
|
||||
However, this is not straightforward as there are 4 different possible
|
||||
states for the settings connection: persistent; in-memory only;
|
||||
in-memory shadowing a persistent file; in-memory shadowing a detached
|
||||
persistent file (i.e. the deletion of the connection doesn't delete
|
||||
the persistent file). Handle all those cases.
|
||||
|
||||
Fixes: 3e09aed2a09f ('checkpoint: add create, rollback and destroy D-Bus API')
|
||||
(cherry picked from commit c979bfeb8b0d3bed19bac2ad01a6a6ed899f924e)
|
||||
(cherry picked from commit ebf25794d9cd89190775ac401c36d63aa1c108f7)
|
||||
---
|
||||
NEWS | 8 ++
|
||||
src/core/nm-checkpoint.c | 242 ++++++++++++++++++++++++++++++++-------
|
||||
2 files changed, 211 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/NEWS b/NEWS
|
||||
index 6ac3118db9..e33152c6f4 100644
|
||||
--- a/NEWS
|
||||
+++ b/NEWS
|
||||
@@ -1,3 +1,11 @@
|
||||
+===============================================
|
||||
+NetworkManager-1.46.2
|
||||
+Overview of changes since NetworkManager-1.46.0
|
||||
+===============================================
|
||||
+
|
||||
+* Properly restore in-memory connection profiles during the rollback
|
||||
+ of a checkpoint.
|
||||
+
|
||||
=============================================
|
||||
NetworkManager-1.46
|
||||
Overview of changes since NetworkManager-1.44
|
||||
diff --git a/src/core/nm-checkpoint.c b/src/core/nm-checkpoint.c
|
||||
index cc5c189bf9..ffcf6e3aad 100644
|
||||
--- a/src/core/nm-checkpoint.c
|
||||
+++ b/src/core/nm-checkpoint.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "nm-active-connection.h"
|
||||
#include "nm-act-request.h"
|
||||
#include "libnm-core-aux-intern/nm-auth-subject.h"
|
||||
+#include "libnm-core-intern/nm-keyfile-internal.h"
|
||||
#include "nm-core-utils.h"
|
||||
#include "nm-dbus-interface.h"
|
||||
#include "devices/nm-device.h"
|
||||
@@ -17,6 +18,7 @@
|
||||
#include "nm-manager.h"
|
||||
#include "settings/nm-settings.h"
|
||||
#include "settings/nm-settings-connection.h"
|
||||
+#include "settings/plugins/keyfile/nms-keyfile-storage.h"
|
||||
#include "nm-simple-connection.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
@@ -29,11 +31,14 @@ typedef struct {
|
||||
NMDevice *device;
|
||||
NMConnection *applied_connection;
|
||||
NMConnection *settings_connection;
|
||||
+ NMConnection *settings_connection_shadowed;
|
||||
guint64 ac_version_id;
|
||||
NMDeviceState state;
|
||||
bool is_software : 1;
|
||||
bool realized : 1;
|
||||
bool activation_lifetime_bound_to_profile_visibility : 1;
|
||||
+ bool settings_connection_is_unsaved : 1;
|
||||
+ bool settings_connection_is_shadowed_owned : 1;
|
||||
NMUnmanFlagOp unmanaged_explicit;
|
||||
NMActivationReason activation_reason;
|
||||
gulong dev_exported_change_id;
|
||||
@@ -150,37 +155,111 @@ nm_checkpoint_includes_devices_of(NMCheckpoint *self, NMCheckpoint *cp_for_devic
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static NMConnection *
|
||||
+parse_connection_from_shadowed_file(const char *path, GError **error)
|
||||
+{
|
||||
+ nm_auto_unref_keyfile GKeyFile *keyfile = NULL;
|
||||
+ gs_free char *base_dir = NULL;
|
||||
+ char *sep;
|
||||
+
|
||||
+ keyfile = g_key_file_new();
|
||||
+ if (!g_key_file_load_from_file(keyfile, path, G_KEY_FILE_NONE, error))
|
||||
+ return NULL;
|
||||
+
|
||||
+ sep = strrchr(path, '/');
|
||||
+ base_dir = g_strndup(path, sep - path);
|
||||
+
|
||||
+ return nm_keyfile_read(keyfile, base_dir, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, error);
|
||||
+}
|
||||
+
|
||||
static NMSettingsConnection *
|
||||
-find_settings_connection(NMCheckpoint *self,
|
||||
- DeviceCheckpoint *dev_checkpoint,
|
||||
- gboolean *need_update,
|
||||
- gboolean *need_activation)
|
||||
+find_settings_connection(NMCheckpoint *self,
|
||||
+ DeviceCheckpoint *dev_checkpoint,
|
||||
+ gboolean *need_update,
|
||||
+ gboolean *need_update_shadowed,
|
||||
+ gboolean *need_activation,
|
||||
+ NMSettingsConnectionPersistMode *persist_mode)
|
||||
{
|
||||
NMCheckpointPrivate *priv = NM_CHECKPOINT_GET_PRIVATE(self);
|
||||
NMActiveConnection *active;
|
||||
NMSettingsConnection *sett_conn;
|
||||
+ const char *shadowed_file;
|
||||
+ NMConnection *shadowed_connection = NULL;
|
||||
const char *uuid, *ac_uuid;
|
||||
const CList *tmp_clist;
|
||||
-
|
||||
- *need_activation = FALSE;
|
||||
- *need_update = FALSE;
|
||||
+ gboolean sett_conn_unsaved;
|
||||
+ NMSettingsStorage *storage;
|
||||
+
|
||||
+ *need_activation = FALSE;
|
||||
+ *need_update = FALSE;
|
||||
+ *need_update_shadowed = FALSE;
|
||||
+
|
||||
+ /* With regard to storage, there are 4 different possible states for the settings
|
||||
+ * connection: 1) persistent; 2) in-memory only; 3) in-memory shadowing a persistent
|
||||
+ * file; 4) in-memory shadowing a detached persistent file (i.e. the deletion of
|
||||
+ * the connection doesn't delete the persistent file).
|
||||
+ */
|
||||
+ if (dev_checkpoint->settings_connection_is_unsaved) {
|
||||
+ if (dev_checkpoint->settings_connection_shadowed) {
|
||||
+ if (dev_checkpoint->settings_connection_is_shadowed_owned)
|
||||
+ *persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY;
|
||||
+ else
|
||||
+ *persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED;
|
||||
+ } else
|
||||
+ *persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY;
|
||||
+ } else {
|
||||
+ *persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK;
|
||||
+ }
|
||||
|
||||
uuid = nm_connection_get_uuid(dev_checkpoint->settings_connection);
|
||||
sett_conn = nm_settings_get_connection_by_uuid(NM_SETTINGS_GET, uuid);
|
||||
|
||||
- if (!sett_conn)
|
||||
- return NULL;
|
||||
-
|
||||
- /* Now check if the connection changed, ... */
|
||||
- if (!nm_connection_compare(dev_checkpoint->settings_connection,
|
||||
- nm_settings_connection_get_connection(sett_conn),
|
||||
- NM_SETTING_COMPARE_FLAG_EXACT)) {
|
||||
+ /* Check if the connection changed */
|
||||
+ if (sett_conn
|
||||
+ && !nm_connection_compare(dev_checkpoint->settings_connection,
|
||||
+ nm_settings_connection_get_connection(sett_conn),
|
||||
+ NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)) {
|
||||
_LOGT("rollback: settings connection %s changed", uuid);
|
||||
*need_update = TRUE;
|
||||
*need_activation = TRUE;
|
||||
}
|
||||
|
||||
- /* ... is active, ... */
|
||||
+ storage = sett_conn ? nm_settings_connection_get_storage(sett_conn) : NULL;
|
||||
+ shadowed_file = storage ? nm_settings_storage_get_shadowed_storage(storage, NULL) : NULL;
|
||||
+ shadowed_connection =
|
||||
+ shadowed_file ? parse_connection_from_shadowed_file(shadowed_file, NULL) : NULL;
|
||||
+
|
||||
+ if (dev_checkpoint->settings_connection_shadowed) {
|
||||
+ if (!shadowed_connection
|
||||
+ || !nm_connection_compare(dev_checkpoint->settings_connection_shadowed,
|
||||
+ shadowed_connection,
|
||||
+ NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)) {
|
||||
+ _LOGT("rollback: shadowed connection changed for %s", uuid);
|
||||
+ *need_update_shadowed = TRUE;
|
||||
+ *need_update = TRUE;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (shadowed_connection) {
|
||||
+ _LOGT("rollback: shadowed connection changed for %s", uuid);
|
||||
+ *need_update = TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!sett_conn)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* Check if the connection unsaved flag changed */
|
||||
+ sett_conn_unsaved = NM_FLAGS_HAS(nm_settings_connection_get_flags(sett_conn),
|
||||
+ NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED);
|
||||
+ if (sett_conn_unsaved != dev_checkpoint->settings_connection_is_unsaved) {
|
||||
+ _LOGT("rollback: storage changed for settings connection %s: unsaved (%d -> %d)",
|
||||
+ uuid,
|
||||
+ dev_checkpoint->settings_connection_is_unsaved,
|
||||
+ sett_conn_unsaved);
|
||||
+ *need_update = TRUE;
|
||||
+ }
|
||||
+
|
||||
+ /* Check if the active state changed */
|
||||
nm_manager_for_each_active_connection (priv->manager, active, tmp_clist) {
|
||||
ac_uuid =
|
||||
nm_settings_connection_get_uuid(nm_active_connection_get_settings_connection(active));
|
||||
@@ -196,7 +275,7 @@ find_settings_connection(NMCheckpoint *self,
|
||||
return sett_conn;
|
||||
}
|
||||
|
||||
- /* ... or if the connection was reactivated/reapplied */
|
||||
+ /* Check if the connection was reactivated/reapplied */
|
||||
if (nm_active_connection_version_id_get(active) != dev_checkpoint->ac_version_id) {
|
||||
_LOGT("rollback: active connection version id of %s changed", uuid);
|
||||
*need_activation = TRUE;
|
||||
@@ -212,12 +291,19 @@ restore_and_activate_connection(NMCheckpoint *self, DeviceCheckpoint *dev_checkp
|
||||
NMSettingsConnection *connection;
|
||||
gs_unref_object NMAuthSubject *subject = NULL;
|
||||
GError *local_error = NULL;
|
||||
- gboolean need_update, need_activation;
|
||||
+ gboolean need_update;
|
||||
+ gboolean need_update_shadowed;
|
||||
+ gboolean need_activation;
|
||||
NMSettingsConnectionPersistMode persist_mode;
|
||||
NMSettingsConnectionIntFlags sett_flags;
|
||||
NMSettingsConnectionIntFlags sett_mask;
|
||||
|
||||
- connection = find_settings_connection(self, dev_checkpoint, &need_update, &need_activation);
|
||||
+ connection = find_settings_connection(self,
|
||||
+ dev_checkpoint,
|
||||
+ &need_update,
|
||||
+ &need_update_shadowed,
|
||||
+ &need_activation,
|
||||
+ &persist_mode);
|
||||
|
||||
/* FIXME: we need to ensure to re-create/update the profile for the
|
||||
* same settings plugin. E.g. if it was a keyfile in /run or /etc,
|
||||
@@ -229,9 +315,26 @@ restore_and_activate_connection(NMCheckpoint *self, DeviceCheckpoint *dev_checkp
|
||||
sett_mask = NM_SETTINGS_CONNECTION_INT_FLAGS_NONE;
|
||||
|
||||
if (connection) {
|
||||
+ if (need_update_shadowed) {
|
||||
+ _LOGD("rollback: updating shadowed file for connection %s",
|
||||
+ nm_connection_get_uuid(dev_checkpoint->settings_connection));
|
||||
+ nm_settings_connection_update(
|
||||
+ connection,
|
||||
+ NULL,
|
||||
+ dev_checkpoint->settings_connection_shadowed,
|
||||
+ NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK,
|
||||
+ sett_flags,
|
||||
+ sett_mask,
|
||||
+ NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS
|
||||
+ | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET,
|
||||
+ "checkpoint-rollback",
|
||||
+ NULL);
|
||||
+ }
|
||||
+
|
||||
if (need_update) {
|
||||
- _LOGD("rollback: updating connection %s", nm_settings_connection_get_uuid(connection));
|
||||
- persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP;
|
||||
+ _LOGD("rollback: updating connection %s with persist mode \"%s\"",
|
||||
+ nm_connection_get_uuid(dev_checkpoint->settings_connection),
|
||||
+ nm_settings_connection_persist_mode_to_string(persist_mode));
|
||||
nm_settings_connection_update(
|
||||
connection,
|
||||
NULL,
|
||||
@@ -246,21 +349,54 @@ restore_and_activate_connection(NMCheckpoint *self, DeviceCheckpoint *dev_checkp
|
||||
}
|
||||
} else {
|
||||
/* The connection was deleted, recreate it */
|
||||
- _LOGD("rollback: adding connection %s again",
|
||||
- nm_connection_get_uuid(dev_checkpoint->settings_connection));
|
||||
-
|
||||
- persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK;
|
||||
- if (!nm_settings_add_connection(NM_SETTINGS_GET,
|
||||
- NULL,
|
||||
- dev_checkpoint->settings_connection,
|
||||
- persist_mode,
|
||||
- NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
|
||||
- sett_flags,
|
||||
- &connection,
|
||||
- &local_error)) {
|
||||
- _LOGD("rollback: connection add failure: %s", local_error->message);
|
||||
- g_clear_error(&local_error);
|
||||
- return FALSE;
|
||||
+ if (need_update_shadowed) {
|
||||
+ _LOGD("rollback: adding back shadowed file for connection %s",
|
||||
+ nm_connection_get_uuid(dev_checkpoint->settings_connection));
|
||||
+
|
||||
+ if (!nm_settings_add_connection(NM_SETTINGS_GET,
|
||||
+ NULL,
|
||||
+ dev_checkpoint->settings_connection_shadowed,
|
||||
+ NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK,
|
||||
+ NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
|
||||
+ sett_flags,
|
||||
+ &connection,
|
||||
+ &local_error)) {
|
||||
+ _LOGD("rollback: connection add failure: %s", local_error->message);
|
||||
+ g_clear_error(&local_error);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ _LOGD("rollback: updating connection %s with persist mode \"%s\"",
|
||||
+ nm_connection_get_uuid(dev_checkpoint->settings_connection),
|
||||
+ nm_settings_connection_persist_mode_to_string(persist_mode));
|
||||
+
|
||||
+ nm_settings_connection_update(
|
||||
+ connection,
|
||||
+ NULL,
|
||||
+ dev_checkpoint->settings_connection,
|
||||
+ persist_mode,
|
||||
+ sett_flags,
|
||||
+ sett_mask,
|
||||
+ NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS
|
||||
+ | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET,
|
||||
+ "checkpoint-rollback",
|
||||
+ NULL);
|
||||
+ } else {
|
||||
+ _LOGD("rollback: adding back connection %s with persist mode \"%s\"",
|
||||
+ nm_connection_get_uuid(dev_checkpoint->settings_connection),
|
||||
+ nm_settings_connection_persist_mode_to_string(persist_mode));
|
||||
+ if (!nm_settings_add_connection(NM_SETTINGS_GET,
|
||||
+ NULL,
|
||||
+ dev_checkpoint->settings_connection,
|
||||
+ persist_mode,
|
||||
+ NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
|
||||
+ sett_flags,
|
||||
+ &connection,
|
||||
+ &local_error)) {
|
||||
+ _LOGD("rollback: connection add failure: %s", local_error->message);
|
||||
+ g_clear_error(&local_error);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
}
|
||||
need_activation = TRUE;
|
||||
}
|
||||
@@ -362,11 +498,15 @@ nm_checkpoint_rollback(NMCheckpoint *self)
|
||||
while (g_hash_table_iter_next(&iter, (gpointer *) &device, (gpointer *) &dev_checkpoint)) {
|
||||
guint32 result = NM_ROLLBACK_RESULT_OK;
|
||||
|
||||
- _LOGD("rollback: restoring device %s (state %d, realized %d, explicitly unmanaged %d)",
|
||||
+ _LOGD("rollback: restoring device %s (state %d, realized %d, explicitly unmanaged %d, "
|
||||
+ "connection-unsaved %d, connection-shadowed %d, connection-shadowed-owned %d)",
|
||||
dev_checkpoint->original_dev_name,
|
||||
(int) dev_checkpoint->state,
|
||||
dev_checkpoint->realized,
|
||||
- dev_checkpoint->unmanaged_explicit);
|
||||
+ dev_checkpoint->unmanaged_explicit,
|
||||
+ dev_checkpoint->settings_connection_is_unsaved,
|
||||
+ !!dev_checkpoint->settings_connection_shadowed,
|
||||
+ dev_checkpoint->settings_connection_is_shadowed_owned);
|
||||
|
||||
if (nm_device_is_real(device)) {
|
||||
if (!dev_checkpoint->realized) {
|
||||
@@ -518,6 +658,7 @@ device_checkpoint_destroy(gpointer data)
|
||||
g_clear_object(&dev_checkpoint->applied_connection);
|
||||
g_clear_object(&dev_checkpoint->settings_connection);
|
||||
g_clear_object(&dev_checkpoint->device);
|
||||
+ g_clear_object(&dev_checkpoint->settings_connection_shadowed);
|
||||
g_free(dev_checkpoint->original_dev_path);
|
||||
g_free(dev_checkpoint->original_dev_name);
|
||||
|
||||
@@ -555,7 +696,7 @@ _dev_exported_changed(NMDBusObject *obj, NMCheckpoint *checkpoint)
|
||||
}
|
||||
|
||||
static DeviceCheckpoint *
|
||||
-device_checkpoint_create(NMCheckpoint *checkpoint, NMDevice *device)
|
||||
+device_checkpoint_create(NMCheckpoint *self, NMDevice *device)
|
||||
{
|
||||
DeviceCheckpoint *dev_checkpoint;
|
||||
NMConnection *applied_connection;
|
||||
@@ -579,7 +720,7 @@ device_checkpoint_create(NMCheckpoint *checkpoint, NMDevice *device)
|
||||
dev_checkpoint->dev_exported_change_id = g_signal_connect(device,
|
||||
NM_DBUS_OBJECT_EXPORTED_CHANGED,
|
||||
G_CALLBACK(_dev_exported_changed),
|
||||
- checkpoint);
|
||||
+ self);
|
||||
|
||||
if (nm_device_get_unmanaged_mask(device, NM_UNMANAGED_USER_EXPLICIT)) {
|
||||
dev_checkpoint->unmanaged_explicit =
|
||||
@@ -589,6 +730,11 @@ device_checkpoint_create(NMCheckpoint *checkpoint, NMDevice *device)
|
||||
|
||||
act_request = nm_device_get_act_request(device);
|
||||
if (act_request) {
|
||||
+ NMSettingsStorage *storage;
|
||||
+ gboolean shadowed_owned = FALSE;
|
||||
+ const char *shadowed_file;
|
||||
+ gs_free_error GError *error = NULL;
|
||||
+
|
||||
settings_connection = nm_act_request_get_settings_connection(act_request);
|
||||
applied_connection = nm_act_request_get_applied_connection(act_request);
|
||||
|
||||
@@ -602,6 +748,24 @@ device_checkpoint_create(NMCheckpoint *checkpoint, NMDevice *device)
|
||||
dev_checkpoint->activation_lifetime_bound_to_profile_visibility =
|
||||
NM_FLAGS_HAS(nm_active_connection_get_state_flags(NM_ACTIVE_CONNECTION(act_request)),
|
||||
NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY);
|
||||
+
|
||||
+ dev_checkpoint->settings_connection_is_unsaved =
|
||||
+ NM_FLAGS_HAS(nm_settings_connection_get_flags(settings_connection),
|
||||
+ NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED);
|
||||
+
|
||||
+ storage = nm_settings_connection_get_storage(settings_connection);
|
||||
+ shadowed_file =
|
||||
+ storage ? nm_settings_storage_get_shadowed_storage(storage, &shadowed_owned) : NULL;
|
||||
+ if (shadowed_file) {
|
||||
+ dev_checkpoint->settings_connection_is_shadowed_owned = shadowed_owned;
|
||||
+ dev_checkpoint->settings_connection_shadowed =
|
||||
+ parse_connection_from_shadowed_file(shadowed_file, &error);
|
||||
+ if (!dev_checkpoint->settings_connection_shadowed) {
|
||||
+ _LOGW("error reading shadowed connection file for %s: %s",
|
||||
+ nm_device_get_iface(device),
|
||||
+ error->message);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
return dev_checkpoint;
|
||||
--
|
||||
2.41.0
|
||||
|
@ -1,398 +0,0 @@
|
||||
From 3806d476ab8c45a8ea534be064515744ccea16e2 Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Tue, 7 May 2024 17:51:19 +0200
|
||||
Subject: [PATCH 1/4] vpn: allow IP configurations without addresses
|
||||
|
||||
An IPv4-over-IPv6 (or vice-versa) IPsec VPN can return IP
|
||||
configurations with routes and without addresses. For example, in this
|
||||
scenario:
|
||||
|
||||
+---------------+ +---------------+
|
||||
| fd01::10/64 <-- VPN --> fd02::20/64 |
|
||||
| host1 | | host2 |
|
||||
+-------^-------+ +-------^-------+
|
||||
| |
|
||||
+-------v-------+ +-------v-------+
|
||||
| subnet1 | | subnet2 |
|
||||
| 172.16.1.0/24 | | 172.16.2.0/24 |
|
||||
+---------------+ +---------------+
|
||||
|
||||
host1 and host2 establish a IPv6 tunnel which encapsulates packets
|
||||
between the two IPv4 subnets. Therefore, in routed mode, host1 will
|
||||
need to configure a route like "172.16.2.0/24 via ipsec1" even if the
|
||||
host doesn't have any IPv4 address on the VPN interface.
|
||||
|
||||
Accept IP configurations without address from the VPN; only check that
|
||||
the address and prefix are sane if they are provided.
|
||||
|
||||
(cherry picked from commit 97f185e1f8e5a60d770711d8bce8bd12a205590f)
|
||||
(cherry picked from commit 518b7c5bd51d3f652c8179594a522f6ddf93f449)
|
||||
(cherry picked from commit 476a9553f61c4bd6f0c8dec476b3179de6cf2293)
|
||||
---
|
||||
src/core/vpn/nm-vpn-connection.c | 44 ++++++++++++++++++++------------
|
||||
1 file changed, 27 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
|
||||
index 3dba9ff6c8..62aecbd286 100644
|
||||
--- a/src/core/vpn/nm-vpn-connection.c
|
||||
+++ b/src/core/vpn/nm-vpn-connection.c
|
||||
@@ -1988,6 +1988,12 @@ _dbus_signal_ip_config_cb(NMVpnConnection *self, int addr_family, GVariant *dict
|
||||
|
||||
nm_l3_config_data_set_dns_priority(l3cd, AF_INET, NM_DNS_PRIORITY_DEFAULT_VPN);
|
||||
|
||||
+ _vardict_to_addr(addr_family,
|
||||
+ dict,
|
||||
+ IS_IPv4 ? NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY
|
||||
+ : NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY,
|
||||
+ &priv->ip_data_x[IS_IPv4].gw_internal);
|
||||
+
|
||||
if (IS_IPv4) {
|
||||
address.a4 = (NMPlatformIP4Address){
|
||||
.plen = 24,
|
||||
@@ -1998,16 +2004,17 @@ _dbus_signal_ip_config_cb(NMVpnConnection *self, int addr_family, GVariant *dict
|
||||
};
|
||||
}
|
||||
|
||||
- _vardict_to_addr(addr_family,
|
||||
- dict,
|
||||
- IS_IPv4 ? NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY
|
||||
- : NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY,
|
||||
- &priv->ip_data_x[IS_IPv4].gw_internal);
|
||||
-
|
||||
- _vardict_to_addr(addr_family,
|
||||
- dict,
|
||||
- IS_IPv4 ? NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS : NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS,
|
||||
- address.ax.address_ptr);
|
||||
+ if (_vardict_to_addr(addr_family,
|
||||
+ dict,
|
||||
+ IS_IPv4 ? NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS
|
||||
+ : NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS,
|
||||
+ address.ax.address_ptr)
|
||||
+ && nm_ip_addr_is_null(addr_family, &address.ax.address_ptr)) {
|
||||
+ _LOGW("invalid IP%c config received: address is zero",
|
||||
+ nm_utils_addr_family_to_char(addr_family));
|
||||
+ _check_complete(self, FALSE);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
if (!_vardict_to_addr(addr_family,
|
||||
dict,
|
||||
@@ -2024,17 +2031,20 @@ _dbus_signal_ip_config_cb(NMVpnConnection *self, int addr_family, GVariant *dict
|
||||
&u32))
|
||||
address.ax.plen = u32;
|
||||
|
||||
- if (address.ax.plen > 0 && address.ax.plen <= (IS_IPv4 ? 32 : 128)
|
||||
- && !nm_ip_addr_is_null(addr_family, &address.ax.address_ptr)) {
|
||||
- address.ax.addr_source = NM_IP_CONFIG_SOURCE_VPN;
|
||||
- nm_l3_config_data_add_address(l3cd, addr_family, NULL, &address.ax);
|
||||
- } else {
|
||||
- _LOGW("invalid IP%c config received: no valid IP address/prefix",
|
||||
- nm_utils_addr_family_to_char(addr_family));
|
||||
+ if (!nm_ip_addr_is_null(addr_family, &address.ax.address_ptr)
|
||||
+ && (address.ax.plen == 0 || address.ax.plen > (IS_IPv4 ? 32 : 128))) {
|
||||
+ _LOGW("invalid IP%c config received: invalid prefix %u",
|
||||
+ nm_utils_addr_family_to_char(addr_family),
|
||||
+ address.ax.plen);
|
||||
_check_complete(self, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (!nm_ip_addr_is_null(addr_family, &address.ax.address_ptr)) {
|
||||
+ address.ax.addr_source = NM_IP_CONFIG_SOURCE_VPN;
|
||||
+ nm_l3_config_data_add_address(l3cd, addr_family, NULL, &address.ax);
|
||||
+ }
|
||||
+
|
||||
if (IS_IPv4) {
|
||||
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_DNS, "au", &var_iter)) {
|
||||
while (g_variant_iter_next(var_iter, "u", &u32))
|
||||
--
|
||||
2.45.2
|
||||
|
||||
|
||||
From 044f85613f09861d908045feda6d6f3b499d75b5 Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Wed, 8 May 2024 10:49:27 +0200
|
||||
Subject: [PATCH 2/4] core: rename l3cd's "dhcp_enabled" to
|
||||
"allow_routes_without_address"
|
||||
|
||||
The name "dhcp_enabled" is misleading because the flag is set for
|
||||
method=auto, which doesn't necessarily imply DHCP. Also, it doesn't
|
||||
convey what the flag is used for. Rename it to
|
||||
"allow_routes_without_address".
|
||||
|
||||
(cherry picked from commit b31febea22485d3dd063cfff8fc61c1e3901a7ca)
|
||||
(cherry picked from commit 6897b6ecfdd5ed2e50c7db45a4ea3c7c7998d908)
|
||||
(cherry picked from commit ea731bba9b1f5a22e48c0a6c1881bc91c3cf1032)
|
||||
---
|
||||
src/core/nm-l3-config-data.c | 68 +++++++++++++++++++-----------------
|
||||
src/core/nm-l3-config-data.h | 3 +-
|
||||
src/core/nm-l3cfg.c | 9 +++--
|
||||
3 files changed, 41 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c
|
||||
index a4647116a9..fbee1bf7e8 100644
|
||||
--- a/src/core/nm-l3-config-data.c
|
||||
+++ b/src/core/nm-l3-config-data.c
|
||||
@@ -157,8 +157,8 @@ struct _NML3ConfigData {
|
||||
bool has_routes_with_type_local_6_set : 1;
|
||||
bool has_routes_with_type_local_4_val : 1;
|
||||
bool has_routes_with_type_local_6_val : 1;
|
||||
- bool dhcp_enabled_4 : 1;
|
||||
- bool dhcp_enabled_6 : 1;
|
||||
+ bool allow_routes_without_address_4 : 1;
|
||||
+ bool allow_routes_without_address_6 : 1;
|
||||
|
||||
bool ndisc_hop_limit_set : 1;
|
||||
bool ndisc_reachable_time_msec_set : 1;
|
||||
@@ -678,26 +678,28 @@ nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex, NMIPConfigSourc
|
||||
|
||||
self = g_slice_new(NML3ConfigData);
|
||||
*self = (NML3ConfigData){
|
||||
- .ref_count = 1,
|
||||
- .ifindex = ifindex,
|
||||
- .multi_idx = nm_dedup_multi_index_ref(multi_idx),
|
||||
- .mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT,
|
||||
- .llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT,
|
||||
- .dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT,
|
||||
- .flags = NM_L3_CONFIG_DAT_FLAGS_NONE,
|
||||
- .metered = NM_TERNARY_DEFAULT,
|
||||
- .proxy_browser_only = NM_TERNARY_DEFAULT,
|
||||
- .proxy_method = NM_PROXY_CONFIG_METHOD_UNKNOWN,
|
||||
- .route_table_sync_4 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
||||
- .route_table_sync_6 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
||||
- .never_default_6 = NM_OPTION_BOOL_DEFAULT,
|
||||
- .never_default_4 = NM_OPTION_BOOL_DEFAULT,
|
||||
- .source = source,
|
||||
- .ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
|
||||
- .mptcp_flags = NM_MPTCP_FLAGS_NONE,
|
||||
- .ndisc_hop_limit_set = FALSE,
|
||||
- .ndisc_reachable_time_msec_set = FALSE,
|
||||
- .ndisc_retrans_timer_msec_set = FALSE,
|
||||
+ .ref_count = 1,
|
||||
+ .ifindex = ifindex,
|
||||
+ .multi_idx = nm_dedup_multi_index_ref(multi_idx),
|
||||
+ .mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT,
|
||||
+ .llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT,
|
||||
+ .dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT,
|
||||
+ .flags = NM_L3_CONFIG_DAT_FLAGS_NONE,
|
||||
+ .metered = NM_TERNARY_DEFAULT,
|
||||
+ .proxy_browser_only = NM_TERNARY_DEFAULT,
|
||||
+ .proxy_method = NM_PROXY_CONFIG_METHOD_UNKNOWN,
|
||||
+ .route_table_sync_4 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
||||
+ .route_table_sync_6 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
||||
+ .never_default_6 = NM_OPTION_BOOL_DEFAULT,
|
||||
+ .never_default_4 = NM_OPTION_BOOL_DEFAULT,
|
||||
+ .source = source,
|
||||
+ .ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
|
||||
+ .mptcp_flags = NM_MPTCP_FLAGS_NONE,
|
||||
+ .ndisc_hop_limit_set = FALSE,
|
||||
+ .ndisc_reachable_time_msec_set = FALSE,
|
||||
+ .ndisc_retrans_timer_msec_set = FALSE,
|
||||
+ .allow_routes_without_address_4 = TRUE,
|
||||
+ .allow_routes_without_address_6 = TRUE,
|
||||
};
|
||||
|
||||
_idx_type_init(&self->idx_addresses_4, NMP_OBJECT_TYPE_IP4_ADDRESS);
|
||||
@@ -1936,15 +1938,15 @@ nm_l3_config_data_set_mptcp_flags(NML3ConfigData *self, NMMptcpFlags mptcp_flags
|
||||
}
|
||||
|
||||
gboolean
|
||||
-nm_l3_config_data_get_dhcp_enabled(const NML3ConfigData *self, int addr_family)
|
||||
+nm_l3_config_data_get_allow_routes_without_address(const NML3ConfigData *self, int addr_family)
|
||||
{
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
|
||||
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
||||
if (IS_IPv4) {
|
||||
- return self->dhcp_enabled_4;
|
||||
+ return self->allow_routes_without_address_4;
|
||||
} else {
|
||||
- return self->dhcp_enabled_6;
|
||||
+ return self->allow_routes_without_address_6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2758,18 +2760,18 @@ _init_from_connection_ip(NML3ConfigData *self, int addr_family, NMConnection *co
|
||||
method = nm_setting_ip_config_get_method(s_ip);
|
||||
if (IS_IPv4) {
|
||||
if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
|
||||
- self->dhcp_enabled_4 = TRUE;
|
||||
+ self->allow_routes_without_address_4 = FALSE;
|
||||
} else {
|
||||
- self->dhcp_enabled_4 = FALSE;
|
||||
+ self->allow_routes_without_address_4 = TRUE;
|
||||
}
|
||||
} else {
|
||||
method = nm_setting_ip_config_get_method(s_ip);
|
||||
if (NM_IN_STRSET(method,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
|
||||
- self->dhcp_enabled_6 = TRUE;
|
||||
+ self->allow_routes_without_address_6 = FALSE;
|
||||
} else {
|
||||
- self->dhcp_enabled_6 = FALSE;
|
||||
+ self->allow_routes_without_address_6 = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3456,11 +3458,11 @@ nm_l3_config_data_merge(NML3ConfigData *self,
|
||||
self->dhcp_lease_x[0] = nm_dhcp_lease_ref(self->dhcp_lease_x[0]);
|
||||
self->dhcp_lease_x[1] = nm_dhcp_lease_ref(self->dhcp_lease_x[1]);
|
||||
}
|
||||
- if (src->dhcp_enabled_4)
|
||||
- self->dhcp_enabled_4 = TRUE;
|
||||
+ if (!src->allow_routes_without_address_4)
|
||||
+ self->allow_routes_without_address_4 = FALSE;
|
||||
|
||||
- if (src->dhcp_enabled_6)
|
||||
- self->dhcp_enabled_6 = TRUE;
|
||||
+ if (!src->allow_routes_without_address_6)
|
||||
+ self->allow_routes_without_address_6 = FALSE;
|
||||
}
|
||||
|
||||
NML3ConfigData *
|
||||
diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h
|
||||
index b55b2f4194..5c8491a704 100644
|
||||
--- a/src/core/nm-l3-config-data.h
|
||||
+++ b/src/core/nm-l3-config-data.h
|
||||
@@ -554,7 +554,8 @@ NMSettingIP6ConfigPrivacy nm_l3_config_data_get_ip6_privacy(const NML3ConfigData
|
||||
gboolean nm_l3_config_data_set_ip6_privacy(NML3ConfigData *self,
|
||||
NMSettingIP6ConfigPrivacy ip6_privacy);
|
||||
|
||||
-gboolean nm_l3_config_data_get_dhcp_enabled(const NML3ConfigData *self, int addr_family);
|
||||
+gboolean nm_l3_config_data_get_allow_routes_without_address(const NML3ConfigData *self,
|
||||
+ int addr_family);
|
||||
|
||||
NMProxyConfigMethod nm_l3_config_data_get_proxy_method(const NML3ConfigData *self);
|
||||
|
||||
diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c
|
||||
index f428d04cc6..ab9844d642 100644
|
||||
--- a/src/core/nm-l3cfg.c
|
||||
+++ b/src/core/nm-l3cfg.c
|
||||
@@ -1301,7 +1301,6 @@ _commit_collect_routes(NML3Cfg *self,
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
const NMDedupMultiEntry *entry;
|
||||
- gboolean is_dhcp_enabled;
|
||||
|
||||
nm_assert(routes && !*routes);
|
||||
nm_assert(routes_nodev && !*routes_nodev);
|
||||
@@ -1321,10 +1320,10 @@ _commit_collect_routes(NML3Cfg *self,
|
||||
else {
|
||||
nm_assert(NMP_OBJECT_CAST_IP_ROUTE(obj)->ifindex == self->priv.ifindex);
|
||||
|
||||
- is_dhcp_enabled =
|
||||
- nm_l3_config_data_get_dhcp_enabled(self->priv.p->combined_l3cd_commited,
|
||||
- addr_family);
|
||||
- if (!any_addrs && is_dhcp_enabled) {
|
||||
+ if (!any_addrs
|
||||
+ && !nm_l3_config_data_get_allow_routes_without_address(
|
||||
+ self->priv.p->combined_l3cd_commited,
|
||||
+ addr_family)) {
|
||||
/* This is a unicast route (or a similar route, which has an
|
||||
* ifindex).
|
||||
*
|
||||
--
|
||||
2.45.2
|
||||
|
||||
|
||||
From 66f8dfc453eda98a77c9a85c2b6110955f02b5c7 Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Wed, 8 May 2024 11:02:20 +0200
|
||||
Subject: [PATCH 3/4] core: add
|
||||
nm_l3_config_data_set_allow_routes_without_address()
|
||||
|
||||
Add a function to set the allow-routes-without-address flag for
|
||||
l3cds. It will be used in the next commit.
|
||||
|
||||
(cherry picked from commit a3ce13c947e6eda71fa07de273ede55b806e8d45)
|
||||
(cherry picked from commit 5fa063f90d443044ca1dba71478c701ce7b62b94)
|
||||
(cherry picked from commit e008ec734553f7b065714025e6f3628cac10f314)
|
||||
---
|
||||
src/core/nm-l3-config-data.c | 15 +++++++++++++++
|
||||
src/core/nm-l3-config-data.h | 4 ++++
|
||||
2 files changed, 19 insertions(+)
|
||||
|
||||
diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c
|
||||
index fbee1bf7e8..908c4d65d5 100644
|
||||
--- a/src/core/nm-l3-config-data.c
|
||||
+++ b/src/core/nm-l3-config-data.c
|
||||
@@ -1950,6 +1950,21 @@ nm_l3_config_data_get_allow_routes_without_address(const NML3ConfigData *self, i
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+nm_l3_config_data_set_allow_routes_without_address(NML3ConfigData *self,
|
||||
+ int addr_family,
|
||||
+ gboolean value)
|
||||
+{
|
||||
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
+
|
||||
+ nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
||||
+ if (IS_IPv4) {
|
||||
+ self->allow_routes_without_address_4 = value;
|
||||
+ } else {
|
||||
+ self->allow_routes_without_address_6 = value;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
NMProxyConfigMethod
|
||||
nm_l3_config_data_get_proxy_method(const NML3ConfigData *self)
|
||||
{
|
||||
diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h
|
||||
index 5c8491a704..faf4f0bfa9 100644
|
||||
--- a/src/core/nm-l3-config-data.h
|
||||
+++ b/src/core/nm-l3-config-data.h
|
||||
@@ -557,6 +557,10 @@ gboolean nm_l3_config_data_set_ip6_privacy(NML3ConfigData *self,
|
||||
gboolean nm_l3_config_data_get_allow_routes_without_address(const NML3ConfigData *self,
|
||||
int addr_family);
|
||||
|
||||
+void nm_l3_config_data_set_allow_routes_without_address(NML3ConfigData *self,
|
||||
+ int addr_family,
|
||||
+ gboolean value);
|
||||
+
|
||||
NMProxyConfigMethod nm_l3_config_data_get_proxy_method(const NML3ConfigData *self);
|
||||
|
||||
gboolean nm_l3_config_data_set_proxy_method(NML3ConfigData *self, NMProxyConfigMethod value);
|
||||
--
|
||||
2.45.2
|
||||
|
||||
|
||||
From 1d041a7ada56c27dcd155ff67a1bf02f0b00e35e Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Wed, 8 May 2024 11:04:04 +0200
|
||||
Subject: [PATCH 4/4] vpn: allow IP configurations with routes and without
|
||||
addresses
|
||||
|
||||
Usually, when the method is "auto" we want to avoid configuring routes
|
||||
until the automatic method completes. To achieve that, we clear the
|
||||
"allow_routes_without_address" flag of l3cds when the method is "auto".
|
||||
|
||||
For VPNs, IP configurations with only routes are perfectly valid,
|
||||
therefore set the flag.
|
||||
|
||||
(cherry picked from commit d1ffdb28ebaf3af23ac76b59c35fe7e4672cb5bc)
|
||||
(cherry picked from commit 5b4ed809cc458504f01a02e908a91f2625613787)
|
||||
(cherry picked from commit 83847cc621aaa5ee6130e4088582875fcd98dd64)
|
||||
---
|
||||
src/core/vpn/nm-vpn-connection.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
|
||||
index 62aecbd286..f26f4c42e0 100644
|
||||
--- a/src/core/vpn/nm-vpn-connection.c
|
||||
+++ b/src/core/vpn/nm-vpn-connection.c
|
||||
@@ -1433,6 +1433,10 @@ _check_complete(NMVpnConnection *self, gboolean success)
|
||||
l3cd = nm_l3_config_data_new_from_connection(nm_netns_get_multi_idx(priv->netns),
|
||||
nm_vpn_connection_get_ip_ifindex(self, TRUE),
|
||||
connection);
|
||||
+
|
||||
+ nm_l3_config_data_set_allow_routes_without_address(l3cd, AF_INET, TRUE);
|
||||
+ nm_l3_config_data_set_allow_routes_without_address(l3cd, AF_INET6, TRUE);
|
||||
+
|
||||
_l3cfg_l3cd_set(self, L3CD_TYPE_STATIC, l3cd);
|
||||
|
||||
_l3cfg_l3cd_gw_extern_update(self);
|
||||
--
|
||||
2.45.2
|
||||
|
@ -1,241 +0,0 @@
|
||||
From 4a31371e834057712c33678b249127062b250a33 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
|
||||
Date: Mon, 3 Jun 2024 14:29:15 +0200
|
||||
Subject: [PATCH 1/2] vpn: handle hint tags in the daemon
|
||||
|
||||
Commit 345bd1b18731 ('libnmc: fix secrets request on 2nd stage of 2FA
|
||||
authentication') and commit 27c701ebfbc9 ('libnmc: allow user input in
|
||||
ECHO mode for 2FA challenges') introduced 2 new tags that hints for the
|
||||
secret agents can have as prefix.
|
||||
|
||||
These tags were processed (and removed) in the secret agents, not in the
|
||||
daemon. This is wrong because a system with an updated VPN plugin but a
|
||||
not yet updated secret agent (like nm-plasma) will fail: it won't remove
|
||||
the prefix and the daemon will save the secret with the prefix, i.e.
|
||||
"x-dynamic-challenge:challenge-response" instead of just
|
||||
"challenge-response". Then, VPN plugins doesn't recognize it, failing the
|
||||
profile's activation. This is, in fact, an API break.
|
||||
|
||||
Also, if the VPN connection already existed before updating NM and the
|
||||
VPN plugin, the secret flags are not added to the profile (they are only
|
||||
added when the profile is created or modified). This causes the user's
|
||||
first time response is saved to the profile, so the activation fails the
|
||||
second and next times.
|
||||
|
||||
See:
|
||||
- https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1536
|
||||
- https://gitlab.gnome.org/GNOME/NetworkManager-openvpn/-/issues/142
|
||||
|
||||
Anyway, in a good design the daemon should contain almost all the logic
|
||||
and the clients should keep as simple as possible. Fix above's problems
|
||||
by letting the daemon to receive the secret names with the prefix
|
||||
already included. The daemon will strip it and will know what it means.
|
||||
|
||||
Note that this is done only in the functions that saves the secrets from
|
||||
the data received via D-Bus. For example, nm_setting_vpn_add_secret
|
||||
doesn't need to do it because this value shouldn't come from VPN
|
||||
plugin's hints.
|
||||
|
||||
(cherry picked from commit 0583e1f8436e4c8a4e462a643c711b69d157b938)
|
||||
(cherry picked from commit 574741783c34fc62e8df78544b619d8281ddc85d)
|
||||
(cherry picked from commit bdbcda1e22c2eba9a51fb476b79fb680a99be84f)
|
||||
---
|
||||
src/libnm-core-impl/nm-setting-vpn.c | 55 ++++++++++++++++++++++++++--
|
||||
1 file changed, 52 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/libnm-core-impl/nm-setting-vpn.c b/src/libnm-core-impl/nm-setting-vpn.c
|
||||
index b867d01860..65a14866c8 100644
|
||||
--- a/src/libnm-core-impl/nm-setting-vpn.c
|
||||
+++ b/src/libnm-core-impl/nm-setting-vpn.c
|
||||
@@ -577,14 +577,48 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+_parse_secret_hint_tag(const char *secret_name,
|
||||
+ const char **out_secret_name,
|
||||
+ NMSettingSecretFlags *out_implied_flags)
|
||||
+{
|
||||
+ NMSettingSecretFlags implied_flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||
+ gboolean ret = FALSE;
|
||||
+
|
||||
+ nm_assert(secret_name);
|
||||
+
|
||||
+ if (g_str_has_prefix(secret_name, NM_SECRET_TAG_DYNAMIC_CHALLENGE)) {
|
||||
+ secret_name += NM_STRLEN(NM_SECRET_TAG_DYNAMIC_CHALLENGE);
|
||||
+ implied_flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED;
|
||||
+ ret = TRUE;
|
||||
+ } else if (g_str_has_prefix(secret_name, NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO)) {
|
||||
+ secret_name += NM_STRLEN(NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO);
|
||||
+ implied_flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED;
|
||||
+ ret = TRUE;
|
||||
+ }
|
||||
+
|
||||
+ NM_SET_OUT(out_secret_name, secret_name);
|
||||
+ NM_SET_OUT(out_implied_flags, implied_flags);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static NMSettingUpdateSecretResult
|
||||
update_secret_string(NMSetting *setting, const char *key, const char *value, GError **error)
|
||||
{
|
||||
NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting);
|
||||
+ NMSettingSecretFlags hint_implied_flags, flags;
|
||||
|
||||
g_return_val_if_fail(key && key[0], NM_SETTING_UPDATE_SECRET_ERROR);
|
||||
g_return_val_if_fail(value, NM_SETTING_UPDATE_SECRET_ERROR);
|
||||
|
||||
+ /* If the name is prefixed with a hint tag, process it before saving:
|
||||
+ * remove the prefix and apply the flags that it implies */
|
||||
+ _parse_secret_hint_tag(key, &key, &hint_implied_flags);
|
||||
+ if (hint_implied_flags) {
|
||||
+ nm_setting_get_secret_flags(setting, key, &flags, NULL);
|
||||
+ nm_setting_set_secret_flags(setting, key, flags | hint_implied_flags, NULL);
|
||||
+ }
|
||||
+
|
||||
if (nm_streq0(nm_g_hash_table_lookup(priv->secrets, key), value))
|
||||
return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
|
||||
|
||||
@@ -599,6 +633,7 @@ update_secret_dict(NMSetting *setting, GVariant *secrets, GError **error)
|
||||
GVariantIter iter;
|
||||
const char *name, *value;
|
||||
NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
|
||||
+ NMSettingSecretFlags hint_implied_flags, flags;
|
||||
|
||||
g_return_val_if_fail(secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
|
||||
|
||||
@@ -618,6 +653,14 @@ update_secret_dict(NMSetting *setting, GVariant *secrets, GError **error)
|
||||
/* Now add the items to the settings' secrets list */
|
||||
g_variant_iter_init(&iter, secrets);
|
||||
while (g_variant_iter_next(&iter, "{&s&s}", &name, &value)) {
|
||||
+ /* If the name is prefixed with a hint tag, process it before saving:
|
||||
+ * remove the prefix and apply the flags that it implies */
|
||||
+ _parse_secret_hint_tag(name, &name, &hint_implied_flags);
|
||||
+ if (hint_implied_flags) {
|
||||
+ nm_setting_get_secret_flags(setting, name, &flags, NULL);
|
||||
+ nm_setting_set_secret_flags(setting, name, flags | hint_implied_flags, NULL);
|
||||
+ }
|
||||
+
|
||||
if (nm_streq0(nm_g_hash_table_lookup(priv->secrets, name), value))
|
||||
continue;
|
||||
|
||||
@@ -727,6 +770,7 @@ get_secret_flags(NMSetting *setting,
|
||||
GError **error)
|
||||
{
|
||||
NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting);
|
||||
+ NMSettingSecretFlags implied_flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||
gs_free char *flags_key_free = NULL;
|
||||
const char *flags_key;
|
||||
const char *flags_val;
|
||||
@@ -734,6 +778,10 @@ get_secret_flags(NMSetting *setting,
|
||||
|
||||
nm_assert(secret_name);
|
||||
|
||||
+ /* Secrets received via D-Bus from VPN plugins might be prefixed by a hint tag. If
|
||||
+ * that's the case, process it first: remove the tag and get the flags that it implies */
|
||||
+ _parse_secret_hint_tag(secret_name, &secret_name, &implied_flags);
|
||||
+
|
||||
if (!secret_name[0]) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
@@ -746,7 +794,7 @@ get_secret_flags(NMSetting *setting,
|
||||
|
||||
if (!priv->data
|
||||
|| !g_hash_table_lookup_extended(priv->data, flags_key, NULL, (gpointer *) &flags_val)) {
|
||||
- NM_SET_OUT(out_flags, NM_SETTING_SECRET_FLAG_NONE);
|
||||
+ NM_SET_OUT(out_flags, implied_flags);
|
||||
|
||||
/* having no secret flag for the secret is fine, as long as there
|
||||
* is the secret itself... */
|
||||
@@ -772,7 +820,7 @@ get_secret_flags(NMSetting *setting,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- NM_SET_OUT(out_flags, (NMSettingSecretFlags) i64);
|
||||
+ NM_SET_OUT(out_flags, (NMSettingSecretFlags) i64 | implied_flags);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -783,7 +831,8 @@ set_secret_flags(NMSetting *setting,
|
||||
GError **error)
|
||||
{
|
||||
nm_assert(secret_name);
|
||||
-
|
||||
+ nm_assert(!_parse_secret_hint_tag(secret_name, NULL, NULL)); /* Accept hint tags only via D-Bus,
|
||||
+ saved by update_one_secret */
|
||||
if (!secret_name[0]) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
--
|
||||
2.44.0
|
||||
|
||||
|
||||
From ef781d957db80d1e628098dab2cbb1da70558511 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
|
||||
Date: Wed, 29 May 2024 16:50:10 +0200
|
||||
Subject: [PATCH 2/2] libnmc: don't strip prefix tags from secret names
|
||||
|
||||
The daemon is now capable of understanding and removing these prefix
|
||||
tags by itself. It is better than this is not a responsibility of the
|
||||
secret agent because it requires changes in all secret agents to work
|
||||
properly (see https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1536).
|
||||
|
||||
If the secret agent knows what these prefix tags are, it can remove them
|
||||
only in the text that is displayed in the UI, but maintaining the
|
||||
original string as the secret name that is returned to the daemon.
|
||||
|
||||
Secret agents that doesn't know what these prefix tags are won't do
|
||||
anything with them, and they will also return the same string as secret
|
||||
name, as expected. The only drawback is that they might display the full
|
||||
string to the user, which is not a nice UX but it will at least work.
|
||||
|
||||
Also, allow to translate the secret name for the UI in libnmc.
|
||||
|
||||
(cherry picked from commit 18240bb72d191c987afe150d3a5023fe79d994dd)
|
||||
(cherry picked from commit e217ec040d04835450c2de92cd2cf408e22f3fcd)
|
||||
(cherry picked from commit a8a59e3e0af2f0922c1e6f0e18f00fe195c2d026)
|
||||
---
|
||||
src/libnmc-base/nm-secret-agent-simple.c | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/libnmc-base/nm-secret-agent-simple.c b/src/libnmc-base/nm-secret-agent-simple.c
|
||||
index 4bb77c9802..9d1a2ae962 100644
|
||||
--- a/src/libnmc-base/nm-secret-agent-simple.c
|
||||
+++ b/src/libnmc-base/nm-secret-agent-simple.c
|
||||
@@ -431,7 +431,7 @@ add_vpn_secrets(RequestData *request, GPtrArray *secrets, char **msg)
|
||||
const NmcVpnPasswordName *p;
|
||||
const char *vpn_msg = NULL;
|
||||
char **iter;
|
||||
- char *secret_name;
|
||||
+ char *ui_name;
|
||||
bool is_challenge = FALSE;
|
||||
bool force_echo;
|
||||
|
||||
@@ -442,19 +442,19 @@ add_vpn_secrets(RequestData *request, GPtrArray *secrets, char **msg)
|
||||
vpn_msg = &(*iter)[NM_STRLEN(NM_SECRET_TAG_VPN_MSG)];
|
||||
} else {
|
||||
if (NM_STR_HAS_PREFIX(*iter, NM_SECRET_TAG_DYNAMIC_CHALLENGE)) {
|
||||
- secret_name = &(*iter)[NM_STRLEN(NM_SECRET_TAG_DYNAMIC_CHALLENGE)];
|
||||
+ ui_name = &(*iter)[NM_STRLEN(NM_SECRET_TAG_DYNAMIC_CHALLENGE)];
|
||||
is_challenge = TRUE;
|
||||
force_echo = FALSE;
|
||||
} else if (NM_STR_HAS_PREFIX(*iter, NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO)) {
|
||||
- secret_name = &(*iter)[NM_STRLEN(NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO)];
|
||||
+ ui_name = &(*iter)[NM_STRLEN(NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO)];
|
||||
is_challenge = TRUE;
|
||||
force_echo = TRUE;
|
||||
} else {
|
||||
- secret_name = *iter;
|
||||
- force_echo = FALSE;
|
||||
+ ui_name = *iter;
|
||||
+ force_echo = FALSE;
|
||||
}
|
||||
|
||||
- add_vpn_secret_helper(secrets, s_vpn, secret_name, secret_name, force_echo);
|
||||
+ add_vpn_secret_helper(secrets, s_vpn, *iter, ui_name, force_echo);
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.44.0
|
||||
|
@ -1,37 +0,0 @@
|
||||
From 567853b4299f529ff886bd86292f680cd3b651c6 Mon Sep 17 00:00:00 2001
|
||||
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
Date: Thu, 25 Jul 2024 10:20:14 +0200
|
||||
Subject: [PATCH] ovs: wait for the link to be ready before activating
|
||||
|
||||
When activating an ovs-interface we already wait for the cloned MAC
|
||||
address to be set, ifindex is present and platform link also present but
|
||||
in some cases this is not enough.
|
||||
|
||||
If an udev rule is in place it might modify the interface when it is in
|
||||
a later stage of the activation causing some race conditions or
|
||||
problems. In order to solve that, we must wait until the link is fully
|
||||
initialized.
|
||||
|
||||
(cherry picked from commit 83bf7a8cdb56154cee6ed53c1cc3046ed9db73b8)
|
||||
(cherry picked from commit 00e178351beba50b9d4c877364c6b46cc182dfcd)
|
||||
(cherry picked from commit 6328a1a0d1e4ae4f86c11b97a9ee54ec15fa233a)
|
||||
---
|
||||
src/core/devices/ovs/nm-device-ovs-interface.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c
|
||||
index 17eb2c2d12..104b312674 100644
|
||||
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
|
||||
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
|
||||
@@ -155,6 +155,8 @@ check_waiting_for_link(NMDevice *device, const char *from)
|
||||
reason = "no ifindex";
|
||||
} else if (!(pllink = nm_platform_link_get(platform, ip_ifindex))) {
|
||||
reason = "platform link not found";
|
||||
+ } else if (!pllink->initialized) {
|
||||
+ reason = "link is not ready yet";
|
||||
} else if (priv->wait_link.cloned_mac
|
||||
&& !nm_utils_hwaddr_matches(priv->wait_link.cloned_mac,
|
||||
-1,
|
||||
--
|
||||
2.45.2
|
||||
|
@ -1,67 +0,0 @@
|
||||
From 0d744e4942d1a8bc7c600ddde82057bb8aa7c985 Mon Sep 17 00:00:00 2001
|
||||
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
Date: Wed, 31 Jul 2024 01:07:23 +0200
|
||||
Subject: [PATCH] ovs: fix triggering stage3 activation without DHCP client
|
||||
initialized
|
||||
|
||||
It is possible that we learn the link is ready on stage3_ip_config
|
||||
rather than in link_changed event due to a stage3_ip_config scheduled by
|
||||
another component. In such cases, we proceed with IP configuration
|
||||
without allocating the resources needed like initializing DHCP client.
|
||||
|
||||
In order to avoid that, if we learn during stage3_ip_config that the
|
||||
link is now ready, we need to schedule another stage3_ip_config to
|
||||
allocate the resources we might need.
|
||||
|
||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2004
|
||||
|
||||
Fixes: 83bf7a8cdb56 ('ovs: wait for the link to be ready before activating')
|
||||
(cherry picked from commit 40d51b91048e01f3bdfe6df1e0de7184b1ac2715)
|
||||
(cherry picked from commit 63dfd3b60b2764e652e18977b74de00b9a2a5d60)
|
||||
(cherry picked from commit f8f5626f727517d2d0140e3dc46de449877e151f)
|
||||
---
|
||||
src/core/devices/ovs/nm-device-ovs-interface.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c
|
||||
index 104b312674..a1efa5e96a 100644
|
||||
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
|
||||
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
|
||||
@@ -379,6 +379,7 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
{
|
||||
NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device);
|
||||
NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
|
||||
+ bool old_wait_link;
|
||||
|
||||
/*
|
||||
* When the ovs-interface device enters stage3, it becomes eligible to be attached to
|
||||
@@ -432,6 +433,7 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
priv->wait_link.cloned_mac_evaluated = TRUE;
|
||||
}
|
||||
|
||||
+ old_wait_link = priv->wait_link.waiting;
|
||||
priv->wait_link.waiting = TRUE;
|
||||
if (check_waiting_for_link(device, addr_family == AF_INET ? "stage3-ipv4" : "stage3-ipv6")) {
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||
@@ -450,6 +452,18 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
nm_utils_addr_family_to_char(addr_family));
|
||||
|
||||
priv->wait_link.waiting = FALSE;
|
||||
+ /*
|
||||
+ * It is possible we detect the link is ready before link_changed event does. It could happen
|
||||
+ * because another stage3_ip_config scheduled happened right after the link is ready.
|
||||
+ * Therefore, if we learn on this function that we are not waiting for the link anymore,
|
||||
+ * we schedule a sync. stage3_ip_config. Otherwise, it could happen that we proceed with
|
||||
+ * IP configuration without the needed allocated resources like DHCP client.
|
||||
+ */
|
||||
+ if (old_wait_link) {
|
||||
+ nm_device_bring_up(device);
|
||||
+ nm_device_activate_schedule_stage3_ip_config(device, TRUE);
|
||||
+ return;
|
||||
+ }
|
||||
nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
|
||||
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
|
||||
|
||||
--
|
||||
2.45.2
|
||||
|
@ -1,231 +0,0 @@
|
||||
From cf4f45af5cb23978123a991c191bf409bc237a9b Mon Sep 17 00:00:00 2001
|
||||
From: Wen Liang <liangwen12year@gmail.com>
|
||||
Date: Mon, 29 Jul 2024 14:42:05 -0400
|
||||
Subject: [PATCH 1/1] policy: unblock the autoconnect for children when parent
|
||||
is available
|
||||
|
||||
When parent is available and in the process of activation, we should
|
||||
unblock the autoconnect and schedule an auto activate for the children.
|
||||
Notice that when the parent is the ovs-interface, the kernel link is
|
||||
only created in stage3, if we only unblock the children in the stage1,
|
||||
then the children device and connection will be blocked again due
|
||||
to the fact the kernel link for the parent ovs-interface is not
|
||||
existed yet, thus, we have to separately unblock the children
|
||||
when the parent ovs-interface is in the activated state.
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-46904
|
||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2003
|
||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager-ci/-/merge_requests/1735
|
||||
(cherry picked from commit 5f64f292e6a518098f874ba9ff876e413e38a3ca)
|
||||
(cherry picked from commit 8243425c6d031c685518a74018cd39cd6c10a36b)
|
||||
(cherry picked from commit 02db74ed0bc5ac8b3c942c2c4bc61a56258cc063)
|
||||
---
|
||||
src/core/nm-policy.c | 136 +++++++++++++++++++++++++++++++++++--------
|
||||
1 file changed, 111 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c
|
||||
index feea97b114..9777cf326f 100644
|
||||
--- a/src/core/nm-policy.c
|
||||
+++ b/src/core/nm-policy.c
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "devices/nm-device.h"
|
||||
+#include "devices/nm-device-factory.h"
|
||||
#include "dns/nm-dns-manager.h"
|
||||
#include "nm-act-request.h"
|
||||
#include "nm-auth-utils.h"
|
||||
@@ -1773,6 +1774,74 @@ _connection_autoconnect_retries_set(NMPolicy *self,
|
||||
}
|
||||
}
|
||||
|
||||
+static void
|
||||
+unblock_autoconnect_for_children(NMPolicy *self,
|
||||
+ const char *parent_device,
|
||||
+ const char *parent_uuid_settings,
|
||||
+ const char *parent_uuid_applied,
|
||||
+ const char *parent_mac_addr,
|
||||
+ gboolean reset_devcon_autoconnect)
|
||||
+{
|
||||
+ NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
|
||||
+ NMSettingsConnection *const *connections;
|
||||
+ gboolean changed;
|
||||
+ guint i;
|
||||
+
|
||||
+ _LOGT(LOGD_CORE,
|
||||
+ "block-autoconnect: unblocking child profiles for parent ifname=%s%s%s, uuid=%s%s%s"
|
||||
+ "%s%s%s",
|
||||
+ NM_PRINT_FMT_QUOTE_STRING(parent_device),
|
||||
+ NM_PRINT_FMT_QUOTE_STRING(parent_uuid_settings),
|
||||
+ NM_PRINT_FMT_QUOTED(parent_uuid_applied,
|
||||
+ ", applied-uuid=\"",
|
||||
+ parent_uuid_applied,
|
||||
+ "\"",
|
||||
+ ""));
|
||||
+
|
||||
+ changed = FALSE;
|
||||
+ connections = nm_settings_get_connections(priv->settings, NULL);
|
||||
+ for (i = 0; connections[i]; i++) {
|
||||
+ NMSettingsConnection *sett_conn = connections[i];
|
||||
+ NMConnection *connection;
|
||||
+ NMDeviceFactory *factory;
|
||||
+ const char *parent_name = NULL;
|
||||
+
|
||||
+ connection = nm_settings_connection_get_connection(sett_conn);
|
||||
+ factory = nm_device_factory_manager_find_factory_for_connection(connection);
|
||||
+ if (factory)
|
||||
+ parent_name = nm_device_factory_get_connection_parent(factory, connection);
|
||||
+
|
||||
+ if (!parent_name)
|
||||
+ continue;
|
||||
+
|
||||
+ if (!NM_IN_STRSET(parent_name,
|
||||
+ parent_device,
|
||||
+ parent_uuid_applied,
|
||||
+ parent_uuid_settings,
|
||||
+ parent_mac_addr))
|
||||
+ continue;
|
||||
+
|
||||
+ if (reset_devcon_autoconnect) {
|
||||
+ if (nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn))
|
||||
+ changed = TRUE;
|
||||
+ }
|
||||
+
|
||||
+ /* unblock the devices associated with that connection */
|
||||
+ if (nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
+ priv->manager,
|
||||
+ NULL,
|
||||
+ sett_conn,
|
||||
+ NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED,
|
||||
+ FALSE)) {
|
||||
+ if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
|
||||
+ changed = TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (changed)
|
||||
+ nm_policy_device_recheck_auto_activate_all_schedule(self);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
unblock_autoconnect_for_ports(NMPolicy *self,
|
||||
const char *master_device,
|
||||
@@ -1854,16 +1923,21 @@ unblock_autoconnect_for_ports_for_sett_conn(NMPolicy *self, NMSettingsConnection
|
||||
}
|
||||
|
||||
static void
|
||||
-activate_slave_connections(NMPolicy *self, NMDevice *device)
|
||||
-{
|
||||
- const char *master_device;
|
||||
- const char *master_uuid_settings = NULL;
|
||||
- const char *master_uuid_applied = NULL;
|
||||
+activate_port_or_children_connections(NMPolicy *self,
|
||||
+ NMDevice *device,
|
||||
+ gboolean activate_children_connections_only)
|
||||
+{
|
||||
+ const char *controller_device;
|
||||
+ const char *controller_uuid_settings = NULL;
|
||||
+ const char *controller_uuid_applied = NULL;
|
||||
+ const char *parent_mac_addr = NULL;
|
||||
NMActRequest *req;
|
||||
gboolean internal_activation = FALSE;
|
||||
|
||||
- master_device = nm_device_get_iface(device);
|
||||
- nm_assert(master_device);
|
||||
+ controller_device = nm_device_get_iface(device);
|
||||
+ nm_assert(controller_device);
|
||||
+
|
||||
+ parent_mac_addr = nm_device_get_permanent_hw_address(device);
|
||||
|
||||
req = nm_device_get_act_request(device);
|
||||
if (req) {
|
||||
@@ -1873,25 +1947,33 @@ activate_slave_connections(NMPolicy *self, NMDevice *device)
|
||||
|
||||
sett_conn = nm_active_connection_get_settings_connection(NM_ACTIVE_CONNECTION(req));
|
||||
if (sett_conn)
|
||||
- master_uuid_settings = nm_settings_connection_get_uuid(sett_conn);
|
||||
+ controller_uuid_settings = nm_settings_connection_get_uuid(sett_conn);
|
||||
|
||||
connection = nm_active_connection_get_applied_connection(NM_ACTIVE_CONNECTION(req));
|
||||
if (connection)
|
||||
- master_uuid_applied = nm_connection_get_uuid(connection);
|
||||
+ controller_uuid_applied = nm_connection_get_uuid(connection);
|
||||
|
||||
- if (nm_streq0(master_uuid_settings, master_uuid_applied))
|
||||
- master_uuid_applied = NULL;
|
||||
+ if (nm_streq0(controller_uuid_settings, controller_uuid_applied))
|
||||
+ controller_uuid_applied = NULL;
|
||||
|
||||
subject = nm_active_connection_get_subject(NM_ACTIVE_CONNECTION(req));
|
||||
internal_activation =
|
||||
subject && (nm_auth_subject_get_subject_type(subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL);
|
||||
}
|
||||
|
||||
- unblock_autoconnect_for_ports(self,
|
||||
- master_device,
|
||||
- master_uuid_settings,
|
||||
- master_uuid_applied,
|
||||
- !internal_activation);
|
||||
+ if (!activate_children_connections_only) {
|
||||
+ unblock_autoconnect_for_ports(self,
|
||||
+ controller_device,
|
||||
+ controller_uuid_settings,
|
||||
+ controller_uuid_applied,
|
||||
+ !internal_activation);
|
||||
+ }
|
||||
+ unblock_autoconnect_for_children(self,
|
||||
+ controller_device,
|
||||
+ controller_uuid_settings,
|
||||
+ controller_uuid_applied,
|
||||
+ parent_mac_addr,
|
||||
+ !internal_activation);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -2059,13 +2141,12 @@ device_state_changed(NMDevice *device,
|
||||
}
|
||||
break;
|
||||
case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED:
|
||||
- /* A connection that fails due to dependency-failed is not
|
||||
- * able to reconnect until the master connection activates
|
||||
- * again; when this happens, the master clears the blocked
|
||||
- * reason for all its slaves in activate_slave_connections()
|
||||
- * and tries to reconnect them. For this to work, the slave
|
||||
- * should be marked as blocked when it fails with
|
||||
- * dependency-failed.
|
||||
+ /* A connection that fails due to dependency-failed is not able to
|
||||
+ * reconnect until the connection it depends on activates again;
|
||||
+ * when this happens, the controller or parent clears the blocked
|
||||
+ * reason for all its dependent devices in activate_port_or_children_connections()
|
||||
+ * and tries to reconnect them. For this to work, the port should
|
||||
+ * be marked as blocked when it fails with dependency-failed.
|
||||
*/
|
||||
_LOGD(LOGD_DEVICE,
|
||||
"block-autoconnect: connection[%p] (%s) now blocked from autoconnect due to "
|
||||
@@ -2109,6 +2190,11 @@ device_state_changed(NMDevice *device,
|
||||
}
|
||||
break;
|
||||
case NM_DEVICE_STATE_ACTIVATED:
|
||||
+ if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_OVS_INTERFACE) {
|
||||
+ /* When parent is ovs-interface, the kernel link is only created in stage3, we have to
|
||||
+ * delay unblocking the children and schedule them for activation until parent is activated */
|
||||
+ activate_port_or_children_connections(self, device, TRUE);
|
||||
+ }
|
||||
if (sett_conn) {
|
||||
/* Reset auto retries back to default since connection was successful */
|
||||
nm_manager_devcon_autoconnect_retries_reset(priv->manager, device, sett_conn);
|
||||
@@ -2193,9 +2279,9 @@ device_state_changed(NMDevice *device,
|
||||
break;
|
||||
|
||||
case NM_DEVICE_STATE_PREPARE:
|
||||
- /* Reset auto-connect retries of all slaves and schedule them for
|
||||
+ /* Reset auto-connect retries of all ports or children and schedule them for
|
||||
* activation. */
|
||||
- activate_slave_connections(self, device);
|
||||
+ activate_port_or_children_connections(self, device, FALSE);
|
||||
|
||||
/* Now that the device state is progressing, we don't care
|
||||
* anymore for the AC state. */
|
||||
--
|
||||
2.45.0
|
||||
|
@ -1,338 +0,0 @@
|
||||
From 0c55f0128ad17764fbe0862819fe43f32abfb27c Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Haller <thaller@redhat.com>
|
||||
Date: Fri, 31 May 2024 10:34:28 +0200
|
||||
Subject: [PATCH 1/2] lldp: fix crash dereferencing NULL pointer during debug
|
||||
logging
|
||||
|
||||
During nm_lldp_neighbor_parse(), the NMLldpNeighbor is not yet added to
|
||||
the NMLldpRX instance. Consequently, n->lldp_rx is NULL.
|
||||
|
||||
Note how we use lldp_x for logging, because we need it for the context
|
||||
for which interface the logging statement is.
|
||||
|
||||
Thus, those debug logging statements will follow a NULL pointer and lead
|
||||
to a crash.
|
||||
|
||||
Fixes: 630de288d2e4 ('lldp: add libnm-lldp as fork of systemd's sd_lldp_rx')
|
||||
|
||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1550
|
||||
(cherry picked from commit c2cddd3241349c0d5612d7603261c182fbc6d7c3)
|
||||
(cherry picked from commit 8a2f7bd6e0572cc524e6bd6e4c2893e03f98a6f0)
|
||||
(cherry picked from commit 6da9b98975ed790a9c00f57bd97e56c77ecb7673)
|
||||
---
|
||||
src/core/devices/nm-lldp-listener.c | 15 ++++++++-
|
||||
src/libnm-lldp/nm-lldp-neighbor.c | 47 +++++++++++++++--------------
|
||||
src/libnm-lldp/nm-lldp-neighbor.h | 4 ++-
|
||||
src/libnm-lldp/nm-lldp-rx.c | 2 +-
|
||||
src/libnm-lldp/nm-lldp-rx.h | 2 +-
|
||||
5 files changed, 44 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/src/core/devices/nm-lldp-listener.c b/src/core/devices/nm-lldp-listener.c
|
||||
index ac7e97f0c2..59c8f54c01 100644
|
||||
--- a/src/core/devices/nm-lldp-listener.c
|
||||
+++ b/src/core/devices/nm-lldp-listener.c
|
||||
@@ -704,9 +704,16 @@ lldp_neighbor_to_variant(LldpNeighbor *neigh)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
+static void
|
||||
+nmtst_lldp_event_handler(NMLldpRX *lldp, NMLldpRXEvent event, NMLldpNeighbor *n, void *user_data)
|
||||
+{
|
||||
+ g_assert_not_reached();
|
||||
+}
|
||||
+
|
||||
GVariant *
|
||||
nmtst_lldp_parse_from_raw(const guint8 *raw_data, gsize raw_len)
|
||||
{
|
||||
+ nm_auto(nm_lldp_rx_unrefp) NMLldpRX *lldp_rx = NULL;
|
||||
nm_auto(nm_lldp_neighbor_unrefp) NMLldpNeighbor *neighbor_nm = NULL;
|
||||
nm_auto(lldp_neighbor_freep) LldpNeighbor *neigh = NULL;
|
||||
GVariant *variant;
|
||||
@@ -714,7 +721,13 @@ nmtst_lldp_parse_from_raw(const guint8 *raw_data, gsize raw_len)
|
||||
g_assert(raw_data);
|
||||
g_assert(raw_len > 0);
|
||||
|
||||
- neighbor_nm = nm_lldp_neighbor_new_from_raw(raw_data, raw_len);
|
||||
+ lldp_rx = nm_lldp_rx_new(&((NMLldpRXConfig){
|
||||
+ .ifindex = 1,
|
||||
+ .neighbors_max = MAX_NEIGHBORS,
|
||||
+ .callback = nmtst_lldp_event_handler,
|
||||
+ }));
|
||||
+
|
||||
+ neighbor_nm = nm_lldp_neighbor_new_from_raw(lldp_rx, raw_data, raw_len);
|
||||
g_assert(neighbor_nm);
|
||||
|
||||
neigh = lldp_neighbor_new(neighbor_nm);
|
||||
diff --git a/src/libnm-lldp/nm-lldp-neighbor.c b/src/libnm-lldp/nm-lldp-neighbor.c
|
||||
index a2a9695e85..0880c02d98 100644
|
||||
--- a/src/libnm-lldp/nm-lldp-neighbor.c
|
||||
+++ b/src/libnm-lldp/nm-lldp-neighbor.c
|
||||
@@ -65,6 +65,7 @@ parse_string(NMLldpRX *lldp_rx, char **s, const void *q, size_t n)
|
||||
const char *p = q;
|
||||
char *k;
|
||||
|
||||
+ nm_assert(lldp_rx);
|
||||
nm_assert(s);
|
||||
nm_assert(p || n == 0);
|
||||
|
||||
@@ -99,31 +100,33 @@ parse_string(NMLldpRX *lldp_rx, char **s, const void *q, size_t n)
|
||||
}
|
||||
|
||||
int
|
||||
-nm_lldp_neighbor_parse(NMLldpNeighbor *n)
|
||||
+nm_lldp_neighbor_parse(NMLldpRX *lldp_rx, NMLldpNeighbor *n)
|
||||
{
|
||||
struct ether_header h;
|
||||
const uint8_t *p;
|
||||
size_t left;
|
||||
int r;
|
||||
|
||||
+ nm_assert(lldp_rx);
|
||||
nm_assert(n);
|
||||
+ nm_assert(!n->lldp_rx);
|
||||
|
||||
if (n->raw_size < sizeof(struct ether_header)) {
|
||||
- _LOG2D(n->lldp_rx, "Received truncated packet, ignoring.");
|
||||
+ _LOG2D(lldp_rx, "Received truncated packet, ignoring.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
memcpy(&h, NM_LLDP_NEIGHBOR_RAW(n), sizeof(h));
|
||||
|
||||
if (h.ether_type != htobe16(NM_ETHERTYPE_LLDP)) {
|
||||
- _LOG2D(n->lldp_rx, "Received packet with wrong type, ignoring.");
|
||||
+ _LOG2D(lldp_rx, "Received packet with wrong type, ignoring.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
if (h.ether_dhost[0] != 0x01 || h.ether_dhost[1] != 0x80 || h.ether_dhost[2] != 0xc2
|
||||
|| h.ether_dhost[3] != 0x00 || h.ether_dhost[4] != 0x00
|
||||
|| !NM_IN_SET(h.ether_dhost[5], 0x00, 0x03, 0x0e)) {
|
||||
- _LOG2D(n->lldp_rx, "Received packet with wrong destination address, ignoring.");
|
||||
+ _LOG2D(lldp_rx, "Received packet with wrong destination address, ignoring.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
@@ -138,7 +141,7 @@ nm_lldp_neighbor_parse(NMLldpNeighbor *n)
|
||||
uint16_t length;
|
||||
|
||||
if (left < 2) {
|
||||
- _LOG2D(n->lldp_rx, "TLV lacks header, ignoring.");
|
||||
+ _LOG2D(lldp_rx, "TLV lacks header, ignoring.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
@@ -147,14 +150,14 @@ nm_lldp_neighbor_parse(NMLldpNeighbor *n)
|
||||
p += 2, left -= 2;
|
||||
|
||||
if (left < length) {
|
||||
- _LOG2D(n->lldp_rx, "TLV truncated, ignoring datagram.");
|
||||
+ _LOG2D(lldp_rx, "TLV truncated, ignoring datagram.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NM_LLDP_TYPE_END:
|
||||
if (length != 0) {
|
||||
- _LOG2D(n->lldp_rx, "End marker TLV not zero-sized, ignoring datagram.");
|
||||
+ _LOG2D(lldp_rx, "End marker TLV not zero-sized, ignoring datagram.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
@@ -166,12 +169,12 @@ nm_lldp_neighbor_parse(NMLldpNeighbor *n)
|
||||
case NM_LLDP_TYPE_CHASSIS_ID:
|
||||
if (length < 2 || length > 256) {
|
||||
/* includes the chassis subtype, hence one extra byte */
|
||||
- _LOG2D(n->lldp_rx, "Chassis ID field size out of range, ignoring datagram.");
|
||||
+ _LOG2D(lldp_rx, "Chassis ID field size out of range, ignoring datagram.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
if (n->id.chassis_id) {
|
||||
- _LOG2D(n->lldp_rx, "Duplicate chassis ID field, ignoring datagram.");
|
||||
+ _LOG2D(lldp_rx, "Duplicate chassis ID field, ignoring datagram.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
@@ -182,12 +185,12 @@ nm_lldp_neighbor_parse(NMLldpNeighbor *n)
|
||||
case NM_LLDP_TYPE_PORT_ID:
|
||||
if (length < 2 || length > 256) {
|
||||
/* includes the port subtype, hence one extra byte */
|
||||
- _LOG2D(n->lldp_rx, "Port ID field size out of range, ignoring datagram.");
|
||||
+ _LOG2D(lldp_rx, "Port ID field size out of range, ignoring datagram.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
if (n->id.port_id) {
|
||||
- _LOG2D(n->lldp_rx, "Duplicate port ID field, ignoring datagram.");
|
||||
+ _LOG2D(lldp_rx, "Duplicate port ID field, ignoring datagram.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
@@ -197,12 +200,12 @@ nm_lldp_neighbor_parse(NMLldpNeighbor *n)
|
||||
|
||||
case NM_LLDP_TYPE_TTL:
|
||||
if (length != 2) {
|
||||
- _LOG2D(n->lldp_rx, "TTL field has wrong size, ignoring datagram.");
|
||||
+ _LOG2D(lldp_rx, "TTL field has wrong size, ignoring datagram.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
if (n->has_ttl) {
|
||||
- _LOG2D(n->lldp_rx, "Duplicate TTL field, ignoring datagram.");
|
||||
+ _LOG2D(lldp_rx, "Duplicate TTL field, ignoring datagram.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
@@ -211,26 +214,26 @@ nm_lldp_neighbor_parse(NMLldpNeighbor *n)
|
||||
break;
|
||||
|
||||
case NM_LLDP_TYPE_PORT_DESCRIPTION:
|
||||
- r = parse_string(n->lldp_rx, &n->port_description, p, length);
|
||||
+ r = parse_string(lldp_rx, &n->port_description, p, length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case NM_LLDP_TYPE_SYSTEM_NAME:
|
||||
- r = parse_string(n->lldp_rx, &n->system_name, p, length);
|
||||
+ r = parse_string(lldp_rx, &n->system_name, p, length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case NM_LLDP_TYPE_SYSTEM_DESCRIPTION:
|
||||
- r = parse_string(n->lldp_rx, &n->system_description, p, length);
|
||||
+ r = parse_string(lldp_rx, &n->system_description, p, length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case NM_LLDP_TYPE_SYSTEM_CAPABILITIES:
|
||||
if (length != 4) {
|
||||
- _LOG2D(n->lldp_rx, "System capabilities field has wrong size.");
|
||||
+ _LOG2D(lldp_rx, "System capabilities field has wrong size.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
@@ -241,13 +244,13 @@ nm_lldp_neighbor_parse(NMLldpNeighbor *n)
|
||||
|
||||
case NM_LLDP_TYPE_PRIVATE:
|
||||
if (length < 4) {
|
||||
- _LOG2D(n->lldp_rx, "Found private TLV that is too short, ignoring.");
|
||||
+ _LOG2D(lldp_rx, "Found private TLV that is too short, ignoring.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
/* RFC 8520: MUD URL */
|
||||
if (memcmp(p, NM_LLDP_OUI_IANA_MUD, sizeof(NM_LLDP_OUI_IANA_MUD)) == 0) {
|
||||
- r = parse_string(n->lldp_rx,
|
||||
+ r = parse_string(lldp_rx,
|
||||
&n->mud_url,
|
||||
p + sizeof(NM_LLDP_OUI_IANA_MUD),
|
||||
length - sizeof(NM_LLDP_OUI_IANA_MUD));
|
||||
@@ -262,7 +265,7 @@ nm_lldp_neighbor_parse(NMLldpNeighbor *n)
|
||||
|
||||
end_marker:
|
||||
if (!n->id.chassis_id || !n->id.port_id || !n->has_ttl) {
|
||||
- _LOG2D(n->lldp_rx, "One or more mandatory TLV missing in datagram. Ignoring.");
|
||||
+ _LOG2D(lldp_rx, "One or more mandatory TLV missing in datagram. Ignoring.");
|
||||
return -NME_UNSPEC;
|
||||
}
|
||||
|
||||
@@ -740,7 +743,7 @@ nm_lldp_neighbor_new(size_t raw_size)
|
||||
}
|
||||
|
||||
NMLldpNeighbor *
|
||||
-nm_lldp_neighbor_new_from_raw(const void *raw, size_t raw_size)
|
||||
+nm_lldp_neighbor_new_from_raw(NMLldpRX *lldp_rx, const void *raw, size_t raw_size)
|
||||
{
|
||||
nm_auto(nm_lldp_neighbor_unrefp) NMLldpNeighbor *n = NULL;
|
||||
int r;
|
||||
@@ -751,7 +754,7 @@ nm_lldp_neighbor_new_from_raw(const void *raw, size_t raw_size)
|
||||
|
||||
nm_memcpy(NM_LLDP_NEIGHBOR_RAW(n), raw, raw_size);
|
||||
|
||||
- r = nm_lldp_neighbor_parse(n);
|
||||
+ r = nm_lldp_neighbor_parse(lldp_rx, n);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
diff --git a/src/libnm-lldp/nm-lldp-neighbor.h b/src/libnm-lldp/nm-lldp-neighbor.h
|
||||
index 1adc967e7e..038591a066 100644
|
||||
--- a/src/libnm-lldp/nm-lldp-neighbor.h
|
||||
+++ b/src/libnm-lldp/nm-lldp-neighbor.h
|
||||
@@ -75,11 +75,13 @@ NM_LLDP_NEIGHBOR_TLV_DATA(const NMLldpNeighbor *n)
|
||||
return ((uint8_t *) NM_LLDP_NEIGHBOR_RAW(n)) + n->rindex + 2;
|
||||
}
|
||||
|
||||
+struct _NMLldpRX;
|
||||
+
|
||||
int nm_lldp_neighbor_prioq_compare_func(const void *a, const void *b);
|
||||
|
||||
void nm_lldp_neighbor_unlink(NMLldpNeighbor *n);
|
||||
NMLldpNeighbor *nm_lldp_neighbor_new(size_t raw_size);
|
||||
-int nm_lldp_neighbor_parse(NMLldpNeighbor *n);
|
||||
+int nm_lldp_neighbor_parse(struct _NMLldpRX *lldp_rx, NMLldpNeighbor *n);
|
||||
void nm_lldp_neighbor_start_ttl(NMLldpNeighbor *n);
|
||||
|
||||
#endif /* __NM_LLDP_NEIGHBOR_H__ */
|
||||
diff --git a/src/libnm-lldp/nm-lldp-rx.c b/src/libnm-lldp/nm-lldp-rx.c
|
||||
index 345c6d5661..90414b3ee7 100644
|
||||
--- a/src/libnm-lldp/nm-lldp-rx.c
|
||||
+++ b/src/libnm-lldp/nm-lldp-rx.c
|
||||
@@ -255,7 +255,7 @@ lldp_rx_receive_datagram(int fd, GIOCondition condition, gpointer user_data)
|
||||
} else
|
||||
n->timestamp_usec = nm_utils_get_monotonic_timestamp_usec();
|
||||
|
||||
- r = nm_lldp_neighbor_parse(n);
|
||||
+ r = nm_lldp_neighbor_parse(lldp_rx, n);
|
||||
if (r < 0) {
|
||||
_LOG2D(lldp_rx, "Failure parsing invalid LLDP datagram.");
|
||||
return G_SOURCE_CONTINUE;
|
||||
diff --git a/src/libnm-lldp/nm-lldp-rx.h b/src/libnm-lldp/nm-lldp-rx.h
|
||||
index a3f3805376..d96ffcd888 100644
|
||||
--- a/src/libnm-lldp/nm-lldp-rx.h
|
||||
+++ b/src/libnm-lldp/nm-lldp-rx.h
|
||||
@@ -68,7 +68,7 @@ NMLldpNeighbor **nm_lldp_rx_get_neighbors(NMLldpRX *lldp_rx, guint *out_len);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
-NMLldpNeighbor *nm_lldp_neighbor_new_from_raw(const void *raw, size_t raw_size);
|
||||
+NMLldpNeighbor *nm_lldp_neighbor_new_from_raw(NMLldpRX *lldp_rx, const void *raw, size_t raw_size);
|
||||
|
||||
NMLldpNeighbor *nm_lldp_neighbor_ref(NMLldpNeighbor *n);
|
||||
NMLldpNeighbor *nm_lldp_neighbor_unref(NMLldpNeighbor *n);
|
||||
--
|
||||
2.46.0
|
||||
|
||||
|
||||
From 36b12bf4f96ed03dd07740070eaf183edf94b5dc Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Haller <thaller@redhat.com>
|
||||
Date: Fri, 31 May 2024 10:49:50 +0200
|
||||
Subject: [PATCH 2/2] lldp: fix multiple access to argument in logging macro
|
||||
|
||||
Fixes: 630de288d2e4 ('lldp: add libnm-lldp as fork of systemd's sd_lldp_rx')
|
||||
(cherry picked from commit 4365de5226aa80c01181a11988a731913e97b264)
|
||||
(cherry picked from commit a1c18ce20d826763db9b175addb36e691e45fda9)
|
||||
(cherry picked from commit 9905bcdcb73d12bb4a95b117e5efd5a9e168dcf4)
|
||||
---
|
||||
src/libnm-lldp/nm-lldp-rx-internal.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/libnm-lldp/nm-lldp-rx-internal.h b/src/libnm-lldp/nm-lldp-rx-internal.h
|
||||
index 47d063ae70..1296a9d33f 100644
|
||||
--- a/src/libnm-lldp/nm-lldp-rx-internal.h
|
||||
+++ b/src/libnm-lldp/nm-lldp-rx-internal.h
|
||||
@@ -34,7 +34,7 @@ struct _NMLldpRX {
|
||||
NMLldpRX *_lldp_rx = (lldp_rx); \
|
||||
\
|
||||
if (_NMLOG2_ENABLED(_level)) { \
|
||||
- _nm_log(level, \
|
||||
+ _nm_log(_level, \
|
||||
_NMLOG2_DOMAIN, \
|
||||
0, \
|
||||
_lldp_rx->config.log_ifname, \
|
||||
--
|
||||
2.46.0
|
||||
|
@ -1,267 +0,0 @@
|
||||
From 2e88b3f69f552cb91057527de2acd6d8c95fb51d Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Wed, 19 Jun 2024 20:14:14 +0200
|
||||
Subject: [PATCH 1/2] nm-daemon-helper: add "service" argument
|
||||
|
||||
Introduce a new argument to specify a comma-separated list of NSS
|
||||
services to use for the "resolve-address" command. For now only accept
|
||||
"dns" and "files"; the latter can be used to do a lookup into
|
||||
/etc/hosts.
|
||||
|
||||
Note that previously the command failed in presence of extra
|
||||
arguments. Therefore, when downgrading NetworkManager without
|
||||
restarting the service, the previously-installed version of the daemon
|
||||
(newer) would spawn the helper with the extra argument, and the
|
||||
newly-installed version of the helper (older) would fail. This issue
|
||||
only impacts hostname resolution and can be fixed by just restarting
|
||||
the daemon.
|
||||
|
||||
In the upgrade path everything works as before, with the only
|
||||
difference that the helper will use by default both "dns" and "files"
|
||||
services.
|
||||
|
||||
Don't strictly check for the absence of extra arguments, so that in
|
||||
the future we can introduce more arguments without necessarily break
|
||||
the downgrade path.
|
||||
|
||||
(cherry picked from commit 229bebfae95f789018433900868700c16a20a17b)
|
||||
(cherry picked from commit c36a74f698cc31fba20d9fd0a74d5cf74b832071)
|
||||
(cherry picked from commit e86ddd9fc590e3b4462464c0562ab115f654f5d1)
|
||||
---
|
||||
src/nm-daemon-helper/nm-daemon-helper.c | 67 +++++++++++++++++--------
|
||||
1 file changed, 45 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/nm-daemon-helper/nm-daemon-helper.c b/src/nm-daemon-helper/nm-daemon-helper.c
|
||||
index 810ea5fa94..32be93a4ef 100644
|
||||
--- a/src/nm-daemon-helper/nm-daemon-helper.c
|
||||
+++ b/src/nm-daemon-helper/nm-daemon-helper.c
|
||||
@@ -55,26 +55,31 @@ cmd_version(void)
|
||||
static int
|
||||
cmd_resolve_address(void)
|
||||
{
|
||||
- nm_auto_free char *address = NULL;
|
||||
+ nm_auto_free char *address = NULL;
|
||||
+ nm_auto_free char *services = NULL;
|
||||
union {
|
||||
struct sockaddr_in in;
|
||||
struct sockaddr_in6 in6;
|
||||
} sockaddr;
|
||||
socklen_t sockaddr_size;
|
||||
char name[NI_MAXHOST];
|
||||
+ char *saveptr = NULL;
|
||||
+ char *service;
|
||||
+ char *str;
|
||||
int ret;
|
||||
|
||||
address = read_arg();
|
||||
if (!address)
|
||||
return RETURN_INVALID_ARGS;
|
||||
|
||||
- if (more_args())
|
||||
- return RETURN_INVALID_ARGS;
|
||||
+ services = read_arg();
|
||||
+ if (!services) {
|
||||
+ /* Called by an old NM version which doesn't support the 'services'
|
||||
+ * argument. Use both services. */
|
||||
+ services = strdup("dns,files");
|
||||
+ }
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
-#if defined(__GLIBC__)
|
||||
- __nss_configure_lookup("hosts", "dns");
|
||||
-#endif
|
||||
|
||||
if (inet_pton(AF_INET, address, &sockaddr.in.sin_addr) == 1) {
|
||||
sockaddr.in.sin_family = AF_INET;
|
||||
@@ -85,33 +90,51 @@ cmd_resolve_address(void)
|
||||
} else
|
||||
return RETURN_INVALID_ARGS;
|
||||
|
||||
- ret = getnameinfo((struct sockaddr *) &sockaddr,
|
||||
- sockaddr_size,
|
||||
- name,
|
||||
- sizeof(name),
|
||||
- NULL,
|
||||
- 0,
|
||||
- NI_NAMEREQD);
|
||||
- if (ret != 0) {
|
||||
- if (ret == EAI_SYSTEM) {
|
||||
- int errsv = errno;
|
||||
+ for (str = services; (service = strtok_r(str, ",", &saveptr)); str = NULL) {
|
||||
+ if (!NM_IN_STRSET(service, "dns", "files")) {
|
||||
+ fprintf(stderr, "Unsupported resolver service '%s'\n", service);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+#if defined(__GLIBC__)
|
||||
+ __nss_configure_lookup("hosts", service);
|
||||
+#endif
|
||||
+
|
||||
+ ret = getnameinfo((struct sockaddr *) &sockaddr,
|
||||
+ sockaddr_size,
|
||||
+ name,
|
||||
+ sizeof(name),
|
||||
+ NULL,
|
||||
+ 0,
|
||||
+ NI_NAMEREQD);
|
||||
+
|
||||
+ if (ret == 0) {
|
||||
+ printf("%s", name);
|
||||
+ return RETURN_SUCCESS;
|
||||
+ } else if (ret == EAI_SYSTEM) {
|
||||
char buf[1024];
|
||||
+ int errsv = errno;
|
||||
|
||||
fprintf(stderr,
|
||||
- "getnameinfo() failed: %d (%s), system error: %d (%s)\n",
|
||||
+ "getnameinfo() via service '%s' failed: %d (%s), system error: %d (%s)\n",
|
||||
+ service,
|
||||
ret,
|
||||
gai_strerror(ret),
|
||||
errsv,
|
||||
_nm_strerror_r(errsv, buf, sizeof(buf)));
|
||||
} else {
|
||||
- fprintf(stderr, "getnameinfo() failed: %d (%s)\n", ret, gai_strerror(ret));
|
||||
+ fprintf(stderr,
|
||||
+ "getnameinfo() via service '%s' failed: %d (%s)\n",
|
||||
+ service,
|
||||
+ ret,
|
||||
+ gai_strerror(ret));
|
||||
}
|
||||
- return RETURN_ERROR;
|
||||
+#if !defined(__GLIBC__)
|
||||
+ break;
|
||||
+#endif
|
||||
}
|
||||
|
||||
- printf("%s", name);
|
||||
-
|
||||
- return RETURN_SUCCESS;
|
||||
+ return RETURN_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
--
|
||||
2.46.0
|
||||
|
||||
|
||||
From 824ab3b1033c5693cca6add3c6e15b2c8789a7df Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Wed, 19 Jun 2024 20:29:37 +0200
|
||||
Subject: [PATCH 2/2] core: also use /etc/hosts for hostname resolution
|
||||
|
||||
Before introducing the hostname lookup via nm-daemon-helper and
|
||||
systemd-resolved, we used GLib's GResolver which internally relies on
|
||||
the libc resolver and generally also returns results from /etc/hosts.
|
||||
|
||||
With the new mechanism we only ask to systemd-resolved (with
|
||||
NO_SYNTHESIZE) or perform the lookup via the "dns" NSS module. In both
|
||||
ways, /etc/hosts is not evaluated.
|
||||
|
||||
Since users relied on having the hostname resolved via /etc/hosts,
|
||||
restore that behavior. Now, after trying the resolution via
|
||||
systemd-resolved and the "dns" NSS module, we also try via the "files"
|
||||
NSS module which reads /etc/hosts.
|
||||
|
||||
Fixes: 27eae4043b27 ('device: add a nm_device_resolve_address()')
|
||||
(cherry picked from commit 410afccb32f5814c6aeebec837505e3f94b7408c)
|
||||
(cherry picked from commit cb54fe7ce9a69b1f8abfd6fa5f2bf83e971ff997)
|
||||
(cherry picked from commit e3861be84505d795c34347af84bbf73dc4196586)
|
||||
---
|
||||
src/core/devices/nm-device-utils.c | 49 ++++++++++++++++++++++--------
|
||||
1 file changed, 36 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/core/devices/nm-device-utils.c b/src/core/devices/nm-device-utils.c
|
||||
index ed0a27382a..75423528c5 100644
|
||||
--- a/src/core/devices/nm-device-utils.c
|
||||
+++ b/src/core/devices/nm-device-utils.c
|
||||
@@ -233,14 +233,36 @@ resolve_addr_helper_cb(GObject *source, GAsyncResult *result, gpointer user_data
|
||||
resolve_addr_complete(info, g_steal_pointer(&output), g_steal_pointer(&error));
|
||||
}
|
||||
|
||||
+typedef enum {
|
||||
+ RESOLVE_ADDR_SERVICE_NONE = 0x0,
|
||||
+ RESOLVE_ADDR_SERVICE_DNS = 0x1,
|
||||
+ RESOLVE_ADDR_SERVICE_FILES = 0x2,
|
||||
+} ResolveAddrService;
|
||||
+
|
||||
static void
|
||||
-resolve_addr_spawn_helper(ResolveAddrInfo *info)
|
||||
+resolve_addr_spawn_helper(ResolveAddrInfo *info, ResolveAddrService services)
|
||||
{
|
||||
- char addr_str[NM_INET_ADDRSTRLEN];
|
||||
+ char addr_str[NM_INET_ADDRSTRLEN];
|
||||
+ char str[256];
|
||||
+ char *s = str;
|
||||
+ gsize len = sizeof(str);
|
||||
+ gboolean comma = FALSE;
|
||||
+
|
||||
+ nm_assert(services != RESOLVE_ADDR_SERVICE_NONE);
|
||||
+ nm_assert((services & ~(RESOLVE_ADDR_SERVICE_DNS | RESOLVE_ADDR_SERVICE_FILES)) == 0);
|
||||
+
|
||||
+ if (services & RESOLVE_ADDR_SERVICE_DNS) {
|
||||
+ nm_strbuf_append(&s, &len, "%sdns", comma ? "," : "");
|
||||
+ comma = TRUE;
|
||||
+ }
|
||||
+ if (services & RESOLVE_ADDR_SERVICE_FILES) {
|
||||
+ nm_strbuf_append(&s, &len, "%sfiles", comma ? "," : "");
|
||||
+ comma = TRUE;
|
||||
+ }
|
||||
|
||||
nm_inet_ntop(info->addr_family, &info->address, addr_str);
|
||||
- _LOG2D(info, "start lookup via nm-daemon-helper");
|
||||
- nm_utils_spawn_helper(NM_MAKE_STRV("resolve-address", addr_str),
|
||||
+ _LOG2D(info, "start lookup via nm-daemon-helper using services: %s", str);
|
||||
+ nm_utils_spawn_helper(NM_MAKE_STRV("resolve-address", addr_str, str),
|
||||
g_task_get_cancellable(info->task),
|
||||
resolve_addr_helper_cb,
|
||||
info);
|
||||
@@ -270,27 +292,28 @@ resolve_addr_resolved_cb(NMDnsSystemdResolved *resolved,
|
||||
dbus_error = g_dbus_error_get_remote_error(error);
|
||||
if (NM_STR_HAS_PREFIX(dbus_error, "org.freedesktop.resolve1.")) {
|
||||
/* systemd-resolved is enabled but it couldn't resolve the
|
||||
- * address via DNS. Don't fall back to spawning the helper,
|
||||
- * because the helper will possibly ask again to
|
||||
+ * address via DNS. Spawn again the helper to check if we
|
||||
+ * can find a result in /etc/hosts. Don't enable the 'dns'
|
||||
+ * service otherwise the helper will possibly ask again to
|
||||
* systemd-resolved (via /etc/resolv.conf), potentially using
|
||||
* other protocols than DNS or returning synthetic results.
|
||||
*
|
||||
- * Consider the error as the final indication that the address
|
||||
- * can't be resolved.
|
||||
- *
|
||||
* See: https://www.freedesktop.org/wiki/Software/systemd/resolved/#commonerrors
|
||||
*/
|
||||
- resolve_addr_complete(info, NULL, g_error_copy(error));
|
||||
+ resolve_addr_spawn_helper(info, RESOLVE_ADDR_SERVICE_FILES);
|
||||
return;
|
||||
}
|
||||
|
||||
- resolve_addr_spawn_helper(info);
|
||||
+ /* systemd-resolved couldn't be contacted, use the helper */
|
||||
+ resolve_addr_spawn_helper(info, RESOLVE_ADDR_SERVICE_DNS | RESOLVE_ADDR_SERVICE_FILES);
|
||||
return;
|
||||
}
|
||||
|
||||
if (names_len == 0) {
|
||||
_LOG2D(info, "systemd-resolved returned no result");
|
||||
- resolve_addr_complete(info, g_strdup(""), NULL);
|
||||
+ /* We passed the NO_SYNTHESIZE flag and so systemd-resolved
|
||||
+ * didn't look into /etc/hosts. Spawn the helper for that. */
|
||||
+ resolve_addr_spawn_helper(info, RESOLVE_ADDR_SERVICE_FILES);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -354,7 +377,7 @@ nm_device_resolve_address(int addr_family,
|
||||
return;
|
||||
}
|
||||
|
||||
- resolve_addr_spawn_helper(info);
|
||||
+ resolve_addr_spawn_helper(info, RESOLVE_ADDR_SERVICE_DNS | RESOLVE_ADDR_SERVICE_FILES);
|
||||
}
|
||||
|
||||
char *
|
||||
--
|
||||
2.46.0
|
||||
|
@ -1,338 +0,0 @@
|
||||
From 8f5767448c3d1ab3748d1d4db98286254f7ad241 Mon Sep 17 00:00:00 2001
|
||||
From: Beniamino Galvani <bgalvani@redhat.com>
|
||||
Date: Wed, 31 Jul 2024 17:08:43 +0200
|
||||
Subject: [PATCH] policy: retry hostname resolution when it fails
|
||||
|
||||
Currently if the system hostname can't be determined, NetworkManager
|
||||
only retries when something changes: a new address is added, the DHCP
|
||||
lease changes, etc.
|
||||
|
||||
However, it might happen that the current failure in looking up the
|
||||
hostname is caused by an external factor, like a temporary outage of
|
||||
the DNS server.
|
||||
|
||||
Add a mechanism to retry the resolution with an increasing timeout.
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-17972
|
||||
(cherry picked from commit 04ad4c86d0e943b1f39d059aafa0c690708293e8)
|
||||
(cherry picked from commit 3555dbd2f2177fe9db9c016431e284d88e08d7cd)
|
||||
(cherry picked from commit 7ae0f3edf06fffee0c642b09741c5df867c5bb10)
|
||||
---
|
||||
src/core/nm-policy.c | 139 ++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 117 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c
|
||||
index 9777cf326f..db588db7d6 100644
|
||||
--- a/src/core/nm-policy.c
|
||||
+++ b/src/core/nm-policy.c
|
||||
@@ -48,6 +48,10 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMPolicy,
|
||||
PROP_ACTIVATING_IP4_AC,
|
||||
PROP_ACTIVATING_IP6_AC, );
|
||||
|
||||
+#define HOSTNAME_RETRY_INTERVAL_MIN 30U
|
||||
+#define HOSTNAME_RETRY_INTERVAL_MAX (60U * 60 * 12) /* 12 hours */
|
||||
+#define HOSTNAME_RETRY_INTERVAL_MULTIPLIER 8U
|
||||
+
|
||||
typedef struct {
|
||||
NMManager *manager;
|
||||
NMNetns *netns;
|
||||
@@ -79,14 +83,21 @@ typedef struct {
|
||||
char *orig_hostname; /* hostname at NM start time */
|
||||
char *cur_hostname; /* hostname we want to assign */
|
||||
char *cur_hostname_full; /* similar to @last_hostname, but before shortening */
|
||||
- char *
|
||||
- last_hostname; /* last hostname NM set (to detect if someone else changed it in the meanwhile) */
|
||||
+ char *last_hostname; /* last hostname NM set (to detect if someone else
|
||||
+ * changed it in the meanwhile) */
|
||||
+ struct {
|
||||
+ GSource *source;
|
||||
+ guint interval_sec;
|
||||
+ gboolean do_restart; /* when something changes, set this to TRUE so that the next retry
|
||||
+ * will restart from the lowest timeout. */
|
||||
+ } hostname_retry;
|
||||
|
||||
bool changing_hostname : 1; /* hostname set operation in progress */
|
||||
bool dhcp_hostname : 1; /* current hostname was set from dhcp */
|
||||
bool updating_dns : 1;
|
||||
|
||||
GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */
|
||||
+
|
||||
} NMPolicyPrivate;
|
||||
|
||||
struct _NMPolicy {
|
||||
@@ -135,9 +146,10 @@ _PRIV_TO_SELF(NMPolicyPrivate *priv)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
-static void update_system_hostname(NMPolicy *self, const char *msg);
|
||||
-static void nm_policy_device_recheck_auto_activate_all_schedule(NMPolicy *self);
|
||||
+static void update_system_hostname(NMPolicy *self, const char *msg, gboolean reset_retry_interval);
|
||||
+static void nm_policy_device_recheck_auto_activate_all_schedule(NMPolicy *self);
|
||||
static NMDevice *get_default_device(NMPolicy *self, int addr_family);
|
||||
+static gboolean hostname_retry_cb(gpointer user_data);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -558,7 +570,56 @@ _get_hostname(NMPolicy *self)
|
||||
}
|
||||
|
||||
static void
|
||||
-_set_hostname(NMPolicy *self, const char *new_hostname, const char *msg)
|
||||
+hostname_retry_schedule(NMPolicy *self)
|
||||
+{
|
||||
+ NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
|
||||
+
|
||||
+ if (priv->hostname_retry.source && !priv->hostname_retry.do_restart)
|
||||
+ return;
|
||||
+
|
||||
+ nm_clear_g_source_inst(&priv->hostname_retry.source);
|
||||
+
|
||||
+ if (priv->hostname_retry.do_restart)
|
||||
+ priv->hostname_retry.interval_sec = 0;
|
||||
+
|
||||
+ priv->hostname_retry.interval_sec *= HOSTNAME_RETRY_INTERVAL_MULTIPLIER;
|
||||
+ priv->hostname_retry.interval_sec = NM_CLAMP(priv->hostname_retry.interval_sec,
|
||||
+ HOSTNAME_RETRY_INTERVAL_MIN,
|
||||
+ HOSTNAME_RETRY_INTERVAL_MAX);
|
||||
+
|
||||
+ _LOGT(LOGD_DNS,
|
||||
+ "hostname-retry: schedule in %u seconds%s",
|
||||
+ priv->hostname_retry.interval_sec,
|
||||
+ priv->hostname_retry.do_restart ? " (restarted)" : "");
|
||||
+ priv->hostname_retry.source =
|
||||
+ nm_g_timeout_add_seconds_source(priv->hostname_retry.interval_sec, hostname_retry_cb, self);
|
||||
+
|
||||
+ priv->hostname_retry.do_restart = FALSE;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+hostname_retry_cb(gpointer user_data)
|
||||
+{
|
||||
+ NMPolicy *self = NM_POLICY(user_data);
|
||||
+ NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
|
||||
+ const CList *tmp_lst;
|
||||
+ NMDevice *device;
|
||||
+
|
||||
+ _LOGT(LOGD_DNS, "hostname-retry: timeout");
|
||||
+
|
||||
+ nm_clear_g_source_inst(&priv->hostname_retry.source);
|
||||
+
|
||||
+ /* Clear any cached DNS results before retrying */
|
||||
+ nm_manager_for_each_device (priv->manager, device, tmp_lst) {
|
||||
+ nm_device_clear_dns_lookup_data(device, "hostname retry timeout");
|
||||
+ }
|
||||
+ update_system_hostname(self, "hostname retry timeout", FALSE);
|
||||
+
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+_set_hostname(NMPolicy *self, const char *new_hostname, const char *msg, gboolean do_retry)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
|
||||
gs_free char *old_hostname = NULL;
|
||||
@@ -612,6 +673,15 @@ _set_hostname(NMPolicy *self, const char *new_hostname, const char *msg)
|
||||
priv->updating_dns = FALSE;
|
||||
}
|
||||
|
||||
+ if (!do_retry) {
|
||||
+ _LOGT(LOGD_DNS, "hostname-retry: clear");
|
||||
+ nm_clear_g_source_inst(&priv->hostname_retry.source);
|
||||
+ priv->hostname_retry.interval_sec = 0;
|
||||
+ priv->hostname_retry.do_restart = FALSE;
|
||||
+ } else if (!priv->hostname_retry.source) {
|
||||
+ hostname_retry_schedule(self);
|
||||
+ }
|
||||
+
|
||||
/* Finally, set kernel hostname */
|
||||
nm_assert(!priv->cur_hostname || priv->cur_hostname[0]);
|
||||
name = priv->cur_hostname ?: FALLBACK_HOSTNAME4;
|
||||
@@ -797,7 +867,7 @@ device_dns_lookup_done(NMDevice *device, gpointer user_data)
|
||||
|
||||
g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self);
|
||||
|
||||
- update_system_hostname(self, "lookup finished");
|
||||
+ update_system_hostname(self, "lookup finished", FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -810,12 +880,28 @@ device_carrier_changed(NMDevice *device, GParamSpec *pspec, gpointer user_data)
|
||||
if (nm_device_has_carrier(device)) {
|
||||
g_signal_handlers_disconnect_by_func(device, device_carrier_changed, priv);
|
||||
msg = g_strdup_printf("device '%s' got carrier", nm_device_get_iface(device));
|
||||
- update_system_hostname(self, msg);
|
||||
+ update_system_hostname(self, msg, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * This function evaluates different sources (static configuration, DHCP, DNS, ...)
|
||||
+ * to set the system hostname.
|
||||
+ *
|
||||
+ * When the function needs to perform a blocking action like a DNS resolution, it
|
||||
+ * subscribes to a signal for the completion event, registering a callback that
|
||||
+ * invokes this function again. In the new invocation, any previous DNS result is
|
||||
+ * cached and doesn't need a new resolution.
|
||||
+ *
|
||||
+ * In case no hostname is found when after sources have been evaluated, it schedules
|
||||
+ * a timer to retry later with an interval that is increased at each attempt. When
|
||||
+ * this function is called after something changed (for example, carrier went up, a
|
||||
+ * new address was added), @reset_retry_interval should be set to TRUE so that the
|
||||
+ * next retry will use the smallest interval. In this way, it can quickly adapt to
|
||||
+ * temporary misconfigurations at boot or when the network environment changes.
|
||||
+ */
|
||||
static void
|
||||
-update_system_hostname(NMPolicy *self, const char *msg)
|
||||
+update_system_hostname(NMPolicy *self, const char *msg, gboolean reset_retry_interval)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
|
||||
const char *configured_hostname;
|
||||
@@ -830,6 +916,9 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||
|
||||
g_return_if_fail(self != NULL);
|
||||
|
||||
+ if (reset_retry_interval)
|
||||
+ priv->hostname_retry.do_restart = TRUE;
|
||||
+
|
||||
if (priv->hostname_mode == NM_POLICY_HOSTNAME_MODE_NONE) {
|
||||
_LOGT(LOGD_DNS, "set-hostname: hostname is unmanaged");
|
||||
return;
|
||||
@@ -872,7 +961,7 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||
/* Try a persistent hostname first */
|
||||
configured_hostname = nm_hostname_manager_get_static_hostname(priv->hostname_manager);
|
||||
if (configured_hostname && nm_utils_is_specific_hostname(configured_hostname)) {
|
||||
- _set_hostname(self, configured_hostname, "from system configuration");
|
||||
+ _set_hostname(self, configured_hostname, "from system configuration", FALSE);
|
||||
priv->dhcp_hostname = FALSE;
|
||||
return;
|
||||
}
|
||||
@@ -909,7 +998,10 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||
if (dhcp_hostname && dhcp_hostname[0]) {
|
||||
p = nm_str_skip_leading_spaces(dhcp_hostname);
|
||||
if (p[0]) {
|
||||
- _set_hostname(self, p, info->IS_IPv4 ? "from DHCPv4" : "from DHCPv6");
|
||||
+ _set_hostname(self,
|
||||
+ p,
|
||||
+ info->IS_IPv4 ? "from DHCPv4" : "from DHCPv6",
|
||||
+ FALSE);
|
||||
priv->dhcp_hostname = TRUE;
|
||||
return;
|
||||
}
|
||||
@@ -937,7 +1029,7 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||
priv);
|
||||
}
|
||||
if (result) {
|
||||
- _set_hostname(self, result, "from address lookup");
|
||||
+ _set_hostname(self, result, "from address lookup", FALSE);
|
||||
return;
|
||||
}
|
||||
if (wait) {
|
||||
@@ -952,8 +1044,10 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||
}
|
||||
|
||||
/* If an hostname was set outside NetworkManager keep it */
|
||||
- if (external_hostname)
|
||||
+ if (external_hostname) {
|
||||
+ hostname_retry_schedule(self);
|
||||
return;
|
||||
+ }
|
||||
|
||||
if (priv->hostname_mode == NM_POLICY_HOSTNAME_MODE_DHCP) {
|
||||
/* In dhcp hostname-mode, the hostname is updated only if it comes from
|
||||
@@ -962,7 +1056,7 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||
* so reset the hostname to the previous value
|
||||
*/
|
||||
if (priv->dhcp_hostname) {
|
||||
- _set_hostname(self, priv->orig_hostname, "reset dhcp hostname");
|
||||
+ _set_hostname(self, priv->orig_hostname, "reset dhcp hostname", TRUE);
|
||||
priv->dhcp_hostname = FALSE;
|
||||
}
|
||||
return;
|
||||
@@ -974,11 +1068,11 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||
* set externally to NM
|
||||
*/
|
||||
if (priv->orig_hostname) {
|
||||
- _set_hostname(self, priv->orig_hostname, "from system startup");
|
||||
+ _set_hostname(self, priv->orig_hostname, "from system startup", TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
- _set_hostname(self, NULL, "no hostname found");
|
||||
+ _set_hostname(self, NULL, "no hostname found", TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1255,7 +1349,7 @@ update_routing_and_dns(NMPolicy *self, gboolean force_update, NMDevice *changed_
|
||||
update_ip6_routing(self, force_update);
|
||||
|
||||
/* Update the system hostname */
|
||||
- update_system_hostname(self, "routing and dns");
|
||||
+ update_system_hostname(self, "routing and dns", FALSE);
|
||||
|
||||
nm_dns_manager_end_updates(priv->dns_manager, __func__);
|
||||
}
|
||||
@@ -1572,7 +1666,7 @@ _static_hostname_changed_cb(NMHostnameManager *hostname_manager,
|
||||
NMPolicyPrivate *priv = user_data;
|
||||
NMPolicy *self = _PRIV_TO_SELF(priv);
|
||||
|
||||
- update_system_hostname(self, "hostname changed");
|
||||
+ update_system_hostname(self, "hostname changed", FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2217,7 +2311,7 @@ device_state_changed(NMDevice *device,
|
||||
update_ip_dns(self, AF_INET6, device);
|
||||
update_ip4_routing(self, TRUE);
|
||||
update_ip6_routing(self, TRUE);
|
||||
- update_system_hostname(self, "routing and dns");
|
||||
+ update_system_hostname(self, "routing and dns", TRUE);
|
||||
nm_dns_manager_end_updates(priv->dns_manager, __func__);
|
||||
|
||||
break;
|
||||
@@ -2365,7 +2459,7 @@ device_l3cd_changed(NMDevice *device,
|
||||
update_ip6_routing(self, TRUE);
|
||||
/* FIXME: since we already monitor platform addresses changes,
|
||||
* this is probably no longer necessary? */
|
||||
- update_system_hostname(self, "ip conf");
|
||||
+ update_system_hostname(self, "ip conf", FALSE);
|
||||
} else {
|
||||
nm_dns_manager_set_ip_config(priv->dns_manager,
|
||||
AF_UNSPEC,
|
||||
@@ -2387,7 +2481,7 @@ device_platform_address_changed(NMDevice *device, gpointer user_data)
|
||||
|
||||
state = nm_device_get_state(device);
|
||||
if (state > NM_DEVICE_STATE_DISCONNECTED && state < NM_DEVICE_STATE_DEACTIVATING) {
|
||||
- update_system_hostname(self, "address changed");
|
||||
+ update_system_hostname(self, "address changed", TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2726,7 +2820,7 @@ dns_config_changed(NMDnsManager *dns_manager, gpointer user_data)
|
||||
nm_device_clear_dns_lookup_data(device, "DNS configuration changed");
|
||||
}
|
||||
|
||||
- update_system_hostname(self, "DNS configuration changed");
|
||||
+ update_system_hostname(self, "DNS configuration changed", FALSE);
|
||||
}
|
||||
|
||||
nm_dispatcher_call_dns_change();
|
||||
@@ -2997,7 +3091,7 @@ constructed(GObject *object)
|
||||
G_OBJECT_CLASS(nm_policy_parent_class)->constructed(object);
|
||||
|
||||
_LOGD(LOGD_DNS, "hostname-mode: %s", _hostname_mode_to_string(priv->hostname_mode));
|
||||
- update_system_hostname(self, "initial hostname");
|
||||
+ update_system_hostname(self, "initial hostname", FALSE);
|
||||
}
|
||||
|
||||
NMPolicy *
|
||||
@@ -3055,6 +3149,7 @@ dispose(GObject *object)
|
||||
|
||||
nm_clear_g_source_inst(&priv->reset_connections_retries_idle_source);
|
||||
nm_clear_g_source_inst(&priv->device_recheck_auto_activate_all_idle_source);
|
||||
+ nm_clear_g_source_inst(&priv->hostname_retry.source);
|
||||
|
||||
nm_clear_g_free(&priv->orig_hostname);
|
||||
nm_clear_g_free(&priv->cur_hostname);
|
||||
--
|
||||
2.46.0
|
||||
|
Loading…
Reference in new issue