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: a8a2e6d727 ('ip-config: Support configuring per-device IPv4 sysctl forwarding option')
This commit is contained in:
Íñigo Huguet 2025-05-02 09:15:00 +02:00 committed by Íñigo Huguet
parent d58d0a793e
commit 8faa33b9d4
3 changed files with 63 additions and 4 deletions

View file

@ -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);
}
}

View file

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

View file

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