Index: NetworkManager-1.0.12/src/dhcp-manager/nm-dhcp-client.c
===================================================================
--- NetworkManager-1.0.12.orig/src/dhcp-manager/nm-dhcp-client.c
+++ NetworkManager-1.0.12/src/dhcp-manager/nm-dhcp-client.c
@@ -52,7 +52,6 @@ typedef struct {
 
 	NMDhcpState  state;
 	pid_t        pid;
-	guint        timeout_id;
 	guint        watch_id;
 	gboolean     info_only;
 
@@ -227,17 +226,6 @@ reason_to_state (const char *iface, cons
 /********************************************/
 
 static void
-timeout_cleanup (NMDhcpClient *self)
-{
-	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
-
-	if (priv->timeout_id) {
-		g_source_remove (priv->timeout_id);
-		priv->timeout_id = 0;
-	}
-}
-
-static void
 watch_cleanup (NMDhcpClient *self)
 {
 	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
@@ -287,8 +275,6 @@ nm_dhcp_client_set_state (NMDhcpClient *
 	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
 	gs_free char *event_id = NULL;
 
-	if (new_state >= NM_DHCP_STATE_BOUND)
-		timeout_cleanup (self);
 	if (new_state >= NM_DHCP_STATE_TIMEOUT)
 		watch_cleanup (self);
 
@@ -297,9 +283,6 @@ nm_dhcp_client_set_state (NMDhcpClient *
 		          || (!priv->ipv6 && NM_IS_IP4_CONFIG (ip_config)));
 		g_assert (options);
 		g_assert_cmpint (g_hash_table_size (options), >, 0);
-	} else {
-		g_assert (ip_config == NULL);
-		g_assert (options == NULL);
 	}
 
 	/* The client may send same-state transitions for RENEW/REBIND events and
@@ -307,7 +290,7 @@ nm_dhcp_client_set_state (NMDhcpClient *
 	 * BOUND state.  Ignore same-state transitions for other events since
 	 * the lease won't have changed and the state was already handled.
 	 */
-	if ((priv->state == new_state) && (new_state != NM_DHCP_STATE_BOUND))
+	if ((priv->state == new_state) && (new_state != NM_DHCP_STATE_BOUND) && (new_state != NM_DHCP_STATE_TIMEOUT))
 		return;
 
 	if (priv->ipv6 && new_state == NM_DHCP_STATE_BOUND) {
@@ -336,21 +319,6 @@ nm_dhcp_client_set_state (NMDhcpClient *
 	               event_id);
 }
 
-static gboolean
-daemon_timeout (gpointer user_data)
-{
-	NMDhcpClient *self = NM_DHCP_CLIENT (user_data);
-	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
-
-	priv->timeout_id = 0;
-	nm_log_warn (priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4,
-	             "(%s): DHCPv%c request timed out.",
-	             priv->iface,
-	             priv->ipv6 ? '6' : '4');
-	nm_dhcp_client_set_state (self, NM_DHCP_STATE_TIMEOUT, NULL, NULL);
-	return G_SOURCE_REMOVE;
-}
-
 static void
 daemon_watch_cb (GPid pid, gint status, gpointer user_data)
 {
@@ -396,11 +364,6 @@ nm_dhcp_client_watch_child (NMDhcpClient
 	g_return_if_fail (priv->pid == -1);
 	priv->pid = pid;
 
-	/* Set up a timeout on the transaction to kill it after the timeout */
-	g_assert (priv->timeout_id == 0);
-	priv->timeout_id = g_timeout_add_seconds (priv->timeout,
-	                                          daemon_timeout,
-	                                          self);
 	g_assert (priv->watch_id == 0);
 	priv->watch_id = g_child_watch_add (pid, daemon_watch_cb, self);
 }
@@ -772,7 +735,7 @@ nm_dhcp_client_handle_event (gpointer un
 	nm_log_dbg (LOGD_DHCP, "(%s): DHCP reason '%s' -> state '%s'",
 	            iface, reason, state_to_string (new_state));
 
-	if (new_state == NM_DHCP_STATE_BOUND) {
+	if (new_state == NM_DHCP_STATE_BOUND || new_state == NM_DHCP_STATE_TIMEOUT) {
 		/* Copy options */
 		str_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 		g_hash_table_foreach (options, (GHFunc) copy_option, str_options);
@@ -856,7 +819,7 @@ set_property (GObject *object, guint pro
 			  const GValue *value, GParamSpec *pspec)
 {
 	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (object);
- 
+
 	switch (prop_id) {
 	case PROP_IFACE:
 		/* construct-only */
@@ -904,7 +867,6 @@ dispose (GObject *object)
 	 */
 
 	watch_cleanup (self);
-	timeout_cleanup (self);
 
 	g_clear_pointer (&priv->iface, g_free);
 	g_clear_pointer (&priv->hostname, g_free);
Index: NetworkManager-1.0.12/src/devices/nm-device.c
===================================================================
--- NetworkManager-1.0.12.orig/src/devices/nm-device.c
+++ NetworkManager-1.0.12/src/devices/nm-device.c
@@ -3593,7 +3593,21 @@ dhcp4_state_changed (NMDhcpClient *clien
 		}
 		break;
 	case NM_DHCP_STATE_TIMEOUT:
-		dhcp4_fail (self, TRUE);
+		/* If got valid ip config from recorded lease file */
+		if (!ip4_config) {
+			_LOGI (LOGD_DHCP4, "DHCP timed out and no valid lease file is available.");
+			dhcp4_fail (self, TRUE);
+		} else {
+			_LOGI (LOGD_DHCP4, "DHCP timed out, but valid lease file exists.");
+			dhcp4_update_config (self, priv->dhcp4_config, options);
+
+			if (priv->ip4_state == IP_CONF)
+				nm_device_activate_schedule_ip4_config_result (self, ip4_config);
+			else if (priv->ip4_state == IP_DONE) {
+				dhcp4_lease_change (self, ip4_config);
+				nm_device_update_metered (self);
+			}
+		}
 		break;
 	case NM_DHCP_STATE_EXPIRE:
 		/* Ignore expiry before we even have a lease (NAK, old lease, etc) */
@@ -4314,7 +4328,22 @@ dhcp6_state_changed (NMDhcpClient *clien
 			dhcp6_lease_change (self);
 		break;
 	case NM_DHCP_STATE_TIMEOUT:
-		dhcp6_timeout (self, client);
+        if (ip6_config) {
+            priv->dhcp6_ip6_config = g_object_ref (ip6_config);
+            dhcp6_update_config (self, priv->dhcp6_config, options);
+            g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
+
+		    if (priv->ip6_state == IP_CONF) {
+			    if (priv->dhcp6_ip6_config == NULL) {
+				    /* FIXME: Initial DHCP failed; should we fail IPv6 entirely then? */
+				    nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DHCP_FAILED);
+				    break;
+			    }
+			    nm_device_activate_schedule_ip6_config_result (self);
+		    } else if (priv->ip6_state == IP_DONE)
+			    dhcp6_lease_change (self);
+        } else
+            dhcp6_timeout (self, client);
 		break;
 	case NM_DHCP_STATE_EXPIRE:
 		/* Ignore expiry before we even have a lease (NAK, old lease, etc) */
