Blob Blame History Raw
commit 09bde40f02c2a02f9503ca0ae430753ca81c1792
Author: Dan Williams <dcbw@redhat.com>
Date:   Wed Oct 9 13:55:05 2013 -0500

    core: fix PropertiesChanged signals for IP-related properties
    
    To present a consistent API to clients, the IP-related properties
    are only valid when the device has finished IP configuration.  But
    they are set before that happens, and their change notifications
    were emitted before the IP configuration was considered valid.
    Re-emit the change notifications when the device enters the IP_CHECK
    state (and thus has IP configuration) and also when the device
    deactivates to enusre clients have up-to-date IP-related property
    information.
    
    For the changes to has_ip_config(), the priv->ipX_state checks are
    not necessary since the device will have valid IP configuration
    when it enters the IP_CHECK state.  The other checks can be
    consolidated into a single statement.
    
    Acked-by: Dan Winship

diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 6810afc..4d61c6a 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -5282,18 +5282,11 @@ set_property (GObject *object, guint prop_id,
 }
 
 static gboolean
-has_ip_config (NMDevice *self)
+ip_config_valid (NMDeviceState state)
 {
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->ip4_state != IP_DONE && priv->ip6_state != IP_DONE)
-		return FALSE;
-
-	if (priv->state == NM_DEVICE_STATE_UNMANAGED)
-		return TRUE;
-
-	return (priv->state >= NM_DEVICE_STATE_IP_CONFIG
-	        && priv->state <= NM_DEVICE_STATE_DEACTIVATING);
+	return (state == NM_DEVICE_STATE_UNMANAGED) ||
+	        (state >= NM_DEVICE_STATE_IP_CHECK &&
+	         state <= NM_DEVICE_STATE_DEACTIVATING);
 }
 
 static void
@@ -5315,7 +5308,7 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_string (value, priv->iface);
 		break;
 	case PROP_IP_IFACE:
-		if (has_ip_config (self))
+		if (ip_config_valid (priv->state))
 			g_value_set_string (value, nm_device_get_ip_iface (self));
 		else
 			g_value_set_string (value, NULL);
@@ -5342,25 +5335,25 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_boolean (value, priv->carrier);
 		break;
 	case PROP_IP4_CONFIG:
-		if (has_ip_config (self) && priv->ip4_config)
+		if (ip_config_valid (priv->state) && priv->ip4_config)
 			g_value_set_boxed (value, nm_ip4_config_get_dbus_path (priv->ip4_config));
 		else
 			g_value_set_boxed (value, "/");
 		break;
 	case PROP_DHCP4_CONFIG:
-		if (has_ip_config (self) && priv->dhcp4_client)
+		if (ip_config_valid (priv->state) && priv->dhcp4_client)
 			g_value_set_boxed (value, nm_dhcp4_config_get_dbus_path (priv->dhcp4_config));
 		else
 			g_value_set_boxed (value, "/");
 		break;
 	case PROP_IP6_CONFIG:
-		if (has_ip_config (self) && priv->ip6_config)
+		if (ip_config_valid (priv->state) && priv->ip6_config)
 			g_value_set_boxed (value, nm_ip6_config_get_dbus_path (priv->ip6_config));
 		else
 			g_value_set_boxed (value, "/");
 		break;
 	case PROP_DHCP6_CONFIG:
-		if (has_ip_config (self) && priv->dhcp6_client)
+		if (ip_config_valid (priv->state) && priv->dhcp6_client)
 			g_value_set_boxed (value, nm_dhcp6_config_get_dbus_path (priv->dhcp6_config));
 		else
 			g_value_set_boxed (value, "/");
@@ -5918,6 +5911,16 @@ state_implies_pending_action (NMDeviceState state)
 	return "unknown";
 }
 
+static void
+notify_ip_properties (NMDevice *device)
+{
+	g_object_notify (G_OBJECT (device), NM_DEVICE_IP_IFACE);
+	g_object_notify (G_OBJECT (device), NM_DEVICE_IP4_CONFIG);
+	g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP4_CONFIG);
+	g_object_notify (G_OBJECT (device), NM_DEVICE_IP6_CONFIG);
+	g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP6_CONFIG);
+}
+
 void
 nm_device_state_changed (NMDevice *device,
                          NMDeviceState state,
@@ -6077,6 +6080,11 @@ nm_device_state_changed (NMDevice *device,
 		break;
 	case NM_DEVICE_STATE_IP_CHECK:
 		nm_device_start_ip_check (device);
+
+		/* IP-related properties are only valid when the device has IP configuration;
+		 * now that it does, ensure their change notifications are emitted.
+		 */
+		notify_ip_properties (device);
 		break;
 	case NM_DEVICE_STATE_SECONDARIES:
 		ip_check_gw_ping_cleanup (device);
@@ -6093,6 +6101,12 @@ nm_device_state_changed (NMDevice *device,
 	if (old_state == NM_DEVICE_STATE_ACTIVATED)
 		nm_dispatcher_call (DISPATCHER_ACTION_DOWN, nm_act_request_get_connection (req), device, NULL, NULL);
 
+	/* IP-related properties are only valid when the device has IP configuration.
+	 * If it no longer does, ensure their change notifications are emitted.
+	 */
+	if (ip_config_valid (old_state) && !ip_config_valid (state))
+	    notify_ip_properties (device);
+
 	/* Dispose of the cached activation request */
 	if (req)
 		g_object_unref (req);