about summary refs log tree commit diff
path: root/src/nm-device.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2011-04-21 10:42:53 +0200
committerMichael Biebl <biebl@debian.org>2011-04-21 10:42:53 +0200
commit8baa1aca8dfd35e3190d7d5655eb83b5b901e263 (patch)
treea9ac1e67d0c22a48330c76f08fc5291f85307055 /src/nm-device.c
parentf75dd6fd1975146623052b843b182dc32c3fbe46 (diff)
Imported Upstream version 0.8.4.0 upstream/0.8.4.0
Diffstat (limited to 'src/nm-device.c')
-rw-r--r--src/nm-device.c334
1 files changed, 174 insertions, 160 deletions
diff --git a/src/nm-device.c b/src/nm-device.c
index 9b182c4d..8675bf62 100644
--- a/src/nm-device.c
+++ b/src/nm-device.c
@@ -15,7 +15,7 @@
  * 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 - 2011 Red Hat, Inc.
+ * Copyright (C) 2005 - 2010 Red Hat, Inc.
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
@@ -184,8 +184,8 @@ static NMActStageReturn dhcp6_start (NMDevice *self,
                                      NMDeviceStateReason *reason);
 
 static void addrconf6_cleanup (NMDevice *self);
-static void dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release);
-static void dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release);
+static void dhcp6_cleanup (NMDevice *self, gboolean stop);
+static void dhcp4_cleanup (NMDevice *self, gboolean stop);
 
 
 static void
@@ -572,38 +572,6 @@ nm_device_get_best_auto_connection (NMDevice *dev,
 	return NM_DEVICE_GET_CLASS (dev)->get_best_auto_connection (dev, connections, specific_object);
 }
 
-gboolean
-nm_device_complete_connection (NMDevice *self,
-                               NMConnection *connection,
-                               const char *specific_object,
-                               const GSList *existing_connections,
-                               GError **error)
-{
-	gboolean success = FALSE;
-
-	g_return_val_if_fail (self != NULL, FALSE);
-	g_return_val_if_fail (connection != NULL, FALSE);
-
-	if (!NM_DEVICE_GET_CLASS (self)->complete_connection) {
-		g_set_error (error,
-		             NM_DEVICE_INTERFACE_ERROR,
-		             NM_DEVICE_INTERFACE_ERROR_CONNECTION_INVALID,
-		             "Device class %s had no complete_connection method",
-		             G_OBJECT_TYPE_NAME (self));
-		return FALSE;
-	}
-
-	success = NM_DEVICE_GET_CLASS (self)->complete_connection (self,
-	                                                           connection,
-	                                                           specific_object,
-	                                                           existing_connections,
-	                                                           error);
-	if (success)
-		success = nm_connection_verify (connection, error);
-
-	return success;
-}
-
 static void
 dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer user_data)
 {
@@ -1190,8 +1158,6 @@ nm_device_handle_autoip4_event (NMDevice *self,
 			aipd_timeout_remove (self);
 			nm_device_activate_schedule_stage4_ip4_config_get (self);
 			break;
-		case NM_DEVICE_STATE_IP_CHECK:
-		case NM_DEVICE_STATE_SECONDARIES:
 		case NM_DEVICE_STATE_ACTIVATED:
 			priv->aipd_addr = ip.s_addr;
 			if (!handle_autoip_change (self, &reason))
@@ -1503,7 +1469,7 @@ dhcp_timeout (NMDHCPClient *client, gpointer user_data)
 	if (!nm_device_get_act_request (device))
 		return;
 
-	nm_dhcp_client_stop (client, FALSE);
+	nm_dhcp_client_stop (client);
 
 	if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) {
 		if (nm_dhcp_client_get_ipv6 (client))
@@ -1514,84 +1480,15 @@ dhcp_timeout (NMDHCPClient *client, gpointer user_data)
 }
 
 static NMActStageReturn
-dhcp4_start (NMDevice *self,
-             NMConnection *connection,
-             NMDeviceStateReason *reason)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMSettingIP4Config *s_ip4;
-	guint8 *anycast = NULL;
-
-	s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
-
-	if (priv->dhcp_anycast_address)
-		anycast = priv->dhcp_anycast_address->data;
-
-	/* Clear old exported DHCP options */
-	if (priv->dhcp4_config)
-		g_object_unref (priv->dhcp4_config);
-	priv->dhcp4_config = nm_dhcp4_config_new ();
-
-	/* Begin DHCP on the interface */
-	g_warn_if_fail (priv->dhcp4_client == NULL);
-	priv->dhcp4_client = nm_dhcp_manager_start_ip4 (priv->dhcp_manager,
-	                                                nm_device_get_ip_iface (self),
-	                                                nm_connection_get_uuid (connection),
-	                                                s_ip4,
-	                                                priv->dhcp_timeout,
-	                                                anycast);
-	if (!priv->dhcp4_client) {
-		*reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED;
-		return NM_ACT_STAGE_RETURN_FAILURE;
-	}
-
-	priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client,
-	                                            "state-changed",
-	                                            G_CALLBACK (dhcp_state_changed),
-	                                            self);
-	priv->dhcp4_timeout_sigid = g_signal_connect (priv->dhcp4_client,
-	                                              "timeout",
-	                                              G_CALLBACK (dhcp_timeout),
-	                                              self);
-
-	/* DHCP devices will be notified by the DHCP manager when stuff happens */
-	return NM_ACT_STAGE_RETURN_POSTPONE;
-}
-
-gboolean
-nm_device_dhcp4_renew (NMDevice *self, gboolean release)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMActStageReturn ret;
-	NMDeviceStateReason reason;
-	NMActRequest *req;
-	NMConnection *connection;
-
-	g_return_val_if_fail (priv->dhcp4_client != NULL, FALSE);
-
-	/* Terminate old DHCP instance and release the old lease */
-	dhcp4_cleanup (self, TRUE, TRUE);
-
-	req = nm_device_get_act_request (self);
-	g_assert (req);
-	connection = nm_act_request_get_connection (req);
-	g_assert (connection);
-
-	/* Start DHCP again on the interface */
-	ret = dhcp4_start (self, connection, &reason);
-
-	return (ret != NM_ACT_STAGE_RETURN_FAILURE);
-}
-
-static NMActStageReturn
 real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	NMConnection *connection;
+	NMSettingConnection *s_con;
 	NMSettingIP4Config *s_ip4;
 	NMActRequest *req;
 	NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
-	const char *ip_iface, *method = NULL;
+	const char *ip_iface, *method = NULL, *uuid;
 
 	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
@@ -1604,6 +1501,9 @@ real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
 
 	req = nm_device_get_act_request (self);
 	connection = nm_act_request_get_connection (req);
+	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+	uuid = nm_setting_connection_get_uuid (s_con);
 
 	s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
 
@@ -1612,7 +1512,42 @@ real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
 		method = nm_setting_ip4_config_get_method (s_ip4);
 
 	if (!s_ip4 || !method || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
-		ret = dhcp4_start (self, connection, reason);
+		guint8 *anycast = NULL;
+
+		/* Begin a DHCP transaction on the interface */
+
+		if (priv->dhcp_anycast_address)
+			anycast = priv->dhcp_anycast_address->data;
+
+		/* Clear old exported DHCP options */
+		if (priv->dhcp4_config)
+			g_object_unref (priv->dhcp4_config);
+		priv->dhcp4_config = nm_dhcp4_config_new ();
+
+		priv->dhcp4_client = nm_dhcp_manager_start_ip4 (priv->dhcp_manager,
+		                                                ip_iface,
+		                                                uuid,
+		                                                s_ip4,
+		                                                priv->dhcp_timeout,
+		                                                anycast);
+		if (priv->dhcp4_client) {
+			priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client,
+			                                            "state-changed",
+			                                            G_CALLBACK (dhcp_state_changed),
+			                                            self);
+			priv->dhcp4_timeout_sigid = g_signal_connect (priv->dhcp4_client,
+			                                              "timeout",
+			                                              G_CALLBACK (dhcp_timeout),
+			                                              self);
+
+			/* DHCP devices will be notified by the DHCP manager when
+			 * stuff happens.	
+			 */
+			ret = NM_ACT_STAGE_RETURN_POSTPONE;
+		} else {
+			*reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED;
+			ret = NM_ACT_STAGE_RETURN_FAILURE;
+		}
 	} else if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
 		GError *error = NULL;
 		const char *iface = nm_device_get_iface (self);
@@ -1651,6 +1586,8 @@ dhcp6_start (NMDevice *self,
 	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
 	guint8 *anycast = NULL;
 	NMSettingIP6Config *s_ip6;
+	NMSettingConnection *s_con;
+	const char *uuid;
 	const char *ip_iface;
 	const struct in6_addr dest = { { { 0xFF,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
 	int err;
@@ -1680,18 +1617,22 @@ dhcp6_start (NMDevice *self,
 	 */
 	err = nm_system_set_ip6_route (priv->ip_iface ? priv->ip_ifindex : priv->ifindex,
 	                               &dest, 8, NULL, 256, 0, RTPROT_BOOT, RT_TABLE_LOCAL, NULL);
-	if (err) {
+	if (err && (nl_get_errno () != EEXIST)) {
 		nm_log_err (LOGD_DEVICE | LOGD_IP6,
 		            "(%s): failed to add IPv6 multicast route: %s",
 		            priv->ip_iface ? priv->ip_iface : priv->iface, nl_geterror ());
 	}
 
+	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+	uuid = nm_setting_connection_get_uuid (s_con);
+
 	s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
 
 	ip_iface = nm_device_get_ip_iface (self);
 	priv->dhcp6_client = nm_dhcp_manager_start_ip6 (priv->dhcp_manager,
 	                                                ip_iface,
-	                                                nm_connection_get_uuid (connection),
+	                                                uuid,
 	                                                s_ip6,
 	                                                priv->dhcp_timeout,
 	                                                anycast,
@@ -2012,7 +1953,9 @@ nm_device_activate_stage4_ip4_config_get (gpointer user_data)
 	g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
 					   NM_ACT_REQUEST_IP4_CONFIG, ip4_config);
 
+nm_log_info (LOGD_DEVICE | LOGD_IP4, "Scheduling stage 5");
 	nm_device_activate_schedule_stage5_ip_config_commit (self, AF_INET);
+nm_log_info (LOGD_DEVICE | LOGD_IP4, "Done scheduling stage 5");
 
 out:
 	nm_log_info (LOGD_DEVICE | LOGD_IP4,
@@ -2727,7 +2670,7 @@ delayed_transitions_clear (NMDevice *self)
 }
 
 static void
-dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release)
+dhcp4_cleanup (NMDevice *self, gboolean stop)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 
@@ -2750,7 +2693,7 @@ dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release)
 		}
 
 		if (stop)
-			nm_dhcp_client_stop (priv->dhcp4_client, release);
+			nm_dhcp_client_stop (priv->dhcp4_client);
 
 		g_object_unref (priv->dhcp4_client);
 		priv->dhcp4_client = NULL;
@@ -2758,7 +2701,7 @@ dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release)
 }
 
 static void
-dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release)
+dhcp6_cleanup (NMDevice *self, gboolean stop)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 
@@ -2782,7 +2725,7 @@ dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release)
 		}
 
 		if (stop)
-			nm_dhcp_client_stop (priv->dhcp6_client, release);
+			nm_dhcp_client_stop (priv->dhcp6_client);
 
 		g_object_unref (priv->dhcp6_client);
 		priv->dhcp6_client = NULL;
@@ -2808,27 +2751,21 @@ dnsmasq_cleanup (NMDevice *self)
 }
 
 /*
- * nm_device_deactivate
+ * nm_device_deactivate_quickly
  *
- * Remove a device's routing table entries and IP address.
+ * Quickly deactivate a device, for things like sleep, etc.  Doesn't
+ * clean much stuff up, and nm_device_deactivate() should be called
+ * on the device eventually.
  *
  */
-static void
-nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
+gboolean
+nm_device_deactivate_quickly (NMDevice *self)
 {
-	NMDevice *self = NM_DEVICE (device);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
-	gboolean tried_ipv6 = FALSE;
-
-	g_return_if_fail (self != NULL);
+	NMDevicePrivate *priv;
 
-	nm_log_info (LOGD_DEVICE, "(%s): deactivating device (reason: %d).",
-	             nm_device_get_iface (self), reason);
+	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
 
-	/* Save whether or not we tried IPv6 for later */
-	if (NM_DEVICE_GET_PRIVATE (self)->ip6_manager)
-		tried_ipv6 = TRUE;
+	priv = NM_DEVICE_GET_PRIVATE (self);
 
 	/* Break the activation chain */
 	activation_source_clear (self, TRUE, AF_INET);
@@ -2837,8 +2774,8 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
 	/* Clear any delayed transitions */
 	delayed_transitions_clear (self);
 
-	dhcp4_cleanup (self, TRUE, FALSE);
-	dhcp6_cleanup (self, TRUE, FALSE);
+	dhcp4_cleanup (self, TRUE);
+	dhcp6_cleanup (self, TRUE);
 	addrconf6_cleanup (self);
 	dnsmasq_cleanup (self);
 	aipd_cleanup (self);
@@ -2850,12 +2787,39 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
 		nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
 
 	/* Call device type-specific deactivation */
-	if (NM_DEVICE_GET_CLASS (self)->deactivate)
-		NM_DEVICE_GET_CLASS (self)->deactivate (self);
+	if (NM_DEVICE_GET_CLASS (self)->deactivate_quickly)
+		NM_DEVICE_GET_CLASS (self)->deactivate_quickly (self);
 
 	/* Tear down an existing activation request */
 	clear_act_request (self);
 
+	return TRUE;
+}
+
+/*
+ * nm_device_deactivate
+ *
+ * Remove a device's routing table entries and IP address.
+ *
+ */
+static void
+nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
+{
+	NMDevice *self = NM_DEVICE (device);
+	NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
+	gboolean tried_ipv6 = FALSE;
+
+	g_return_if_fail (self != NULL);
+
+	nm_log_info (LOGD_DEVICE, "(%s): deactivating device (reason: %d).",
+	             nm_device_get_iface (self), reason);
+
+	/* Check this before deactivate_quickly is run */
+	if (NM_DEVICE_GET_PRIVATE (self)->ip6_manager)
+		tried_ipv6 = TRUE;
+
+	nm_device_deactivate_quickly (self);
+
 	/* Take out any entries in the routing table and any IP address the device had. */
 	nm_system_device_flush_routes (self, tried_ipv6 ? AF_UNSPEC : AF_INET);
 	nm_system_device_flush_addresses (self, tried_ipv6 ? AF_UNSPEC : AF_INET);
@@ -2864,6 +2828,10 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
 	/* Clean up nameservers and addresses */
 	nm_device_set_ip4_config (self, NULL, FALSE, &ignored);
 	nm_device_set_ip6_config (self, NULL, FALSE, &ignored);
+
+	/* Call device type-specific deactivation */
+	if (NM_DEVICE_GET_CLASS (self)->deactivate)
+		NM_DEVICE_GET_CLASS (self)->deactivate (self);
 }
 
 static gboolean
@@ -2890,6 +2858,31 @@ check_connection_compatible (NMDeviceInterface *dev_iface,
 	return TRUE;
 }
 
+static void
+connection_secrets_updated_cb (NMActRequest *req,
+                               NMConnection *connection,
+                               GSList *updated_settings,
+                               RequestSecretsCaller caller,
+                               gpointer user_data)
+{
+	NMDevice *self = NM_DEVICE (user_data);
+
+	if (NM_DEVICE_GET_CLASS (self)->connection_secrets_updated)
+		NM_DEVICE_GET_CLASS (self)->connection_secrets_updated (self, connection, updated_settings, caller);
+}
+
+static void
+connection_secrets_failed_cb (NMActRequest *req,
+                              NMConnection *connection,
+                              const char *setting_name,
+                              RequestSecretsCaller caller,
+                              gpointer user_data)
+{
+	NMDevice *self = NM_DEVICE (user_data);
+
+	nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS);
+}
+
 static gboolean
 device_activation_precheck (NMDevice *self, NMConnection *connection, GError **error)
 {
@@ -2932,6 +2925,14 @@ nm_device_activate (NMDeviceInterface *device,
 	}
 
 	priv->act_request = g_object_ref (req);
+	priv->secrets_updated_id = g_signal_connect (req,
+										"connection-secrets-updated",
+										G_CALLBACK (connection_secrets_updated_cb),
+										device);
+	priv->secrets_failed_id = g_signal_connect (req,
+									    "connection-secrets-failed",
+									    G_CALLBACK (connection_secrets_failed_cb),
+									    device);
 
 	if (!nm_act_request_get_assumed (req)) {
 		/* HACK: update the state a bit early to avoid a race between the 
@@ -2963,20 +2964,29 @@ gboolean
 nm_device_is_activating (NMDevice *device)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-	NMDeviceState state;
 
 	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
 
-	state = nm_device_get_state (device);
-	if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES)
+	switch (nm_device_get_state (device)) {
+	case NM_DEVICE_STATE_PREPARE:
+	case NM_DEVICE_STATE_CONFIG:
+	case NM_DEVICE_STATE_NEED_AUTH:
+	case NM_DEVICE_STATE_IP_CONFIG:
 		return TRUE;
+		break;
+	default:
+		break;
+	}
 
 	/* There's a small race between the time when stage 1 is scheduled
 	 * and when the device actually sets STATE_PREPARE when the activation
 	 * handler is actually run.  If there's an activation handler scheduled
 	 * we're activating anyway.
 	 */
-	return priv->act_source_id ? TRUE : FALSE;
+	if (priv->act_source_id)
+		return TRUE;
+
+	return FALSE;
 }
 
 
@@ -3323,8 +3333,10 @@ dispose (GObject *object)
 	    NMSettingIP4Config *s_ip4 = NULL;
 		const char *method = NULL;
 
+		/* Only system connections can be left up */
 		connection = nm_act_request_get_connection (priv->act_request);
-		if (connection) {
+		if (   connection
+		    && (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM)) {
 
 			/* Only static or DHCP IPv4 connections can be left up.
 			 * All IPv6 connections can be left up, so we don't have
@@ -3344,8 +3356,8 @@ dispose (GObject *object)
 	delayed_transitions_clear (self);
 
 	/* Clean up and stop DHCP */
-	dhcp4_cleanup (self, take_down, FALSE);
-	dhcp6_cleanup (self, take_down, FALSE);
+	dhcp4_cleanup (self, take_down);
+	dhcp6_cleanup (self, take_down);
 	addrconf6_cleanup (self);
 	dnsmasq_cleanup (self);
 
@@ -3450,12 +3462,6 @@ set_property (GObject *object, guint prop_id,
 	}
 }
 
-static gboolean
-_is_connected (NMDeviceState state)
-{
-	return (state >= NM_DEVICE_STATE_IP_CONFIG && state <= NM_DEVICE_STATE_DEACTIVATING);
-}
-
 static void
 get_property (GObject *object, guint prop_id,
 			  GValue *value, GParamSpec *pspec)
@@ -3474,7 +3480,7 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_string (value, priv->iface);
 		break;
 	case NM_DEVICE_INTERFACE_PROP_IP_IFACE:
-		if (_is_connected (state))
+		if ((state == NM_DEVICE_STATE_ACTIVATED) || (state == NM_DEVICE_STATE_IP_CONFIG))
 			g_value_set_string (value, nm_device_get_ip_iface (self));
 		else
 			g_value_set_string (value, NULL);
@@ -3492,25 +3498,33 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_uint (value, priv->ip4_address);
 		break;
 	case NM_DEVICE_INTERFACE_PROP_IP4_CONFIG:
-		if (_is_connected (state) && priv->ip4_config)
-			g_value_set_boxed (value, nm_ip4_config_get_dbus_path (priv->ip4_config));
-		else
-			g_value_set_boxed (value, "/");
+		if ((state == NM_DEVICE_STATE_ACTIVATED) || (state == NM_DEVICE_STATE_IP_CONFIG)) {
+			if (priv->ip4_config) {
+				g_value_set_boxed (value, nm_ip4_config_get_dbus_path (priv->ip4_config));
+				break;
+			}
+		}
+		g_value_set_boxed (value, "/");
 		break;
 	case NM_DEVICE_INTERFACE_PROP_DHCP4_CONFIG:
-		if (_is_connected (state) && priv->dhcp4_client)
+		if (   ((state == NM_DEVICE_STATE_ACTIVATED) || (state == NM_DEVICE_STATE_IP_CONFIG))
+		    && 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 NM_DEVICE_INTERFACE_PROP_IP6_CONFIG:
-		if (_is_connected (state) && priv->ip6_config)
-			g_value_set_boxed (value, nm_ip6_config_get_dbus_path (priv->ip6_config));
-		else
-			g_value_set_boxed (value, "/");
+		if ((state == NM_DEVICE_STATE_ACTIVATED) || (state == NM_DEVICE_STATE_IP_CONFIG)) {
+			if (priv->ip6_config) {
+				g_value_set_boxed (value, nm_ip6_config_get_dbus_path (priv->ip6_config));
+				break;
+			}
+		}
+		g_value_set_boxed (value, "/");
 		break;
 	case NM_DEVICE_INTERFACE_PROP_DHCP6_CONFIG:
-		if (_is_connected (state) && priv->dhcp6_client)
+		if (   ((state == NM_DEVICE_STATE_ACTIVATED) || (state == NM_DEVICE_STATE_IP_CONFIG))
+		    && priv->dhcp6_client)
 			g_value_set_boxed (value, nm_dhcp6_config_get_dbus_path (priv->dhcp6_config));
 		else
 			g_value_set_boxed (value, "/");
@@ -3863,7 +3877,7 @@ spec_match_list (NMDeviceInterface *device, const GSList *specs)
 static NMConnection *
 connection_match_config (NMDeviceInterface *device, const GSList *connections)
 {
-	g_return_val_if_fail (device != NULL, NULL);
+	g_return_val_if_fail (device != NULL, FALSE);
 
 	if (NM_DEVICE_GET_CLASS (device)->connection_match_config)
 		return NM_DEVICE_GET_CLASS (device)->connection_match_config (NM_DEVICE (device), connections);