diff --git a/src/ip6-manager/Makefile.am b/src/ip6-manager/Makefile.am index 39d77155f..c2f559142 100644 --- a/src/ip6-manager/Makefile.am +++ b/src/ip6-manager/Makefile.am @@ -11,9 +11,7 @@ noinst_LTLIBRARIES = libip6-manager.la libip6_manager_la_SOURCES = \ nm-ip6-manager.c \ - nm-ip6-manager.h \ - nm-netlink-listener.c \ - nm-netlink-listener.h + nm-ip6-manager.h libip6_manager_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c index be85ab0dc..04a304946 100644 --- a/src/ip6-manager/nm-ip6-manager.c +++ b/src/ip6-manager/nm-ip6-manager.c @@ -25,7 +25,8 @@ #include #include "nm-ip6-manager.h" -#include "nm-netlink-listener.h" +#include "nm-netlink-monitor.h" +#include "nm-netlink.h" #include "NetworkManagerUtils.h" #include "nm-marshal.h" #include "nm-logging.h" @@ -40,7 +41,7 @@ #define IF_RS_SENT 0x10 typedef struct { - NMNetlinkListener *netlink; + NMNetlinkMonitor *monitor; GHashTable *devices_by_iface, *devices_by_index; struct nl_handle *nlh; @@ -82,6 +83,8 @@ typedef struct { GArray *rdnss_servers; guint rdnss_timeout_id; + + guint32 ra_flags; } NMIP6Device; G_DEFINE_TYPE (NMIP6Manager, nm_ip6_manager, G_TYPE_OBJECT) @@ -96,7 +99,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; static NMIP6Manager *nm_ip6_manager_new (void); -static void netlink_notification (NMNetlinkListener *listener, struct nl_msg *msg, gpointer user_data); +static void netlink_notification (NMNetlinkMonitor *monitor, struct nl_msg *msg, gpointer user_data); static void nm_ip6_device_destroy (NMIP6Device *device); @@ -122,12 +125,14 @@ nm_ip6_manager_init (NMIP6Manager *manager) (GDestroyNotify) nm_ip6_device_destroy); priv->devices_by_index = g_hash_table_new (NULL, NULL); - priv->netlink = nm_netlink_listener_get (); - g_signal_connect (priv->netlink, "notification", - G_CALLBACK (netlink_notification), manager); - nm_netlink_listener_subscribe (priv->netlink, RTNLGRP_IPV6_IFADDR, NULL); - nm_netlink_listener_subscribe (priv->netlink, RTNLGRP_IPV6_PREFIX, NULL); - nm_netlink_listener_subscribe (priv->netlink, RTNLGRP_ND_USEROPT, NULL); + priv->monitor = nm_netlink_monitor_get (); + nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_IFADDR, NULL); + nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_PREFIX, NULL); + nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_ND_USEROPT, NULL); + nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_LINK, NULL); + + g_signal_connect (priv->monitor, "notification", + G_CALLBACK (netlink_notification), manager); priv->nlh = nm_netlink_get_default_handle (); priv->addr_cache = rtnl_addr_alloc_cache (priv->nlh); @@ -141,7 +146,7 @@ finalize (GObject *object) g_hash_table_destroy (priv->devices_by_iface); g_hash_table_destroy (priv->devices_by_index); - g_object_unref (priv->netlink); + g_object_unref (priv->monitor); nl_cache_free (priv->addr_cache); nl_cache_free (priv->route_cache); @@ -348,8 +353,6 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed) struct rtnl_addr *rtnladdr; struct nl_addr *nladdr; struct in6_addr *addr; - struct rtnl_link *link; - guint flags; CallbackInfo *info; guint dhcp_opts = IP6_DHCP_OPT_NONE; @@ -373,21 +376,16 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed) } } - /* Note: we don't want to keep a cache of links, because the - * kernel doesn't send notifications when the flags change, so the - * cached rtnl_links would have out-of-date flags. - */ - link = nm_netlink_index_to_rtnl_link (device->index); - flags = rtnl_link_get_flags (link); - rtnl_link_put (link); - - if ((flags & IF_RA_RCVD) && device->state < NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT) + if ((device->ra_flags & IF_RA_RCVD) && device->state < NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT) device->state = NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT; - if (flags & IF_RA_MANAGED) + if (device->ra_flags & IF_RA_MANAGED) { dhcp_opts = IP6_DHCP_OPT_MANAGED; - else if (flags & IF_RA_OTHERCONF) + nm_log_dbg (LOGD_IP6, "router advertisement deferred to DHCPv6"); + } else if (device->ra_flags & IF_RA_OTHERCONF) { dhcp_opts = IP6_DHCP_OPT_OTHERCONF; + nm_log_dbg (LOGD_IP6, "router advertisement requests parallel DHCPv6"); + } if (!device->addrconf_complete) { if (device->state >= device->target_state || @@ -598,8 +596,58 @@ process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg) return NULL; } +static struct nla_policy link_policy[IFLA_MAX + 1] = { + [IFLA_PROTINFO] = { .type = NLA_NESTED }, +}; + +static struct nla_policy link_prot_policy[IFLA_INET6_MAX + 1] = { + [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, +}; + +static NMIP6Device * +process_newlink (NMIP6Manager *manager, struct nl_msg *msg) +{ + struct nlmsghdr *hdr = nlmsg_hdr (msg); + struct ifinfomsg *ifi; + NMIP6Device *device; + struct nlattr *tb[IFLA_MAX + 1]; + struct nlattr *pi[IFLA_INET6_MAX + 1]; + int err; + + ifi = nlmsg_data (hdr); + if (ifi->ifi_family != AF_INET6) + return NULL; + + device = nm_ip6_manager_get_device (manager, ifi->ifi_index); + if (!device || device->addrconf_complete) + return NULL; + + /* FIXME: we have to do this manually for now since libnl doesn't yet + * support the IFLA_PROTINFO attribute of NEWLINK messages. When it does, + * we can get rid of this function and just grab IFLA_PROTINFO from + * nm_ip6_device_sync_from_netlink(), then get the IFLA_INET6_FLAGS out of + * the PROTINFO. + */ + + err = nlmsg_parse (hdr, sizeof (*ifi), tb, IFLA_MAX, link_policy); + if (err < 0) + return NULL; + if (!tb[IFLA_PROTINFO]) + return NULL; + + err = nla_parse_nested (pi, IFLA_INET6_MAX, tb[IFLA_PROTINFO], link_prot_policy); + if (err < 0) + return NULL; + if (!pi[IFLA_INET6_FLAGS]) + return NULL; + + device->ra_flags = nla_get_u32 (pi[IFLA_INET6_FLAGS]); + + return device; +} + static void -netlink_notification (NMNetlinkListener *listener, struct nl_msg *msg, gpointer user_data) +netlink_notification (NMNetlinkMonitor *monitor, struct nl_msg *msg, gpointer user_data) { NMIP6Manager *manager = (NMIP6Manager *) user_data; NMIP6Device *device; @@ -613,22 +661,22 @@ netlink_notification (NMNetlinkListener *listener, struct nl_msg *msg, gpointer device = process_addr (manager, msg); config_changed = TRUE; break; - case RTM_NEWROUTE: case RTM_DELROUTE: device = process_route (manager, msg); config_changed = TRUE; break; - case RTM_NEWPREFIX: device = process_prefix (manager, msg); break; - case RTM_NEWNDUSEROPT: device = process_nduseropt (manager, msg); config_changed = TRUE; break; - + case RTM_NEWLINK: + device = process_newlink (manager, msg); + config_changed = TRUE; + break; default: return; } @@ -758,6 +806,7 @@ nm_ip6_manager_begin_addrconf (NMIP6Manager *manager, nm_log_info (LOGD_IP6, "Activation (%s) Beginning IP6 addrconf.", iface); device->addrconf_complete = FALSE; + device->ra_flags = 0; /* Set up a timeout on the transaction to kill it after the timeout */ info = callback_info_new (device, 0); @@ -771,6 +820,7 @@ nm_ip6_manager_begin_addrconf (NMIP6Manager *manager, * device is already fully configured and schedule the * ADDRCONF_COMPLETE signal in that case. */ + nm_netlink_monitor_request_ip6_info (priv->monitor, NULL); nm_ip6_device_sync_from_netlink (device, FALSE); } diff --git a/src/ip6-manager/nm-netlink-listener.c b/src/ip6-manager/nm-netlink-listener.c deleted file mode 100644 index 55c4d76ad..000000000 --- a/src/ip6-manager/nm-netlink-listener.c +++ /dev/null @@ -1,406 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2009 Red Hat, Inc. - * Copyright (C) 2005 - 2008 Novell, Inc. - * Copyright (C) 2005 Ray Strode - * - * Some code borrowed from HAL: - * - * Copyright (C) 2003 David Zeuthen, - * Copyright (C) 2004 Novell, Inc. - */ - -/* FIXME: this should be merged with src/nm-netlink-monitor.c */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "NetworkManager.h" -#include "nm-system.h" -#include "nm-netlink-listener.h" -#include "nm-marshal.h" -#include "nm-netlink.h" - -#define NM_NETLINK_LISTENER_EVENT_CONDITIONS \ - ((GIOCondition) (G_IO_IN | G_IO_PRI)) - -#define NM_NETLINK_LISTENER_ERROR_CONDITIONS \ - ((GIOCondition) (G_IO_ERR | G_IO_NVAL)) - -#define NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS \ - ((GIOCondition) (G_IO_HUP)) - -#define NM_NETLINK_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - NM_TYPE_NETLINK_LISTENER, \ - NMNetlinkListenerPrivate)) - -typedef struct { - struct nl_handle *nlh; - struct nl_cb * nlh_cb; - struct nl_cache * nlh_link_cache; - - GIOChannel * io_channel; - guint event_id; - - guint request_status_id; -} NMNetlinkListenerPrivate; - -static gboolean nm_netlink_listener_event_handler (GIOChannel *channel, - GIOCondition io_condition, - gpointer user_data); - -static gboolean nm_netlink_listener_error_handler (GIOChannel *channel, - GIOCondition io_condition, - NMNetlinkListener *listener); - -static gboolean nm_netlink_listener_disconnect_handler (GIOChannel *channel, - GIOCondition io_condition, - NMNetlinkListener *listener); - -static void close_connection (NMNetlinkListener *listener); - -enum { - NOTIFICATION = 0, - ERROR, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -G_DEFINE_TYPE (NMNetlinkListener, nm_netlink_listener, G_TYPE_OBJECT); - -NMNetlinkListener * -nm_netlink_listener_get (void) -{ - static NMNetlinkListener *singleton = NULL; - - if (!singleton) - singleton = NM_NETLINK_LISTENER (g_object_new (NM_TYPE_NETLINK_LISTENER, NULL)); - else - g_object_ref (singleton); - - return singleton; -} - -static void -nm_netlink_listener_init (NMNetlinkListener *listener) -{ -} - -static void -finalize (GObject *object) -{ - NMNetlinkListenerPrivate *priv = NM_NETLINK_LISTENER_GET_PRIVATE (object); - - if (priv->request_status_id) - g_source_remove (priv->request_status_id); - - if (priv->io_channel) - close_connection (NM_NETLINK_LISTENER (object)); - - if (priv->nlh) { - nl_handle_destroy (priv->nlh); - priv->nlh = NULL; - } - - if (priv->nlh_cb) { - nl_cb_put (priv->nlh_cb); - priv->nlh_cb = NULL; - } - - G_OBJECT_CLASS (nm_netlink_listener_parent_class)->finalize (object); -} - -static void -nm_netlink_listener_class_init (NMNetlinkListenerClass *listener_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (listener_class); - - g_type_class_add_private (listener_class, sizeof (NMNetlinkListenerPrivate)); - - /* Virtual methods */ - object_class->finalize = finalize; - - /* Signals */ - signals[NOTIFICATION] = - g_signal_new ("notification", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMNetlinkListenerClass, notification), - NULL, NULL, g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - signals[ERROR] = - g_signal_new ("error", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMNetlinkListenerClass, error), - NULL, NULL, _nm_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); -} - -static int -netlink_event_input (struct nl_msg *msg, void *listener) -{ - struct nlmsghdr *hdr = nlmsg_hdr (msg); - - if (hdr->nlmsg_pid != 0) - return NL_STOP; - - g_signal_emit (listener, signals[NOTIFICATION], 0, msg); - - /* Stop processing messages */ - return NL_STOP; -} - -static gboolean -open_connection (NMNetlinkListener *listener, GError **error) -{ - NMNetlinkListenerPrivate *priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener); - int fd; - GError *channel_error = NULL; - GIOFlags channel_flags; - - g_return_val_if_fail (priv->io_channel == NULL, FALSE); - - priv->nlh_cb = nl_cb_alloc (NL_CB_DEFAULT); - priv->nlh = nl_handle_alloc_cb (priv->nlh_cb); - if (!priv->nlh) { - g_set_error (error, NM_NETLINK_LISTENER_ERROR, - NM_NETLINK_LISTENER_ERROR_NETLINK_ALLOC_HANDLE, - _("unable to allocate netlink handle: %s"), - nl_geterror ()); - goto error; - } - - nl_disable_sequence_check (priv->nlh); - nl_socket_modify_cb (priv->nlh, NL_CB_VALID, NL_CB_CUSTOM, netlink_event_input, listener); - if (nl_connect (priv->nlh, NETLINK_ROUTE) < 0) { - g_set_error (error, NM_NETLINK_LISTENER_ERROR, - NM_NETLINK_LISTENER_ERROR_NETLINK_CONNECT, - _("unable to connect to netlink: %s"), - nl_geterror ()); - goto error; - } - - fd = nl_socket_get_fd (priv->nlh); - priv->io_channel = g_io_channel_unix_new (fd); - - g_io_channel_set_encoding (priv->io_channel, NULL, &channel_error); - /* Encoding is NULL, so no conversion error can possibly occur */ - g_assert (channel_error == NULL); - - g_io_channel_set_close_on_unref (priv->io_channel, TRUE); - channel_flags = g_io_channel_get_flags (priv->io_channel); - channel_error = NULL; - g_io_channel_set_flags (priv->io_channel, - channel_flags | G_IO_FLAG_NONBLOCK, - &channel_error); - if (channel_error != NULL) { - g_propagate_error (error, channel_error); - goto error; - } - - priv->event_id = g_io_add_watch (priv->io_channel, - (NM_NETLINK_LISTENER_EVENT_CONDITIONS | - NM_NETLINK_LISTENER_ERROR_CONDITIONS | - NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS), - nm_netlink_listener_event_handler, - listener); - return TRUE; - -error: - if (priv->io_channel) - close_connection (listener); - - if (priv->nlh) { - nl_handle_destroy (priv->nlh); - priv->nlh = NULL; - } - - if (priv->nlh_cb) { - nl_cb_put (priv->nlh_cb); - priv->nlh_cb = NULL; - } - return FALSE; -} - -static void -close_connection (NMNetlinkListener *listener) -{ - NMNetlinkListenerPrivate *priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener); - - g_return_if_fail (priv->io_channel != NULL); - - if (priv->event_id) { - g_source_remove (priv->event_id); - priv->event_id = 0; - } - - g_io_channel_shutdown (priv->io_channel, - TRUE /* flush pending data */, - NULL); - - g_io_channel_unref (priv->io_channel); - priv->io_channel = NULL; -} - -GQuark -nm_netlink_listener_error_quark (void) -{ - static GQuark error_quark = 0; - - if (error_quark == 0) - error_quark = g_quark_from_static_string ("nm-netlink-listener-error-quark"); - - return error_quark; -} - -gboolean -nm_netlink_listener_subscribe (NMNetlinkListener *listener, - int group, - GError **error) -{ - NMNetlinkListenerPrivate *priv; - - g_return_val_if_fail (NM_IS_NETLINK_LISTENER (listener), FALSE); - - priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener); - - if (!priv->nlh) { - if (!open_connection (listener, error)) - return FALSE; - } - - if (nl_socket_add_membership (priv->nlh, group) < 0) { - g_set_error (error, NM_NETLINK_LISTENER_ERROR, - NM_NETLINK_LISTENER_ERROR_NETLINK_JOIN_GROUP, - _("unable to join netlink group: %s"), - nl_geterror ()); - return FALSE; - } - - return TRUE; -} - -void -nm_netlink_listener_unsubscribe (NMNetlinkListener *listener, int group) -{ - NMNetlinkListenerPrivate *priv; - - g_return_if_fail (NM_IS_NETLINK_LISTENER (listener)); - - priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener); - g_return_if_fail (priv->nlh != NULL); - - nl_socket_drop_membership (priv->nlh, group); -} - -static gboolean -nm_netlink_listener_event_handler (GIOChannel *channel, - GIOCondition io_condition, - gpointer user_data) -{ - NMNetlinkListener *listener = (NMNetlinkListener *) user_data; - NMNetlinkListenerPrivate *priv; - GError *error = NULL; - - g_return_val_if_fail (NM_IS_NETLINK_LISTENER (listener), TRUE); - - priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener); - g_return_val_if_fail (priv->event_id > 0, TRUE); - - if (io_condition & NM_NETLINK_LISTENER_ERROR_CONDITIONS) - return nm_netlink_listener_error_handler (channel, io_condition, listener); - else if (io_condition & NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS) - return nm_netlink_listener_disconnect_handler (channel, io_condition, listener); - - g_return_val_if_fail (!(io_condition & ~(NM_NETLINK_LISTENER_EVENT_CONDITIONS)), FALSE); - - if (nl_recvmsgs_default (priv->nlh) < 0) { - error = g_error_new (NM_NETLINK_LISTENER_ERROR, - NM_NETLINK_LISTENER_ERROR_PROCESSING_MESSAGE, - _("error processing netlink message: %s"), - nl_geterror ()); - - g_signal_emit (G_OBJECT (listener), - signals[ERROR], - 0, error); - g_error_free (error); - } - - return TRUE; -} - -static gboolean -nm_netlink_listener_error_handler (GIOChannel *channel, - GIOCondition io_condition, - NMNetlinkListener *listener) -{ - GError *socket_error; - const char *err_msg; - int err_code; - socklen_t err_len; - - g_return_val_if_fail (io_condition & NM_NETLINK_LISTENER_ERROR_CONDITIONS, FALSE); - - err_code = 0; - err_len = sizeof (err_code); - if (getsockopt (g_io_channel_unix_get_fd (channel), - SOL_SOCKET, SO_ERROR, (void *) &err_code, &err_len)) - err_msg = strerror (err_code); - else - err_msg = _("error occurred while waiting for data on socket"); - - socket_error = g_error_new (NM_NETLINK_LISTENER_ERROR, - NM_NETLINK_LISTENER_ERROR_WAITING_FOR_SOCKET_DATA, - "%s", - err_msg); - - g_signal_emit (G_OBJECT (listener), - signals[ERROR], - 0, socket_error); - - g_error_free (socket_error); - - return TRUE; -} - -static gboolean -nm_netlink_listener_disconnect_handler (GIOChannel *channel, - GIOCondition io_condition, - NMNetlinkListener *listener) -{ - - g_return_val_if_fail (!(io_condition & ~(NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS)), FALSE); - return FALSE; -} - diff --git a/src/ip6-manager/nm-netlink-listener.h b/src/ip6-manager/nm-netlink-listener.h deleted file mode 100644 index 0baabac00..000000000 --- a/src/ip6-manager/nm-netlink-listener.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Netlink socket listener - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2009 Red Hat, Inc. - * Copyright (C) 2005 - 2008 Novell, Inc. - * Copyright (C) 2005 Ray Strode - */ - -#ifndef NM_NETLINK_LISTENER_H -#define NM_NETLINK_LISTENER_H - -#include -#include - -#include "nm-netlink.h" - -G_BEGIN_DECLS - -#define NM_TYPE_NETLINK_LISTENER (nm_netlink_listener_get_type ()) -#define NM_NETLINK_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NETLINK_LISTENER, NMNetlinkListener)) -#define NM_NETLINK_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_NETLINK_LISTENER, NMNetlinkListenerClass)) -#define NM_IS_NETLINK_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_NETLINK_LISTENER)) -#define NM_IS_NETLINK_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_NETLINK_LISTENER)) -#define NM_NETLINK_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_NETLINK_LISTENER, NMNetlinkListenerClass)) -#define NM_NETLINK_LISTENER_ERROR (nm_netlink_listener_error_quark ()) - -typedef enum { - NM_NETLINK_LISTENER_ERROR_GENERIC = 0, - NM_NETLINK_LISTENER_ERROR_NETLINK_ALLOC_HANDLE, - NM_NETLINK_LISTENER_ERROR_NETLINK_CONNECT, - NM_NETLINK_LISTENER_ERROR_NETLINK_JOIN_GROUP, - NM_NETLINK_LISTENER_ERROR_NETLINK_ALLOC_LINK_CACHE, - NM_NETLINK_LISTENER_ERROR_PROCESSING_MESSAGE, - NM_NETLINK_LISTENER_ERROR_BAD_ALLOC, - NM_NETLINK_LISTENER_ERROR_WAITING_FOR_SOCKET_DATA, - NM_NETLINK_LISTENER_ERROR_LINK_CACHE_UPDATE -} NMNetlinkListenerError; - -typedef struct { - GObject parent; -} NMNetlinkListener; - -typedef struct { - GObjectClass parent_class; - - /* Signals */ - void (*notification) (NMNetlinkListener *listener, struct nl_msg *msg); - void (*error) (NMNetlinkListener *listener, GError *error); -} NMNetlinkListenerClass; - -GType nm_netlink_listener_get_type (void) G_GNUC_CONST; -GQuark nm_netlink_listener_error_quark (void) G_GNUC_CONST; - -NMNetlinkListener *nm_netlink_listener_get (void); - -gboolean nm_netlink_listener_subscribe (NMNetlinkListener *listener, - int group, - GError **error); -void nm_netlink_listener_unsubscribe (NMNetlinkListener *listener, - int group); - -G_END_DECLS - -#endif /* NM_NETLINK_LISTENER_H */ diff --git a/src/nm-netlink-monitor.c b/src/nm-netlink-monitor.c index b807d5c37..24b463ce3 100644 --- a/src/nm-netlink-monitor.c +++ b/src/nm-netlink-monitor.c @@ -442,6 +442,28 @@ nm_netlink_monitor_unsubscribe (NMNetlinkMonitor *self, int group) set_subs (self, group, subs); } +/***************************************************************/ + +gboolean +nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *self, GError **error) +{ + NMNetlinkMonitorPrivate *priv; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); + + priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); + + /* FIXME: nl_rtgen_request() gets the return value screwed up with + * libnl-1.1; revisit this and return a proper error when we port to + * a later libnl. + */ + nl_rtgen_request (priv->nlh, RTM_GETLINK, AF_INET6, NLM_F_DUMP); + + return TRUE; +} + + static gboolean deferred_emit_carrier_state (gpointer user_data) { diff --git a/src/nm-netlink-monitor.h b/src/nm-netlink-monitor.h index 1920704a7..a2b26e6b3 100644 --- a/src/nm-netlink-monitor.h +++ b/src/nm-netlink-monitor.h @@ -79,6 +79,8 @@ gboolean nm_netlink_monitor_subscribe (NMNetlinkMonitor *monitor void nm_netlink_monitor_unsubscribe (NMNetlinkMonitor *monitor, int group); +gboolean nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *monitor, + GError **error); gboolean nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor, GError **error);