From 8faa33b9d4419938198110210f20480cd0d3158c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Fri, 2 May 2025 09:15:00 +0200 Subject: [PATCH] manager: add sharing-ipv4-changed signal This signal notifies about the "sharing state", that's it, when there is at least one shared connection active or not. Each device informs to nm_manager when a shared connection is activated or deactivated and nm_manager emits this signal when the first shared connection is activated or the last one is deactivated. For now we're only interested in IPv4 forwarding as it's the only one that we need to track from nm_device (in following commits). Fixes: a8a2e6d727f0 ('ip-config: Support configuring per-device IPv4 sysctl forwarding option') --- src/core/devices/nm-device.c | 14 ++++++++--- src/core/nm-manager.c | 49 ++++++++++++++++++++++++++++++++++++ src/core/nm-manager.h | 4 +++ 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index dd481180df..4edec0c462 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -13528,15 +13528,21 @@ nm_device_activate_schedule_stage3_ip_config(NMDevice *self, gboolean do_sync) static void _dev_ipsharedx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDeviceIPState old_state = priv->ipshared_data_x[IS_IPv4].state; - if (priv->ipshared_data_x[IS_IPv4].state != state) { + if (old_state != state) { _LOGD_ipshared(addr_family, "set state %s (was %s)", nm_device_ip_state_to_string(state), - nm_device_ip_state_to_string(priv->ipshared_data_x[IS_IPv4].state)); + nm_device_ip_state_to_string(old_state)); priv->ipshared_data_x[IS_IPv4].state = state; + + if (old_state == NM_DEVICE_IP_STATE_READY || state == NM_DEVICE_IP_STATE_READY) + nm_manager_update_shared_connection(NM_MANAGER_GET, + addr_family, + state == NM_DEVICE_IP_STATE_READY); } } diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 060e0c2c7c..87dde2c3af 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -136,6 +136,7 @@ enum { ACTIVE_CONNECTION_REMOVED, CONFIGURE_QUIT, DEVICE_IFINDEX_CHANGED, + SHARING_IPV4_CHANGED, LAST_SIGNAL }; @@ -238,6 +239,8 @@ typedef struct { guint8 device_state_prune_ratelimit_count; + guint shared_connections_ip4_count; + bool startup : 1; bool devices_inited : 1; @@ -8829,6 +8832,41 @@ nm_manager_emit_device_ifindex_changed(NMManager *self, NMDevice *device) g_signal_emit(self, signals[DEVICE_IFINDEX_CHANGED], 0, device); } +void +nm_manager_update_shared_connection(NMManager *self, int addr_family, gboolean enabled) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gboolean state_changed, state; + + /* Only IPv4 supported for the moment */ + if (addr_family != AF_INET) + return; + + if (enabled) { + g_return_if_fail(priv->shared_connections_ip4_count < G_MAXUINT); + priv->shared_connections_ip4_count++; + state_changed = priv->shared_connections_ip4_count == 1; + } else { + g_return_if_fail(priv->shared_connections_ip4_count > 0); + priv->shared_connections_ip4_count--; + state_changed = priv->shared_connections_ip4_count == 0; + } + + if (state_changed) { + state = priv->shared_connections_ip4_count > 0; + _LOGD(LOGD_SHARING, "sharing-ipv4 state change %d -> %d", !state, state); + g_signal_emit(self, signals[SHARING_IPV4_CHANGED], 0, state); + } +} + +gboolean +nm_manager_get_sharing_ipv4(NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + + return priv->shared_connections_ip4_count > 0; +} + /*****************************************************************************/ NM_DEFINE_SINGLETON_REGISTER(NMManager); @@ -9932,6 +9970,17 @@ nm_manager_class_init(NMManagerClass *manager_class) G_TYPE_NONE, 1, NM_TYPE_DEVICE); + + signals[SHARING_IPV4_CHANGED] = g_signal_new(NM_MANAGER_SHARING_IPV4_CHANGED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); } NMConfig * diff --git a/src/core/nm-manager.h b/src/core/nm-manager.h index 3c5213c4f2..e10ca0d110 100644 --- a/src/core/nm-manager.h +++ b/src/core/nm-manager.h @@ -61,6 +61,7 @@ #define NM_MANAGER_CONFIGURE_QUIT "configure-quit" #define NM_MANAGER_INTERNAL_DEVICE_ADDED "internal-device-added" #define NM_MANAGER_INTERNAL_DEVICE_REMOVED "internal-device-removed" +#define NM_MANAGER_SHARING_IPV4_CHANGED "sharing-ipv4-changed" GType nm_manager_get_type(void); @@ -212,6 +213,9 @@ struct _NMDnsManager; struct _NMDnsManager *nm_manager_get_dns_manager(NMManager *self); +void nm_manager_update_shared_connection(NMManager *self, int addr_family, gboolean enabled); +gboolean nm_manager_get_sharing_ipv4(NMManager *self); + /*****************************************************************************/ void nm_manager_notify_delete_settings_connections(NMManager *self,