import NetworkManager-1.48.10-2.el9_5

i9c changed/i9c/NetworkManager-1.48.10-2.el9_5
MSVSphere Packaging Team 1 month ago
parent 7383cd1c4c
commit c2a779fbed
Signed by: sys_gitsync
GPG Key ID: B2B0B9F29E528FE8

@ -1 +1 @@
3c11d700a2e81a7abce285ab94d015ac966f59d3 SOURCES/NetworkManager-1.46.0.tar.xz 6423adef5f4bb2c0cc20c2173e03a7ac8b8565ca SOURCES/NetworkManager-1.48.10.tar.xz

2
.gitignore vendored

@ -1 +1 @@
SOURCES/NetworkManager-1.46.0.tar.xz SOURCES/NetworkManager-1.48.10.tar.xz

@ -1,4 +1,4 @@
From 6016ef0813a6c048369cc27ae85fc12699bacab5 Mon Sep 17 00:00:00 2001 From 065584036f8072c994a8bdab210bcfd0ff483960 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk> From: Lubomir Rintel <lkundrak@v3.sk>
Date: Tue, 27 Aug 2024 00:29:17 +0200 Date: Tue, 27 Aug 2024 00:29:17 +0200
Subject: [PATCH] cloud-setup: allow bigger restart bursts Subject: [PATCH] cloud-setup: allow bigger restart bursts
@ -14,13 +14,12 @@ interfere on a chance things really go awry.
https://issues.redhat.com/browse/RHEL-49694 https://issues.redhat.com/browse/RHEL-49694
(cherry picked from commit 927cff9f178911b2a146259a89bfcc9727cbd8c3) (cherry picked from commit 927cff9f178911b2a146259a89bfcc9727cbd8c3)
(cherry picked from commit 4dc35c72744f8820575ab0ea4638c4ddd880547d) (cherry picked from commit 4dc35c72744f8820575ab0ea4638c4ddd880547d)
(cherry picked from commit 097dfdf711d2f968d0580839f5a7a54731c68f34)
--- ---
src/nm-cloud-setup/nm-cloud-setup.service.in | 11 +++++++++++ src/nm-cloud-setup/nm-cloud-setup.service.in | 11 +++++++++++
1 file changed, 11 insertions(+) 1 file changed, 11 insertions(+)
diff --git a/src/nm-cloud-setup/nm-cloud-setup.service.in b/src/nm-cloud-setup/nm-cloud-setup.service.in diff --git a/src/nm-cloud-setup/nm-cloud-setup.service.in b/src/nm-cloud-setup/nm-cloud-setup.service.in
index 4aa6017e48..10acf8add6 100644 index e73654d892..ecb70e1c8e 100644
--- a/src/nm-cloud-setup/nm-cloud-setup.service.in --- a/src/nm-cloud-setup/nm-cloud-setup.service.in
+++ b/src/nm-cloud-setup/nm-cloud-setup.service.in +++ b/src/nm-cloud-setup/nm-cloud-setup.service.in
@@ -8,6 +8,17 @@ After=NetworkManager.service @@ -8,6 +8,17 @@ After=NetworkManager.service

@ -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,4 +1,4 @@
From 81bba3f2321939bb9fd0200a91ac0bec79960732 Mon Sep 17 00:00:00 2001 From 7183fbf6f35572f9fb0c2eeef5c155a3b9c82a54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com> From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
Date: Tue, 27 Aug 2024 12:08:16 +0200 Date: Tue, 27 Aug 2024 12:08:16 +0200
Subject: [PATCH] cloud-setup: azure: ensure that primary address is placed Subject: [PATCH] cloud-setup: azure: ensure that primary address is placed
@ -15,7 +15,6 @@ callback and the address is added in the right position directly.
Co-authored-by: Fernando Fernandez Mancera <ffmancera@riseup.net> Co-authored-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
(cherry picked from commit 72014db629cff33611ade58190d45a714efa1bbf) (cherry picked from commit 72014db629cff33611ade58190d45a714efa1bbf)
(cherry picked from commit c976e212372da9683a1e2f8618e3bcfdf21d5e25) (cherry picked from commit c976e212372da9683a1e2f8618e3bcfdf21d5e25)
(cherry picked from commit 55812963fde9519bb2752c46575a740fa0fea688)
--- ---
src/nm-cloud-setup/nmcs-provider-azure.c | 43 ++++++++++++++++-------- src/nm-cloud-setup/nmcs-provider-azure.c | 43 ++++++++++++++++--------
1 file changed, 29 insertions(+), 14 deletions(-) 1 file changed, 29 insertions(+), 14 deletions(-)

@ -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

@ -1,13 +1,12 @@
%global wpa_supplicant_version 1:1.1 %global wpa_supplicant_version 1:1.1
%global ppp_version %(pkg-config --modversion pppd 2>/dev/null || sed -n 's/^#define\\s*VERSION\\s*"\\([^\\s]*\\)"$/\\1/p' %{_includedir}/pppd/patchlevel.h 2>/dev/null | grep . || echo bad) %global ppp_version %(pkg-config --modversion pppd 2>/dev/null || sed -n 's/^#define\\s*VERSION\\s*"\\([^\\s]*\\)"$/\\1/p' %{_includedir}/pppd/patchlevel.h 2>/dev/null | grep . || echo bad)
%global glib2_version %(pkg-config --modversion glib-2.0 2>/dev/null || echo bad) %global glib2_version %(pkg-config --modversion glib-2.0 2>/dev/null || echo bad)
%global epoch_version 1 %global epoch_version 1
%global real_version 1.46.0 %global real_version 1.48.10
%global rpm_version %{real_version} %global rpm_version %{real_version}
%global release_version 19 %global release_version 2
%global snapshot %{nil} %global snapshot %{nil}
%global git_sha %{nil} %global git_sha %{nil}
%global bcond_default_debug 0 %global bcond_default_debug 0
@ -212,25 +211,8 @@ Source9: readme-ifcfg-rh-migrated.txt
Patch0001: 0001-revert-change-default-value-for-ipv4.dad-timeout-from-0-to-200ms.patch Patch0001: 0001-revert-change-default-value-for-ipv4.dad-timeout-from-0-to-200ms.patch
# Bugfixes that are only relevant until next rebase of the package. # Bugfixes that are only relevant until next rebase of the package.
# Patch1001: 1001-some.patch Patch1001: 1001-cloud-setup-allow-bigger-restart-bursts-rhel-56740.patch
Patch1001: 1001-drop-privateusers-directive-from-nm-cloud-setup-rhel27053.patch Patch1002: 1002-cloud-setup-ensure-azure-places-primary-address-first-rhel-56387.patch
Patch1002: 1002-allow-rollback-on-internal-global-dns-rhel-29725.patch
Patch1003: 1003-do-not-allow-ovs-bridge-and-port-to-be-parent-rhel-28545.patch
Patch1004: 1004-nm-dispatcher-fix-crash-rhel28973.patch
Patch1005: 1005-fix-race-condition-while-enumerating-devices-rhel25808.patch
Patch1006: 1006-fix-lldp-for-ovs-bridge-ports-rhel31766.patch
Patch1007: 1007-platform-avoid-routes-resync-rhel36162.patch
Patch1008: 1008-checkpoint-preserve-in-memory-state-rhel32493.patch
Patch1010: 1010-allow-ip-configurations-without-addresses-rhel28544.patch
Patch1011: 1011-vpn-handle-hint-tags-in-the-daemon-rhel44712.patch
Patch1013: 1013-ovs-wait-for-the-link-to-be-ready-before-activating-rhel-49799.patch
Patch1014: 1014-ovs-fix-triggering-stage3-without-dhcp-client-rhel-49799.patch
Patch1015: 1015-policy-unblock-the-autoconnect-for-children-when-parent-is-available-rhel-53344.patch
Patch1016: 1016-fix-lldp-crash-dereferencing-null-pointer-rhel-46200.patch
Patch1017: 1017-use-etc-hosts-for-hostname-resolution-rhel-53202.patch
Patch1018: 1018-retry-hostname-resolution-when-it-fails-rhel-55397.patch
Patch1019: 1019-cloud-setup-allow-bigger-restart-bursts-rhel-56739.patch
Patch1020: 1020-cloud-setup-ensure-azure-places-primary-address-first-rhel-56386.patch
Requires(post): systemd Requires(post): systemd
%if 0%{?fedora} || 0%{?rhel} >= 8 %if 0%{?fedora} || 0%{?rhel} >= 8
@ -912,7 +894,8 @@ autoreconf --install --force
--with-resolvconf=no \ --with-resolvconf=no \
--with-netconfig=no \ --with-netconfig=no \
--with-config-dns-rc-manager-default=%{dns_rc_manager_default} \ --with-config-dns-rc-manager-default=%{dns_rc_manager_default} \
--with-config-logging-backend-default=%{logging_backend_default} --with-config-logging-backend-default=%{logging_backend_default} \
--disable-autotools-deprecation
%make_build %make_build
@ -1286,68 +1269,70 @@ fi
%changelog %changelog
* Fri Aug 30 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-19 * Fri Aug 30 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.48.10-2
- Retry hostname resolutions when it fails (RHEL-55397) - cloud-setup: Allow bigger restart bursts (RHEL-56740)
- cloud-setup: allow bigger restart bursts (RHEL-56739) - cloud-setup: Fix Azure swap of primary and secondary IP addresses (RHEL-56387)
- cloud-setup: Fix Azure primary and secondary address swap (RHEL-56386)
* Thu Aug 22 2024 Íñigo Huguet <ihuguet@redhat.com> - 1:1.48.10-1
* Tue Aug 20 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-18 - Unblock the autoconnect for children when parent is available (RHEL-46904)
- Fix crash dereferencing NULL pointer during debug logging (RHEL-46200) - Fix crash produced by malformed LLDP package when debug logging (RHEL-46199)
- Use /etc/hosts for hostname reesolution (RHEL-53202) - Support reapplying bridge-port VLANs (RHEL-26750)
- Add small backoff time before resync (RHEL-29902)
* Tue Aug 13 2024 Wen Liang <wenliang@redhat.com> - 1:1.46.0-17
- Unblock the autoconnect for children when parent is available (RHEL-53344) * Fri Aug 09 2024 Fernando Fernandez Mancera <ferferna@redha.com> - 1:1.46.8-1
- Stop writing offensive terms into keyfiles (RHEL-52597)
* Wed Jul 31 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-16 - Remove offensive words (RHEL-33368)
- Revert OVS checkpoint rollback patches. - Fix cloned-mac-address race condition with DHCP on ovs-interfaces (RHEL-49796)
- Fix OVS stage3 activation without DHCP client initialized (RHEL-49799)
* Fri Jul 26 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.48.6-1
* Thu Jul 25 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-15 - Wait until link is ready before activating for ovs-interface (RHEL-49796)
- Wait for link to be ready before activating ovs-interface (RHEL-49799) - Fix rollback on OVS checkpoint (RHEL-31972)
- Assert that the auto-activate list is empty on dispose (RHEL-44345)
* Tue Jul 23 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-14
- Fix OVS checkpoint rollback (RHEL-32646) * Fri Jul 05 2024 Stanislas Faye <sfaye@redhat.com> 1:1.48.4-1
- Update to 1.48.4 release
* Fri Jun 28 2024 Beniamino Galvani <bgalvani@redhat.com> - 1:1.46.0-13 - Support matching a OVS system interface by MAC address (RHEL-34617)
- Revert "Fix port reactivation when controller is deactivating" (RHEL-32646) - When looking up the system hostname from the reverse DNS lookup of
addresses configured on interfaces, NetworkManager now takes into
* Thu Jun 27 2024 Íñigo Huguet <ihuguet@redhat.com> - 1:1.46.0-12 account the content of /etc/hosts (RHEL-33435)
- Add ipcalc as dependency of NetworkManager-dispatcher-routing-rules (RHEL-43583)
* Thu Jun 27 2024 Íñigo Huguet <ihuguet@redhat.com> 1:1.48.2-2
* Mon Jun 24 2024 Íñigo Huguet <ihuguet@redhat.com> - 1:1.46.0-11 - Add ipcalc as dependency of NetworkManager-dispatcher-routing-rules (RHEL-36648)
- Handle hint's tags from VPN secrets in the daemon (RHEL-44712)
* Mon Jun 24 2024 Beniamino Galvani <bgalvani@redhat.com> 1:1.48.2-1
* Mon Jun 17 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-10 - Update to 1.48.2 release
- Support IPv6 in IPSec VPN (RHEL-28544) - Save connection timestamps when shutting down (RHEL-35539)
- Fix regression with OpenVPN dynamic challenge (RHEL-43720)
* Sat Jun 01 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-9
- Fix port reactivation when controller is deactivating (RHEL-32646) * Thu May 30 2024 Lubomir Rintel <lkundrak@v3.sk> - 1:1.48.0-1
- Upgrade to 1.48.0 release
* Thu May 23 2024 Beniamino Galvani <bgalvani@redhat.com> - 1:1.46.0-8
- Preserve in-memory state of connections after checkpoint/rollback (RHEL-32493) * Thu May 16 2024 Lubomir Rintel <lkundrak@v3.sk> - 1:1.47.91-1
- Upgrade to 1.47.91 (rc2)
* Tue May 14 2024 Íñigo Huguet <ihuguet@redhat.com> - 1:1.46.0-7
- Fix CPU usage of 100% when updating routes cache (RHEL-36162) * Fri May 03 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.47.90-1
- Upgrade to 1.47.90 (rc1)
* Mon Apr 08 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-6
- Rebuild because build must go on 0day not 9.4.0 * Fri Apr 19 2024 Íñigo Huguet <ihuguet@redhat.com> - 1:1.47.5-1
- Fix a crash during shutdown (RHEL-29856)
* Fri Apr 05 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-5
- Fix LLDP for OVS Bridge ports (RHEL-31766) * Fri Apr 05 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.47.4-1
- Fix LLDP support for interfaces attached to OVS bridges. (RHEL-1418)
* Tue Mar 26 2024 Beniamino Galvani <bgalvani@redhat.com> - 1:1.46.0-4 - Fix NMCI crashes on ovs_mtu and bond tests. (RHEL-30348)
- Fix nm-dispatcher crash (RHEL-28973)
- Fix race condition while enumerating devices (RHEL-25808) * Wed Apr 03 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.47.3-2
- Rebuild for CI gating
* Fri Mar 22 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1:1.46.0-3
- Upgrade release number to build with the right target * Tue Mar 26 2024 Gris Ge <fge@redhat.com> - 1.47.3-1
- Upgrade to 1.47.3 release (development)
* Wed Mar 20 2024 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.46.0-2 - Support rollback on global DNS (RHEL-23446)
- Drop PrivateUser directive from nm-cloud-setup service (RHEL-27503) - Support VLAN over OVS interface which holds the same name as OVS bridge (RHEL-26753)
- Support rollback on global DNS (RHEL-29725)
- Do not allow OVS bridge or port to be parent (RHEL-28545) * Fri Mar 08 2024 Íñigo Huguet <ihuguet@redhat.com>
- Update to 1.47.2 release (development)
* Thu Feb 22 2024 Stanislas FAYE <sfaye@redhat.com> - 1.46.0-1 - Support sending DHCPRELEASE (RHEL-17310)
* Thu Feb 22 2024 Stanislas FAYE <sfaye@redhat.com>
- Update to 1.46.0 release - Update to 1.46.0 release
- Fix DHCPv4 lease can't be renewed after it expires (RHEL-24127) - Fix DHCPv4 lease can't be renewed after it expires (RHEL-24127)
- Support the MACsec offload mode (RHEL-24337) - Support the MACsec offload mode (RHEL-24337)

Loading…
Cancel
Save