diff -r 2d298bca0d0a crm/cib/io.c
--- a/crm/cib/io.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/crm/cib/io.c	Fri Feb 09 15:05:29 2007 +0100
@@ -121,7 +121,8 @@ validate_cib_digest(crm_data_t *local_ci
 	crm_malloc0(expected, (length+1));
 	read_len = fread(expected, 1, length, expected_strm);
 	CRM_ASSERT(read_len == length);
-
+	fclose(expected_strm);
+	
 	if(expected == NULL) {
 		crm_err("On-disk digest is empty");
 		
@@ -635,6 +636,8 @@ write_cib_contents(gpointer p)
 		 epoch?epoch:"0", updates?updates:"0", digest);	
 	
 	rc = write_cib_digest(the_cib, digest);
+	crm_free(digest);
+
 	if(rc <= 0) {
 		crm_err("Digest couldn't be written to disk");
 		exit(LSB_EXIT_GENERIC);
@@ -650,7 +653,6 @@ write_cib_contents(gpointer p)
 		exit(LSB_EXIT_OK);
 	}
 	
-	crm_free(digest);
 	return HA_OK;
 }
 
diff -r 2d298bca0d0a crm/crmd/callbacks.c
--- a/crm/crmd/callbacks.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/crm/crmd/callbacks.c	Fri Feb 09 15:05:29 2007 +0100
@@ -410,28 +410,33 @@ crmd_client_status_callback(const char *
 	trigger_fsa(fsa_source);
 }
 
-static void
+void
 crmd_ipc_connection_destroy(gpointer user_data)
 {
+	GCHSource *source = NULL;
 	crmd_client_t *client = user_data;
 
 	if(client == NULL) {
 		crm_debug_4("No client to delete");
 		return;
 	}
-	
-	if(client->client_source != NULL) {
-		crm_debug_4("Deleting %s (%p) from mainloop",
-			    client->uuid, client->client_source);
-		G_main_del_IPC_Channel(client->client_source); 
-		client->client_source = NULL;
-	}
-
-	crm_debug_3("Freeing %s client", client->uuid);
-	crm_free(client->table_key);
-	crm_free(client->sub_sys);
-	crm_free(client->uuid);
-	crm_free(client);
+
+	source = client->client_source;
+	client->client_source = NULL;
+	crm_debug_3("Processing %s (%p)", client->uuid, source);
+	if(source != NULL) {
+		crm_debug_2("Deleting %s (%p) from mainloop",
+			    client->uuid, source);
+		/* this will re-call crmd_ipc_connection_destroy() */
+		G_main_del_IPC_Channel(source);
+
+	} else {
+		crm_debug_2("Freeing %s client", client->uuid);
+		crm_free(client->table_key);
+		crm_free(client->sub_sys);
+		crm_free(client->uuid);
+		crm_free(client);
+	}
 
 	return;
 }
@@ -604,11 +609,7 @@ crmd_ccm_msg_callback(
 			trigger_transition?A_TE_CANCEL:A_NOTHING,
 			FALSE, __FUNCTION__);
 		
-		if (event_data->oc) {
-			crm_free(event_data->oc);
-			event_data->oc = NULL;
-		}
-		crm_free(event_data);
+		delete_ccm_data(event_data);
 	} 
 	
 	oc_ev_callback_done(cookie);
diff -r 2d298bca0d0a crm/crmd/ccm.c
--- a/crm/crmd/ccm.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/crm/crmd/ccm.c	Fri Feb 09 15:05:30 2007 +0100
@@ -49,7 +49,6 @@ void crmd_ccm_msg_callback(oc_ed_t event
 			     size_t size,
 			     const void *data);
 
-gboolean ghash_node_clfree(gpointer key, gpointer value, gpointer user_data);
 void ghash_update_cib_node(gpointer key, gpointer value, gpointer user_data);
 
 #define CCM_EVENT_DETAIL 0
@@ -446,22 +445,9 @@ do_ccm_update_cache(long long action,
 		    g_hash_table_size(fsa_membership_copy->members),
 		    g_hash_table_size(fsa_membership_copy->new_members),
 		    g_hash_table_size(fsa_membership_copy->dead_members));
-	
-	/* Free the old copy */
-	if(tmp != NULL) {
-		if(tmp->members != NULL)
-			g_hash_table_foreach_remove(
-				tmp->members, ghash_node_clfree, NULL);
-		if(tmp->new_members != NULL)
-			g_hash_table_foreach_remove(
-				tmp->new_members, ghash_node_clfree, NULL);
-		if(tmp->dead_members != NULL)
-			g_hash_table_foreach_remove(
-				tmp->dead_members, ghash_node_clfree, NULL);
-		crm_free(tmp);
-	}
-	crm_debug_3("Free'd old copies");
-
+
+	free_ccm_cache(tmp);
+	
 	set_bit_inplace(fsa_input_register, R_CCM_DATA);
 
 	if(cur_state != S_STOPPING) {
@@ -680,15 +666,4 @@ ghash_update_cib_node(gpointer key, gpoi
 	free_xml(tmp1);
 }
 
-gboolean
-ghash_node_clfree(gpointer key, gpointer value, gpointer user_data)
-{
-	/* value->node_uname is free'd as "key" */
-	if(key != NULL) {
-		crm_free(key);
-	}
-	if(value != NULL) {
-		crm_free(value);
-	}
-	return TRUE;
-}
+
diff -r 2d298bca0d0a crm/crmd/crmd_callbacks.h
--- a/crm/crmd/crmd_callbacks.h	Thu Jan 11 18:42:41 2007 -0700
+++ b/crm/crmd/crmd_callbacks.h	Fri Feb 09 15:05:30 2007 +0100
@@ -29,6 +29,8 @@ extern void crmd_ccm_msg_callback(
  * Returning FALSE means "we're all done, close the connection"
  */
 
+extern void crmd_ipc_connection_destroy(gpointer user_data);
+
 extern gboolean crmd_ha_msg_dispatch(
 	ll_cluster_t *cluster_conn, gpointer user_data);
 
diff -r 2d298bca0d0a crm/crmd/crmd_utils.h
--- a/crm/crmd/crmd_utils.h	Thu Jan 11 18:42:41 2007 -0700
+++ b/crm/crmd/crmd_utils.h	Fri Feb 09 15:05:30 2007 +0100
@@ -23,6 +23,9 @@
 #include <crm/common/xml.h>
 
 #define CLIENT_EXIT_WAIT 30
+
+extern void free_ccm_cache(oc_node_list_t *tmp);
+extern void delete_ccm_data(struct crmd_ccm_data_s *ccm_input);
 
 extern void process_client_disconnect(crmd_client_t *curr_client);
 
diff -r 2d298bca0d0a crm/crmd/lrm.c
--- a/crm/crmd/lrm.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/crm/crmd/lrm.c	Fri Feb 09 15:05:30 2007 +0100
@@ -358,7 +358,6 @@ get_rsc_metadata(const char *type, const
 	metadata = g_hash_table_lookup(meta_hash, key);
 	if(metadata) {
 		crm_debug_2("Returning cached metadata for %s", key);
-		crm_free(key);
 		goto out;
 	}
 
@@ -368,14 +367,15 @@ get_rsc_metadata(const char *type, const
 
 	if(metadata) {
  		g_hash_table_insert(meta_hash, key, metadata);
-	}
+		key = NULL; /* prevent it from being free'd */
+
+	} else {
+		crm_warn("No metadata found for %s", key);
+	}		
 
   out:
-	if(metadata == NULL) {
-		crm_warn("No metadata found for %s::%s:%s",
-			 class, type, provider);
-	}
-	
+	
+	crm_free(key);
 	return metadata;
 }
 
@@ -429,7 +429,9 @@ get_rsc_restart_list(lrm_rsc_t *rsc, lrm
 	return restart_list;
 }
 
-static void
+void append_restart_list(crm_data_t *update, lrm_op_t *op, const char *version);
+
+void
 append_restart_list(crm_data_t *update, lrm_op_t *op, const char *version) 
 {
 	int len = 0;
@@ -686,8 +688,6 @@ build_operation_update(
 	if(args_parent == NULL) {
 		free_xml(args_xml);
 	}
-
-	append_restart_list(xml_op, op, caller_version);
 	
 	return TRUE;
 }
@@ -859,7 +859,8 @@ do_lrm_query(gboolean is_replace)
 	}
 
 	xml_result = create_cib_fragment(xml_state, XML_CIB_TAG_STATUS);
-
+	free_xml(xml_state);
+	
 	crm_log_xml_debug_3(xml_state, "Current state of the LRM");
 	
 	return xml_result;
diff -r 2d298bca0d0a crm/crmd/messages.c
--- a/crm/crmd/messages.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/crm/crmd/messages.c	Fri Feb 09 15:05:30 2007 +0100
@@ -314,9 +314,7 @@ delete_fsa_input(fsa_data_t *fsa_data)
 			case fsa_dt_ccm:
 				ccm_input = (struct crmd_ccm_data_s *)
 					fsa_data->data;
-
-				crm_free(ccm_input->oc);
-				crm_free(ccm_input);
+				delete_ccm_data(ccm_input);
 				break;
 				
 			case fsa_dt_none:
diff -r 2d298bca0d0a crm/crmd/utils.c
--- a/crm/crmd/utils.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/crm/crmd/utils.c	Fri Feb 09 15:05:30 2007 +0100
@@ -1151,6 +1148,42 @@ copy_ccm_data(const struct crmd_ccm_data
 	ccm_input_copy->event = ccm_input->event;
 	
 	return ccm_input_copy;
+}
+
+void
+delete_ccm_data(struct crmd_ccm_data_s *ccm_input) 
+{
+	int lpc, offset = 0;
+	oc_node_t *a_node = NULL;
+	oc_ev_membership_t *oc_in = ccm_input->oc;
+	if(oc_in != NULL) {
+		offset = oc_in->m_memb_idx;
+	}
+	for(lpc = 0; lpc < oc_in->m_n_member; lpc++) {
+		a_node = &oc_in->m_array[lpc+offset];
+		crm_free(a_node->node_uname);
+		a_node->node_uname = NULL;
+	}
+
+	if(oc_in != NULL) {
+		offset = oc_in->m_in_idx;
+	}
+	for(lpc = 0; lpc < oc_in->m_n_in; lpc++) {
+		a_node = &oc_in->m_array[lpc+offset];
+		crm_free(a_node->node_uname);
+		a_node->node_uname = NULL;
+	}
+
+	if(oc_in != NULL) {
+		offset = oc_in->m_out_idx;
+	}
+	for(lpc = 0; lpc < oc_in->m_n_out; lpc++) {
+		a_node = &oc_in->m_array[lpc+offset];
+		crm_free(a_node->node_uname);
+		a_node->node_uname = NULL;
+	}
+ 	crm_free(ccm_input->oc);
+ 	crm_free(ccm_input);
 }
 
 oc_ev_membership_t *
@@ -1243,21 +1274,61 @@ copy_ccm_node(oc_node_t a_node, oc_node_
 		  a_node.node_id, a_node.node_born_on,
 		  a_node.node_uname);
 	
+	if(a_node_copy->node_uname != NULL) {
+		crm_debug_2("%p (%s) already copied", a_node_copy, a_node_copy->node_uname);
+		return;
+	}
+
 	a_node_copy->node_id      = a_node.node_id;
-	a_node_copy->node_born_on = a_node.node_born_on;	
+	a_node_copy->node_born_on = a_node.node_born_on;
 	a_node_copy->node_uname   = NULL;
 	
 	if(a_node.node_uname != NULL) {
-			a_node_copy->node_uname =
-				crm_strdup(a_node.node_uname);
+		a_node_copy->node_uname = crm_strdup(a_node.node_uname);
 	} else {
-		crm_err("Node Id %d had a NULL uname!",
-			a_node.node_id);
-	}
-	
+		crm_err("Node Id %d had a NULL uname!", a_node.node_id);
+	}
 	crm_debug_3("Copied ccm node: id=%d, born=%d, uname=%s",
 		  a_node_copy->node_id, a_node_copy->node_born_on,
 		  a_node_copy->node_uname);
+}
+
+static gboolean
+ghash_node_clfree(gpointer key, gpointer value, gpointer user_data)
+{
+	/* value->node_uname is free'd as "key" */
+	if(key != NULL) {
+		crm_free(key);
+	}
+	if(value != NULL) {
+		crm_free(value);
+	}
+	return TRUE;
+}
+
+void
+free_ccm_cache(oc_node_list_t *tmp) 
+{
+	/* Free the old copy */
+	if(tmp == NULL) {
+		return;
+	}
+	
+	if(tmp->members != NULL) {
+		g_hash_table_foreach_remove(
+			tmp->members, ghash_node_clfree, NULL);
+	}
+	if(tmp->new_members != NULL) {
+		g_hash_table_foreach_remove(
+			tmp->new_members, ghash_node_clfree, NULL);
+	}
+	if(tmp->dead_members != NULL) {
+		g_hash_table_foreach_remove(
+			tmp->dead_members, ghash_node_clfree, NULL);
+	}
+	
+	crm_free(tmp);
+	crm_debug_3("Free'd old copies");
 }
 
 crm_data_t*
diff -r 2d298bca0d0a lib/crm/cib/cib_attrs.c
--- a/lib/crm/cib/cib_attrs.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/lib/crm/cib/cib_attrs.c	Fri Feb 09 15:05:30 2007 +0100
@@ -101,7 +101,9 @@ find_attr_details(crm_data_t *xml_search
 			NULL, XML_ATTR_ID, node_uuid, FALSE);
 		crm_log_xml_debug_2(set_children, "search by node:");
 		if(matches == 0) {
-			crm_info("No node matching id=%s in %s", node_uuid, TYPE(xml_search));
+			CRM_CHECK(set_children == NULL, crm_err("Memory leak"));
+			crm_info("No node matching id=%s in %s",
+				 node_uuid, TYPE(xml_search));
 			return NULL;
 		}
 	}
@@ -114,6 +116,7 @@ find_attr_details(crm_data_t *xml_search
 		crm_log_xml_debug_2(set_children, "search by set:");
 		if(matches == 0) {
 			crm_info("No set matching id=%s in %s", set_name, TYPE(xml_search));
+			CRM_CHECK(set_children == NULL, crm_err("Memory leak"));
 			return NULL;
 		}
 	}
@@ -140,6 +143,7 @@ find_attr_details(crm_data_t *xml_search
 			       break;
 			);
 		free_xml(nv_children);
+		free_xml(set_children);
 		return single_match;
 		
 	} else if(matches > 1) {
@@ -176,6 +180,7 @@ find_attr_details(crm_data_t *xml_search
 				);
 		}
 	}
+	free_xml(set_children);
 	return NULL;
 }
 
@@ -230,6 +235,7 @@ update_attr(cib_t *the_cib, int call_opt
 		CRM_CHECK(set_name != NULL, return cib_missing);
 		
 		if(attr_value == NULL) {
+			free_xml(xml_obj);
 			return cib_missing_data;
 		}
 		
@@ -264,6 +270,7 @@ update_attr(cib_t *the_cib, int call_opt
 		xml_obj = create_xml_node(xml_obj, XML_TAG_ATTRS);
 		crm_free(local_set_name);
 	} else {
+		free_xml(xml_obj);
 		xml_obj = NULL;
 	}
 
diff -r 2d298bca0d0a lib/crm/cib/cib_client.c
--- a/lib/crm/cib/cib_client.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/lib/crm/cib/cib_client.c	Fri Feb 09 15:05:30 2007 +0100
@@ -487,7 +487,8 @@ int cib_client_add_notify_callback(
 	
 	if(list_item != NULL) {
 		crm_warn("Callback already present");
-
+		crm_free(new_client);
+		
 	} else {
 		cib->notify_list = g_list_append(
 			cib->notify_list, new_client);
diff -r 2d298bca0d0a lib/crm/common/utils.c
--- a/lib/crm/common/utils.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/lib/crm/common/utils.c	Fri Feb 09 15:05:30 2007 +0100
@@ -519,6 +519,7 @@ int
 int
 compare_version(const char *version1, const char *version2)
 {
+	int rc = 0;
 	int lpc = 0;
 	char *step1 = NULL, *step2 = NULL;
 	char *rest1 = NULL, *rest2 = NULL;
@@ -533,7 +534,7 @@ compare_version(const char *version1, co
 	
 	rest1 = crm_strdup(version1);
 	rest2 = crm_strdup(version2);
-	
+
 	while(1) {
 		int cmp = 0;
 		int step1_i = 0;
@@ -543,6 +544,13 @@ compare_version(const char *version1, co
 		decodeNVpair(rest1, '.', &step1, &tmp1);
 		decodeNVpair(rest2, '.', &step2, &tmp2);
 
+		if(step1 == NULL && step2 == NULL) {
+			CRM_CHECK(tmp1 == tmp2 && tmp1 == NULL,
+				  crm_err("Leftover data: %s, %s",
+					  crm_str(tmp1), crm_str(tmp2)));
+			break;
+		}
+		
 		if(step1 != NULL) {
 			step1_i = crm_parse_int(step1, NULL);
 		}
@@ -564,27 +572,34 @@ compare_version(const char *version1, co
 		crm_free(rest1);
 		crm_free(rest2);
 
+		crm_free(step1);
+		crm_free(step2);
+
 		rest1 = tmp1;
 		rest2 = tmp2;
-
-		if(step1 == NULL && step2 == NULL) {
+		
+		if(cmp < 0) {
+			rc = -1;
 			break;
-		}
-
-		crm_free(step1);
-		crm_free(step2);
-		
-		if(cmp < 0) {
-			crm_debug_3("%s < %s", version1, version2);
-			return -1;
 			
 		} else if(cmp > 0) {
-			crm_debug_3("%s > %s", version1, version2);
-			return 1;
-		}
-	}
-	crm_debug_3("%s == %s", version1, version2);
-	return 0;
+			rc = 1;
+			break;
+		}
+	}
+	
+	crm_free(rest1);
+	crm_free(rest2);
+
+	if(rc == 0) {
+		crm_debug_3("%s == %s", version1, version2);
+	} else if(rc < 0) {
+		crm_debug_3("%s < %s", version1, version2);
+	} else if(rc > 0) {
+		crm_debug_3("%s > %s", version1, version2);
+	}
+	
+	return rc;
 }
 
 gboolean do_stderr = FALSE;
diff -r 2d298bca0d0a lib/crm/common/xml.c
--- a/lib/crm/common/xml.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/lib/crm/common/xml.c	Fri Feb 09 15:05:30 2007 +0100
@@ -2500,13 +2500,13 @@ validate_with_dtd(
 	CRM_CHECK(buffer != NULL, return FALSE);
 
  	doc = xmlParseMemory(buffer, strlen(buffer));
-	CRM_CHECK(doc != NULL, crm_free(buffer); return FALSE);
+	CRM_CHECK(doc != NULL, valid = FALSE; goto cleanup);
 	
 	dtd = xmlParseDTD(NULL, (const xmlChar *)dtd_file);
-	CRM_CHECK(dtd != NULL, crm_free(buffer); return TRUE);
+	CRM_CHECK(dtd != NULL, goto cleanup);
 
 	cvp = xmlNewValidCtxt();
-	CRM_CHECK(cvp != NULL, crm_free(buffer); return TRUE);
+	CRM_CHECK(cvp != NULL, goto cleanup);
 
 	if(to_logs) {
 		cvp->userData = (void *) LOG_ERR;
@@ -2520,15 +2520,16 @@ validate_with_dtd(
 	
 	if (!xmlValidateDtd(cvp, doc, dtd)) {
 		crm_err("CIB does not validate against %s", dtd_file);
+		crm_log_xml_debug(xml_blob, "invalid");
 		valid = FALSE;
-		crm_log_xml_debug(xml_blob, "invalid");
-	}
-
+	}
+	
+  cleanup:
 	xmlFreeValidCtxt(cvp);
 	xmlFreeDtd(dtd);
 	xmlFreeDoc(doc);
-	
 	crm_free(buffer);
+	
 #endif	
 	return valid;
 }
diff -r 2d298bca0d0a tools/attrd.c
--- a/tools/attrd.c	Thu Jan 11 18:42:41 2007 -0700
+++ b/tools/attrd.c	Fri Feb 09 15:05:30 2007 +0100
@@ -85,6 +85,7 @@ free_hash_entry(gpointer data)
 	}	
 	crm_free(entry->id);
 	crm_free(entry->set);
+	crm_free(entry->dampen);
 	crm_free(entry->section);
 	if(entry->value != entry->last_value) {
 		crm_free(entry->value);
@@ -477,6 +489,7 @@ find_hash_entry(HA_Message * msg)
 
 	value = ha_msg_value(msg, F_ATTRD_SET);
 	if(value != NULL) {
+		crm_free(hash_entry->set);
 		hash_entry->set = crm_strdup(value);
 		crm_debug("\t%s->set: %s", attr, value);
 	}
@@ -485,12 +498,15 @@ find_hash_entry(HA_Message * msg)
 	if(value == NULL) {
 		value = XML_CIB_TAG_STATUS;
 	}
+	crm_free(hash_entry->section);
 	hash_entry->section = crm_strdup(value);
 	crm_debug("\t%s->section: %s", attr, value);
 	
 	value = ha_msg_value(msg, F_ATTRD_DAMPEN);
 	if(value != NULL) {
+		crm_free(hash_entry->dampen);
 		hash_entry->dampen = crm_strdup(value);
+
 		hash_entry->timeout = crm_get_msec(value);
 		crm_debug("\t%s->timeout: %s", attr, value);
 	}
@@ -601,6 +617,7 @@ attrd_timer_callback(void *user_data)
 	ha_msg_add(msg, F_ATTRD_SECTION, hash_entry->section);
 	ha_msg_add(msg, F_ATTRD_DAMPEN, hash_entry->dampen);
 	send_ha_message(attrd_cluster_conn, msg, NULL, FALSE);
+	crm_msg_del(msg);
 	
 	return TRUE;
 }
