netlink: fix IPv6 RA flag retrieval
authorDan Williams <dcbw@redhat.com>
Tue, 20 Apr 2010 23:46:08 +0000 (16:46 -0700)
committerDan Williams <dcbw@redhat.com>
Tue, 20 Apr 2010 23:46:08 +0000 (16:46 -0700)
The RA flags aren't in the link flags, they are in the special
PROTINFO flags that the IPv6 stack sends.  To get these, because
libnl doesn't have native support for them, we get to parse the
netlink messages directly.  Furthermore, the PROTINFO message
isn't sent unless it's explicitly requested with a
RTM_GETLINK/AF_INET6 message, meaning we get to poll for it
periodically.

So switch over to the netlink monitor object (killing a lot of
duplicate code) and start requesting the PROTINFO bits from
netlink.

src/ip6-manager/Makefile.am
src/ip6-manager/nm-ip6-manager.c
src/ip6-manager/nm-netlink-listener.c [deleted file]
src/ip6-manager/nm-netlink-listener.h [deleted file]
src/nm-netlink-monitor.c
src/nm-netlink-monitor.h

index 39d7715..c2f5591 100644 (file)
@@ -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) \
index be85ab0..04a3049 100644 (file)
@@ -25,7 +25,8 @@
 #include <netlink/route/route.h>
 
 #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 (file)
index 55c4d76..0000000
+++ /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, <david@fubar.dk>
- * Copyright (C) 2004 Novell, Inc.
- */
-
-/* FIXME: this should be merged with src/nm-netlink-monitor.c */
-
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/types.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/if.h>
-#include <linux/unistd.h>
-#include <unistd.h>
-#include <stdio.h>
-
-#include <glib.h>
-#include <glib/gi18n.h>
-
-#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 (file)
index 0baabac..0000000
+++ /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 <glib.h>
-#include <glib-object.h>
-
-#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 */
index b807d5c..24b463c 100644 (file)
@@ -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)
 {
index 1920704..a2b26e6 100644 (file)
@@ -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);