ipv6: fix incorrect address config signal emission
authorDan Williams <dcbw@redhat.com>
Tue, 20 Oct 2009 18:23:10 +0000 (11:23 -0700)
committerDan Williams <dcbw@redhat.com>
Tue, 20 Oct 2009 18:23:10 +0000 (11:23 -0700)
device->want_signal was never set to TRUE when addrconf was started,
causing random netlink events (say for link-local address addition
or removal) to trigger the config-changed signal from
nm_ip6_device_sync_from_netlink() at the wrong time.  This would
cause IPv6 address configuration to look like it succeeded, when
in fact the config timeout was still in-force.  Thus device
activation would proceed if IPv4 was enabled, but a few seconds later
the device would be deactivated due to the still active IPv6
timeout.

So fix that and clarify when the events from the IPv6 manager happen,
and what the want_signal variable is really for.

src/ip6-manager/nm-ip6-manager.c
src/ip6-manager/nm-ip6-manager.h

index 8908c86..f41169c 100644 (file)
@@ -78,7 +78,7 @@ typedef struct {
 
        NMIP6DeviceState state;
        NMIP6DeviceState target_state;
-       gboolean want_signal;
+       gboolean addrconf_complete;
 
        GArray *rdnss_servers;
        guint rdnss_timeout_id;
@@ -241,7 +241,7 @@ finish_addrconf (gpointer user_data)
        char *iface_copy;
 
        device->finish_addrconf_id = 0;
-       device->want_signal = FALSE;
+       device->addrconf_complete = TRUE;
 
        if (device->state >= device->target_state) {
                g_signal_emit (manager, signals[ADDRCONF_COMPLETE], 0,
@@ -368,7 +368,7 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed)
 //     if (flags & (IF_RA_MANAGED | IF_RA_OTHERCONF))
 //             device->need_dhcp = TRUE;
 
-       if (device->want_signal) {
+       if (!device->addrconf_complete) {
                if (device->state >= device->target_state ||
                        device->state == NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT) {
                        /* device->finish_addrconf_id may currently be a timeout
@@ -466,7 +466,7 @@ process_prefix (NMIP6Manager *manager, struct nl_msg *msg)
        pmsg = (struct prefixmsg *) NLMSG_DATA (nlmsg_hdr (msg));
        device = nm_ip6_manager_get_device (manager, pmsg->prefix_ifindex);
 
-       if (!device || !device->want_signal)
+       if (!device || device->addrconf_complete)
                return NULL;
 
        return device;
@@ -728,6 +728,8 @@ nm_ip6_manager_begin_addrconf (NMIP6Manager *manager,
 
        nm_info ("Activation (%s) Beginning IP6 addrconf.", iface);
 
+       device->addrconf_complete = FALSE;
+
        /* Set up a timeout on the transaction to kill it after the timeout */
        device->finish_addrconf_id = g_timeout_add_seconds (NM_IP6_TIMEOUT,
                                                                                                                finish_addrconf,
index 2c79a45..33b2b98 100644 (file)
@@ -43,8 +43,16 @@ typedef struct {
        GObjectClass parent;
 
        /* Signals */
+
+       /* addrconf_complete is emitted only during initial configuration to indicate
+        * that the initial configuration is complete.
+        */
        void (*addrconf_complete) (NMIP6Manager *manager, char *iface, gboolean success);
 
+       /* config_changed gets emitted only *after* initial configuration is
+        * complete; it's like DHCP renew and indicates that the existing config
+        * of the interface has changed.
+        */
        void (*config_changed)    (NMIP6Manager *manager, char *iface);
 } NMIP6ManagerClass;