From 88c490b3a743dcfdc0dc071b7a7055f1468719f5 Mon Sep 17 00:00:00 2001
From: Alexandru Costache <alexandrux.costache@intel.com>
Date: Wed, 2 Jul 2014 09:23:38 -0400
Subject: [PATCH] dhcp: Fix further crashes when connected to network without
 dhcp

There are several crashing conditions in dhcp_retry_cb() and in
ipv4ll_available_cb(), when service is NULL or dhcp->network is
either NULL or has been freed. Fixed all by removing timeout and
ipv4ll callback when invalidating dhcp.
---
 src/dhcp.c |   40 +++++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/src/dhcp.c b/src/dhcp.c
index e4bac67..70a7d96 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -70,6 +70,20 @@ static void dhcp_free(struct connman_dhcp *dhcp)
 	g_free(dhcp);
 }
 
+static void ipv4ll_stop_client(struct connman_dhcp *dhcp)
+{
+	if (!dhcp->ipv4ll_client)
+		return;
+
+	g_dhcp_client_stop(dhcp->ipv4ll_client);
+	g_dhcp_client_unref(dhcp->ipv4ll_client);
+	dhcp->ipv4ll_client = NULL;
+	ipv4ll_running = false;
+
+	g_free(dhcp->ipv4ll_debug_prefix);
+	dhcp->ipv4ll_debug_prefix = NULL;
+}
+
 /**
  * dhcp_invalidate: Invalidate an existing DHCP lease
  * @dhcp: pointer to the DHCP lease to invalidate.
@@ -132,6 +146,14 @@ static void dhcp_invalidate(struct connman_dhcp *dhcp, bool callback)
 	__connman_ipconfig_set_gateway(ipconfig, NULL);
 	__connman_ipconfig_set_prefixlen(ipconfig, 0);
 
+	if (dhcp->timeout > 0) {
+		g_source_remove(dhcp->timeout);
+		dhcp->timeout = 0;
+	}
+
+	if (ipv4ll_running)
+		ipv4ll_stop_client(dhcp);
+
 	if (dhcp->callback && callback) {
 		g_hash_table_remove(network_table, dhcp->network);
 		network_removed = true;
@@ -157,20 +179,6 @@ static void dhcp_debug(const char *str, void *data)
 	connman_info("%s: %s", (const char *) data, str);
 }
 
-static void ipv4ll_stop_client(struct connman_dhcp *dhcp)
-{
-	if (!dhcp->ipv4ll_client)
-		return;
-
-	g_dhcp_client_stop(dhcp->ipv4ll_client);
-	g_dhcp_client_unref(dhcp->ipv4ll_client);
-	dhcp->ipv4ll_client = NULL;
-	ipv4ll_running = false;
-
-	g_free(dhcp->ipv4ll_debug_prefix);
-	dhcp->ipv4ll_debug_prefix = NULL;
-}
-
 static void ipv4ll_lost_cb(GDHCPClient *dhcp_client, gpointer user_data);
 static void ipv4ll_available_cb(GDHCPClient *ipv4ll_client, gpointer user_data);
 
@@ -574,8 +582,10 @@ static int dhcp_release(struct connman_dhcp *dhcp)
 {
 	DBG("dhcp %p", dhcp);
 
-	if (dhcp->timeout > 0)
+	if (dhcp->timeout > 0) {
 		g_source_remove(dhcp->timeout);
+		dhcp->timeout = 0;
+	}
 
 	if (dhcp->dhcp_client) {
 		g_dhcp_client_stop(dhcp->dhcp_client);
-- 
1.7.10.4

