netlink: implement generic group subscription
Needed by the IPv6 manager.
This commit is contained in:
@@ -66,6 +66,8 @@ typedef struct {
|
|||||||
guint event_id;
|
guint event_id;
|
||||||
|
|
||||||
guint request_status_id;
|
guint request_status_id;
|
||||||
|
|
||||||
|
GHashTable *subscriptions;
|
||||||
} NMNetlinkMonitorPrivate;
|
} NMNetlinkMonitorPrivate;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -263,13 +265,9 @@ nm_netlink_monitor_open_connection (NMNetlinkMonitor *self, GError **error)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nl_socket_add_membership (priv->nlh, RTNLGRP_LINK) < 0) {
|
/* Subscribe to the LINK group for internal carrier signals */
|
||||||
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
if (!nm_netlink_monitor_subscribe (self, RTNLGRP_LINK, error))
|
||||||
NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP,
|
|
||||||
_("unable to join netlink group for monitoring link status: %s"),
|
|
||||||
nl_geterror ());
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
if ((priv->nlh_link_cache = rtnl_link_alloc_cache (priv->nlh)) == NULL) {
|
if ((priv->nlh_link_cache = rtnl_link_alloc_cache (priv->nlh)) == NULL) {
|
||||||
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
||||||
@@ -373,6 +371,77 @@ nm_netlink_monitor_detach (NMNetlinkMonitor *self)
|
|||||||
priv->event_id = 0;
|
priv->event_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_subs (NMNetlinkMonitor *self, int group)
|
||||||
|
{
|
||||||
|
NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
return GPOINTER_TO_INT (g_hash_table_lookup (priv->subscriptions,
|
||||||
|
GINT_TO_POINTER (group)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_subs (NMNetlinkMonitor *self, int group, int new_subs)
|
||||||
|
{
|
||||||
|
NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
g_hash_table_insert (priv->subscriptions,
|
||||||
|
GINT_TO_POINTER (group),
|
||||||
|
GINT_TO_POINTER (new_subs));
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_netlink_monitor_subscribe (NMNetlinkMonitor *self, int group, GError **error)
|
||||||
|
{
|
||||||
|
NMNetlinkMonitorPrivate *priv;
|
||||||
|
int subs;
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE);
|
||||||
|
|
||||||
|
priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
if (!priv->nlh) {
|
||||||
|
if (!nm_netlink_monitor_open_connection (self, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
subs = get_subs (self, group) + 1;
|
||||||
|
if (subs == 1) {
|
||||||
|
if (nl_socket_add_membership (priv->nlh, group) < 0) {
|
||||||
|
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
||||||
|
NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP,
|
||||||
|
_("unable to join netlink group: %s"),
|
||||||
|
nl_geterror ());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update # of subscriptions for this group */
|
||||||
|
set_subs (self, group, subs);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nm_netlink_monitor_unsubscribe (NMNetlinkMonitor *self, int group)
|
||||||
|
{
|
||||||
|
NMNetlinkMonitorPrivate *priv;
|
||||||
|
int subs;
|
||||||
|
|
||||||
|
g_return_if_fail (self != NULL);
|
||||||
|
g_return_if_fail (NM_IS_NETLINK_MONITOR (self));
|
||||||
|
|
||||||
|
priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
|
||||||
|
g_return_if_fail (priv->nlh != NULL);
|
||||||
|
|
||||||
|
subs = get_subs (self, group) - 1;
|
||||||
|
if (subs == 0)
|
||||||
|
nl_socket_drop_membership (priv->nlh, group);
|
||||||
|
|
||||||
|
/* Update # of subscriptions for this group */
|
||||||
|
set_subs (self, group, subs);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
deferred_emit_carrier_state (gpointer user_data)
|
deferred_emit_carrier_state (gpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -515,6 +584,9 @@ nm_netlink_monitor_get (void)
|
|||||||
static void
|
static void
|
||||||
nm_netlink_monitor_init (NMNetlinkMonitor *self)
|
nm_netlink_monitor_init (NMNetlinkMonitor *self)
|
||||||
{
|
{
|
||||||
|
NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
priv->subscriptions = g_hash_table_new (g_int_hash, g_int_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -543,6 +615,8 @@ finalize (GObject *object)
|
|||||||
priv->nlh_cb = NULL;
|
priv->nlh_cb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_hash_table_destroy (priv->subscriptions);
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_netlink_monitor_parent_class)->finalize (object);
|
G_OBJECT_CLASS (nm_netlink_monitor_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -67,11 +67,19 @@ GQuark nm_netlink_monitor_error_quark (void) G_GNUC_CONST;
|
|||||||
|
|
||||||
NMNetlinkMonitor *nm_netlink_monitor_get (void);
|
NMNetlinkMonitor *nm_netlink_monitor_get (void);
|
||||||
|
|
||||||
gboolean nm_netlink_monitor_open_connection (NMNetlinkMonitor *monitor,
|
gboolean nm_netlink_monitor_open_connection (NMNetlinkMonitor *monitor,
|
||||||
GError **error);
|
GError **error);
|
||||||
void nm_netlink_monitor_close_connection (NMNetlinkMonitor *monitor);
|
void nm_netlink_monitor_close_connection (NMNetlinkMonitor *monitor);
|
||||||
void nm_netlink_monitor_attach (NMNetlinkMonitor *monitor);
|
void nm_netlink_monitor_attach (NMNetlinkMonitor *monitor);
|
||||||
void nm_netlink_monitor_detach (NMNetlinkMonitor *monitor);
|
void nm_netlink_monitor_detach (NMNetlinkMonitor *monitor);
|
||||||
|
|
||||||
|
gboolean nm_netlink_monitor_subscribe (NMNetlinkMonitor *monitor,
|
||||||
|
int group,
|
||||||
|
GError **error);
|
||||||
|
void nm_netlink_monitor_unsubscribe (NMNetlinkMonitor *monitor,
|
||||||
|
int group);
|
||||||
|
|
||||||
|
|
||||||
gboolean nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor,
|
gboolean nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor,
|
||||||
GError **error);
|
GError **error);
|
||||||
gboolean nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *monitor,
|
gboolean nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *monitor,
|
||||||
|
Reference in New Issue
Block a user