Hello,

This patch set attempts to move ldap_parse_master_zoneentry() a little bit closer to sane code.

It is preparation for
https://fedorahosted.org/bind-dyndb-ldap/ticket/56

--
Petr^2 Spacek
From bfa03960c700bedda454bb7cef5c89bbfce1bbba Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Tue, 15 Apr 2014 18:57:40 +0200
Subject: [PATCH] Refactor empty zone handling.

https://fedorahosted.org/bind-dyndb-ldap/ticket/56

Signed-off-by: Petr Spacek <pspa...@redhat.com>
---
 src/ldap_helper.c | 79 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 47 insertions(+), 32 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 6c2ead85459eaf531311a15c5817acb4117e7618..790ac4a597dca8772ddb3eed8a6f91d43c7f6b1f 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -715,10 +715,12 @@ destroy_ldap_connection(ldap_connection_t **ldap_connp)
 
 /* Test if the existing zone is 'empty zone' per RFC 6303. */
 static isc_boolean_t ATTR_NONNULLS ATTR_CHECKRESULT
-zone_isempty(isc_mem_t *mctx, dns_zone_t *zone) {
+zone_isempty(dns_zone_t *zone) {
 	char **argv = NULL;
+	isc_mem_t *mctx = NULL;
 	isc_boolean_t result = ISC_FALSE;
 
+	mctx = dns_zone_getmctx(zone);
 	if (dns_zone_getdbtype(zone, &argv, mctx) != ISC_R_SUCCESS)
 		CLEANUP_WITH(ISC_FALSE);
 
@@ -833,6 +835,42 @@ cleanup:
 	return result;
 }
 
+/**
+ * Unload empty zone from given view.
+ *
+ * @retval ISC_R_EXISTS   if a zone with given name is not an empty zone
+ * @retval ISC_R_SUCCESS  if name was an empty zone
+ *                        and it was unloaded successfully
+ * @retval ISC_R_NOTFOUND if name does not match any zone in given view
+ * @retval other errors
+ */
+static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
+zone_unload_ifempty(dns_view_t *view, dns_name_t *name) {
+	isc_result_t result;
+	dns_zone_t *zone = NULL;
+	char zone_name[DNS_NAME_FORMATSIZE];
+
+	CHECK(dns_view_findzone(view, name, &zone));
+
+	if (zone_isempty(zone) == ISC_TRUE) {
+		dns_name_format(name, zone_name, DNS_NAME_FORMATSIZE);
+		result = delete_bind_zone(view->zonetable, &zone);
+		if (result != ISC_R_SUCCESS)
+			log_error_r("unable to unload automatic empty zone "
+				    "%s", zone_name);
+		else
+			log_info("automatic empty zone %s unloaded",
+				 zone_name);
+	} else {
+		result = ISC_R_EXISTS;
+	}
+
+cleanup:
+	if (zone != NULL)
+		dns_zone_detach(&zone);
+	return result;
+}
+
 /*
  * Create a new zone with origin 'name'. The zone will be added to the
  * ldap_inst->view.
@@ -845,44 +883,18 @@ create_zone(ldap_instance_t *ldap_inst, dns_name_t *name, dns_zone_t **zonep)
 	const char *argv[2];
 	sync_state_t sync_state;
 	isc_task_t *task = NULL;
+	char zone_name[DNS_NAME_FORMATSIZE];
 
 	REQUIRE(ldap_inst != NULL);
 	REQUIRE(name != NULL);
 	REQUIRE(zonep != NULL && *zonep == NULL);
 
 	argv[0] = ldapdb_impname;
 	argv[1] = ldap_inst->db_name;
 
-	result = dns_view_findzone(ldap_inst->view, name, &zone);
-	if (result != ISC_R_NOTFOUND) {
-		char zone_name[DNS_NAME_FORMATSIZE];
-		dns_name_format(name, zone_name, DNS_NAME_FORMATSIZE);
-
-		if (result != ISC_R_SUCCESS) {
-			log_error_r("dns_view_findzone() failed while "
-				    "searching for zone '%s'", zone_name);
-		} else { /* zone already exists */
-			if (zone_isempty(ldap_inst->mctx, zone) == ISC_TRUE) {
-				result = delete_bind_zone(ldap_inst->view->zonetable,
-							  &zone);
-				if (result != ISC_R_SUCCESS)
-					log_error_r("failed to create new zone "
-						    "'%s': unable to unload "
-						    "automatic empty zone",
-						    zone_name);
-				else
-					log_info("automatic empty zone %s "
-						 "unloaded", zone_name);
-
-			} else {
-				result = ISC_R_EXISTS;
-				log_error_r("failed to create new zone '%s'",
-					    zone_name);
-			}
-		}
-		if (result != ISC_R_SUCCESS)
-			goto cleanup;
-	}
+	result = zone_unload_ifempty(ldap_inst->view, name);
+	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+		goto cleanup;
 
 	CHECK(dns_zone_create(&zone, ldap_inst->mctx));
 	CHECK(dns_zone_setorigin(zone, name));
@@ -901,6 +913,9 @@ create_zone(ldap_instance_t *ldap_inst, dns_name_t *name, dns_zone_t **zonep)
 	return ISC_R_SUCCESS;
 
 cleanup:
+	dns_name_format(name, zone_name, DNS_NAME_FORMATSIZE);
+	log_error_r("failed to create new zone '%s'", zone_name);
+
 	if (zone != NULL) {
 		if (dns_zone_getmgr(zone) != NULL)
 			dns_zonemgr_releasezone(ldap_inst->zmgr, zone);
@@ -1403,7 +1418,7 @@ configure_zone_forwarders(ldap_entry_t *entry, ldap_instance_t *inst,
 		result = dns_zt_find(inst->view->zonetable, name, 0, NULL,
 				     &zone);
 		if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
-			if (zone_isempty(inst->mctx, zone)) {
+			if (zone_isempty(zone)) {
 				dns_zone_log(zone, ISC_LOG_INFO, "automatic "
 					     "empty zone will be shut down "
 					     "to enable forwarding");
-- 
1.9.0

From 4b7618495a05f80c0cd383be2e48cce6d36f4442 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Tue, 15 Apr 2014 19:21:56 +0200
Subject: [PATCH] Rename variables in ldap_parse_master_zoneentry() and
 create_zone().

This is preparation for future changes related to DNSSEC support.

https://fedorahosted.org/bind-dyndb-ldap/ticket/56
---
 src/ldap_helper.c | 76 +++++++++++++++++++++++++++----------------------------
 1 file changed, 38 insertions(+), 38 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 790ac4a597dca8772ddb3eed8a6f91d43c7f6b1f..b62eb375dab51e9ea49ee8e661f02f1d61055570 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -876,50 +876,50 @@ cleanup:
  * ldap_inst->view.
  */
 static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
-create_zone(ldap_instance_t *ldap_inst, dns_name_t *name, dns_zone_t **zonep)
+create_zone(ldap_instance_t *ldap_inst, dns_name_t *name, dns_zone_t **rawp)
 {
 	isc_result_t result;
-	dns_zone_t *zone = NULL;
+	dns_zone_t *raw = NULL;
 	const char *argv[2];
 	sync_state_t sync_state;
 	isc_task_t *task = NULL;
 	char zone_name[DNS_NAME_FORMATSIZE];
 
 	REQUIRE(ldap_inst != NULL);
 	REQUIRE(name != NULL);
-	REQUIRE(zonep != NULL && *zonep == NULL);
+	REQUIRE(rawp != NULL && *rawp == NULL);
 
 	argv[0] = ldapdb_impname;
 	argv[1] = ldap_inst->db_name;
 
 	result = zone_unload_ifempty(ldap_inst->view, name);
 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
 		goto cleanup;
 
-	CHECK(dns_zone_create(&zone, ldap_inst->mctx));
-	CHECK(dns_zone_setorigin(zone, name));
-	dns_zone_setclass(zone, dns_rdataclass_in);
-	dns_zone_settype(zone, dns_zone_master);
-	CHECK(dns_zone_setdbtype(zone, 2, argv));
-	CHECK(dns_zonemgr_managezone(ldap_inst->zmgr, zone));
+	CHECK(dns_zone_create(&raw, ldap_inst->mctx));
+	CHECK(dns_zone_setorigin(raw, name));
+	dns_zone_setclass(raw, dns_rdataclass_in);
+	dns_zone_settype(raw, dns_zone_master);
+	CHECK(dns_zone_setdbtype(raw, 2, argv));
+	CHECK(dns_zonemgr_managezone(ldap_inst->zmgr, raw));
 	sync_state_get(ldap_inst->sctx, &sync_state);
 	if (sync_state == sync_init) {
-		dns_zone_gettask(zone, &task);
+		dns_zone_gettask(raw, &task);
 		CHECK(sync_task_add(ldap_inst->sctx, task));
 		isc_task_detach(&task);
 	}
 
-	*zonep = zone;
+	*rawp = raw;
 	return ISC_R_SUCCESS;
 
 cleanup:
 	dns_name_format(name, zone_name, DNS_NAME_FORMATSIZE);
 	log_error_r("failed to create new zone '%s'", zone_name);
 
-	if (zone != NULL) {
-		if (dns_zone_getmgr(zone) != NULL)
-			dns_zonemgr_releasezone(ldap_inst->zmgr, zone);
-		dns_zone_detach(&zone);
+	if (raw != NULL) {
+		if (dns_zone_getmgr(raw) != NULL)
+			dns_zonemgr_releasezone(ldap_inst->zmgr, raw);
+		dns_zone_detach(&raw);
 	}
 	if (task != NULL)
 		isc_task_detach(&task);
@@ -1812,7 +1812,7 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 	const char *dn;
 	ldap_valuelist_t values;
 	dns_name_t name;
-	dns_zone_t *zone = NULL;
+	dns_zone_t *raw = NULL;
 	dns_zone_t *zone_raw = NULL;
 	isc_result_t result;
 	isc_boolean_t unlock = ISC_FALSE;
@@ -1880,13 +1880,13 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 	 * Load the zone. */
 
 	/* Check if we are already serving given zone */
-	result = zr_get_zone_ptr(inst->zone_register, &name, &zone);
+	result = zr_get_zone_ptr(inst->zone_register, &name, &raw);
 	if (result == ISC_R_NOTFOUND || result == DNS_R_PARTIALMATCH) {
-		CHECK(create_zone(inst, &name, &zone));
-		CHECK(configure_paths(inst->mctx, inst, zone, ISC_FALSE));
-		CHECK(zr_add_zone(inst->zone_register, zone, dn));
+		CHECK(create_zone(inst, &name, &raw));
+		CHECK(configure_paths(inst->mctx, inst, raw, ISC_FALSE));
+		CHECK(zr_add_zone(inst->zone_register, raw, dn));
 		new_zone = ISC_TRUE;
-		log_debug(2, "created zone %p: %s", zone, dn);
+		log_debug(2, "created zone %p: %s", raw, dn);
 	} else if (result != ISC_R_SUCCESS)
 		goto cleanup;
 
@@ -1912,44 +1912,44 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 		isc_boolean_t ssu_enabled;
 		const char *ssu_policy = NULL;
 
-		log_debug(2, "Setting SSU table for %p: %s", zone, dn);
+		log_debug(2, "Setting SSU table for %p: %s", raw, dn);
 		CHECK(setting_get_bool("dyn_update", zone_settings, &ssu_enabled));
 		if (ssu_enabled) {
 			/* Get the update policy and update the zone with it. */
 			CHECK(setting_get_str("update_policy", zone_settings,
 					      &ssu_policy));
-			CHECK(configure_zone_ssutable(zone, ssu_policy));
+			CHECK(configure_zone_ssutable(raw, ssu_policy));
 		} else {
 			/* Empty policy will prevent the update from reaching
 			 * LDAP driver and error will be logged. */
-			CHECK(configure_zone_ssutable(zone, ""));
+			CHECK(configure_zone_ssutable(raw, ""));
 		}
 	}
 
 	/* Fetch allow-query and allow-transfer ACLs */
-	log_debug(2, "Setting allow-query for %p: %s", zone, dn);
+	log_debug(2, "Setting allow-query for %p: %s", raw, dn);
 	result = ldap_entry_getvalues(entry, "idnsAllowQuery", &values);
 	if (result == ISC_R_SUCCESS) {
-		CHECK(configure_zone_acl(inst->mctx, zone, &dns_zone_setqueryacl,
+		CHECK(configure_zone_acl(inst->mctx, raw, &dns_zone_setqueryacl,
 					 HEAD(values)->value, acl_type_query));
 	} else {
 		log_debug(2, "allow-query not set");
-		dns_zone_clearqueryacl(zone);
+		dns_zone_clearqueryacl(raw);
 	}
 
-	log_debug(2, "Setting allow-transfer for %p: %s", zone, dn);
+	log_debug(2, "Setting allow-transfer for %p: %s", raw, dn);
 	result = ldap_entry_getvalues(entry, "idnsAllowTransfer", &values);
 	if (result == ISC_R_SUCCESS) {
-		CHECK(configure_zone_acl(inst->mctx, zone, &dns_zone_setxfracl,
+		CHECK(configure_zone_acl(inst->mctx, raw, &dns_zone_setxfracl,
 					 HEAD(values)->value, acl_type_transfer));
 	} else {
 		log_debug(2, "allow-transfer not set");
-		dns_zone_clearxfracl(zone);
+		dns_zone_clearxfracl(raw);
 	}
 
 	sync_state_get(inst->sctx, &sync_state);
 	if (new_zone == ISC_TRUE && sync_state == sync_finished)
-		CHECK(publish_zone(task, inst, zone));
+		CHECK(publish_zone(task, inst, raw));
 
 	/* synchronize zone origin with LDAP */
 	CHECK(setting_get_str("fake_mname", inst->local_settings,
@@ -2026,21 +2026,21 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 	dns_diff_print(&diff, NULL);
 #endif
 	if (ldap_writeback == ISC_TRUE) {
-		dns_zone_log(zone, ISC_LOG_DEBUG(5), "writing new zone serial "
+		dns_zone_log(raw, ISC_LOG_DEBUG(5), "writing new zone serial "
 			     "%u to LDAP", new_serial);
 		result = ldap_replace_serial(inst, &name, new_serial);
 		if (result != ISC_R_SUCCESS)
-			dns_zone_log(zone, ISC_LOG_ERROR,
+			dns_zone_log(raw, ISC_LOG_ERROR,
 				     "serial (%u) write back to LDAP failed",
 				     new_serial);
 	}
 
 	if (!EMPTY(diff.tuples)) {
 		if (sync_state == sync_finished && new_zone == ISC_FALSE) {
 			/* write the transaction to journal */
-			dns_zone_getraw(zone, &zone_raw);
+			dns_zone_getraw(raw, &zone_raw);
 			if (zone_raw == NULL)
-				journal_filename = dns_zone_getjournal(zone);
+				journal_filename = dns_zone_getjournal(raw);
 			else
 				journal_filename = dns_zone_getjournal(zone_raw);
 			CHECK(dns_journal_open(inst->mctx, journal_filename,
@@ -2060,7 +2060,7 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 
 	/* Do zone load only if the initial LDAP synchronization is done. */
 	if (sync_state == sync_finished && data_changed == ISC_TRUE)
-		CHECK(load_zone(zone));
+		CHECK(load_zone(raw));
 
 cleanup:
 	dns_diff_clear(&diff);
@@ -2089,8 +2089,8 @@ cleanup:
 		isc_task_endexclusive(task);
 	if (dns_name_dynamic(&name))
 		dns_name_free(&name, inst->mctx);
-	if (zone != NULL)
-		dns_zone_detach(&zone);
+	if (raw != NULL)
+		dns_zone_detach(&raw);
 	ldapdb_rdatalist_destroy(inst->mctx, &rdatalist);
 
 	return result;
-- 
1.9.0

From f6af8ce3b6e38352d9a418ed237144e3a170a923 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Wed, 16 Apr 2014 16:07:06 +0200
Subject: [PATCH] Add support for key-directory to configure_paths().

https://fedorahosted.org/bind-dyndb-ldap/ticket/56

Signed-off-by: Petr Spacek <pspa...@redhat.com>
---
 src/ldap_helper.c   | 9 +++++++++
 src/zone_register.c | 4 ++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index b62eb375dab51e9ea49ee8e661f02f1d61055570..f6f4daa28bcebb134d734765133806f6e1e7f619 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -1642,16 +1642,25 @@ configure_paths(isc_mem_t *mctx, ldap_instance_t *inst, dns_zone_t *zone,
 		isc_boolean_t issecure) {
 	isc_result_t result;
 	ld_string_t *file_name = NULL;
+	ld_string_t *key_dir = NULL;
 
 	CHECK(zr_get_zone_path(mctx, ldap_instance_getsettings_local(inst),
 			       dns_zone_getorigin(zone),
 			       (issecure ? "signed" : "raw"), &file_name));
 	CHECK(dns_zone_setfile(zone, str_buf(file_name)));
+	if (issecure == ISC_TRUE) {
+		CHECK(zr_get_zone_path(mctx,
+				       ldap_instance_getsettings_local(inst),
+				       dns_zone_getorigin(zone), "keys/",
+				       &key_dir));
+		dns_zone_setkeydirectory(zone, str_buf(key_dir));
+	}
 	CHECK(fs_file_remove(dns_zone_getfile(zone)));
 	CHECK(fs_file_remove(dns_zone_getjournal(zone)));
 
 cleanup:
 	str_destroy(&file_name);
+	str_destroy(&key_dir);
 	return result;
 }
 
diff --git a/src/zone_register.c b/src/zone_register.c
index d58159c3104f2624bfaa05de4515db5b2598d51f..e84664b3b5ea3a9306a592e82fa53f3dbc097de4 100644
--- a/src/zone_register.c
+++ b/src/zone_register.c
@@ -257,9 +257,9 @@ create_zone_info(isc_mem_t *mctx, dns_zone_t *zone, const char *dn,
 				  settings_name, global_settings,
 				  &zinfo->settings));
 
-	/* Prepate a directory for this zone */
+	/* Prepare a directory for this zone */
 	CHECK(zr_get_zone_path(mctx, global_settings, dns_zone_getorigin(zone),
-			       NULL, &zone_dir));
+			       "keys/", &zone_dir));
 	CHECK(fs_dirs_create(str_buf(zone_dir)));
 
 	DE_CONST(db_name, argv[0]);
-- 
1.9.0

From 990f10ac003ea8d1e9cac89c49cf41c45b29d1f6 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Thu, 17 Apr 2014 14:49:48 +0200
Subject: [PATCH] Refactor master zone configuration.

ldap_parse_master_zoneentry() is way too long and unmanageable.

https://fedorahosted.org/bind-dyndb-ldap/ticket/56
---
 src/ldap_helper.c | 140 ++++++++++++++++++++++++++++++++----------------------
 1 file changed, 83 insertions(+), 57 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index f6f4daa28bcebb134d734765133806f6e1e7f619..816080b6f3d8e5721a6b08939f280f89489cf9e4 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -1813,21 +1813,101 @@ cleanup:
 #undef MAX_SERIAL_LENGTH
 }
 
+/**
+ * Reconfigure master zone according to configuration in LDAP object.
+ *
+ * @param[in]  raw Raw zone backed by LDAP database. In-line secure zone
+ *                 will be reconfigured as necessary.
+ */
+static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
+zone_master_reconfigure(ldap_entry_t *entry, settings_set_t *zone_settings,
+			dns_zone_t *raw, isc_task_t *task) {
+	isc_result_t result;
+	const char *dn = NULL;
+	ldap_valuelist_t values;
+	isc_mem_t *mctx = NULL;
+	isc_boolean_t ssu_changed;
+
+	REQUIRE(entry != NULL);
+	REQUIRE(zone_settings != NULL);
+	REQUIRE(raw != NULL);
+	REQUIRE(task != NULL);
+
+	dn = entry->dn;
+	mctx = dns_zone_getmctx(raw);
+
+	result = setting_update_from_ldap_entry("dyn_update", zone_settings,
+						"idnsAllowDynUpdate", entry, task);
+	if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE)
+		goto cleanup;
+	ssu_changed = (result == ISC_R_SUCCESS);
+
+	result = setting_update_from_ldap_entry("sync_ptr", zone_settings,
+				       "idnsAllowSyncPTR", entry, task);
+	if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE)
+		goto cleanup;
+
+	result = setting_update_from_ldap_entry("update_policy", zone_settings,
+						"idnsUpdatePolicy", entry, task);
+	if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE)
+		goto cleanup;
+
+	if (result == ISC_R_SUCCESS || ssu_changed) {
+		isc_boolean_t ssu_enabled;
+		const char *ssu_policy = NULL;
+
+		log_debug(2, "Setting SSU table for %p: %s", raw, dn);
+		CHECK(setting_get_bool("dyn_update", zone_settings, &ssu_enabled));
+		if (ssu_enabled) {
+			/* Get the update policy and update the zone with it. */
+			CHECK(setting_get_str("update_policy", zone_settings,
+					      &ssu_policy));
+			CHECK(configure_zone_ssutable(raw, ssu_policy));
+		} else {
+			/* Empty policy will prevent the update from reaching
+			 * LDAP driver and error will be logged. */
+			CHECK(configure_zone_ssutable(raw, ""));
+		}
+	}
+
+	/* Fetch allow-query and allow-transfer ACLs */
+	log_debug(2, "Setting allow-query for %p: %s", raw, dn);
+	result = ldap_entry_getvalues(entry, "idnsAllowQuery", &values);
+	if (result == ISC_R_SUCCESS) {
+		CHECK(configure_zone_acl(mctx, raw, &dns_zone_setqueryacl,
+					 HEAD(values)->value, acl_type_query));
+	} else {
+		log_debug(2, "allow-query not set");
+		dns_zone_clearqueryacl(raw);
+	}
+
+	log_debug(2, "Setting allow-transfer for %p: %s", raw, dn);
+	result = ldap_entry_getvalues(entry, "idnsAllowTransfer", &values);
+	if (result == ISC_R_SUCCESS) {
+		CHECK(configure_zone_acl(mctx, raw, &dns_zone_setxfracl,
+					 HEAD(values)->value, acl_type_transfer));
+	} else {
+		log_debug(2, "allow-transfer not set");
+		dns_zone_clearxfracl(raw);
+	}
+
+cleanup:
+	return result;
+}
+
 /* Parse the master zone entry */
 static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
 ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 			    isc_task_t *task)
 {
 	const char *dn;
-	ldap_valuelist_t values;
 	dns_name_t name;
 	dns_zone_t *raw = NULL;
 	dns_zone_t *zone_raw = NULL;
 	isc_result_t result;
 	isc_boolean_t unlock = ISC_FALSE;
 	isc_boolean_t new_zone = ISC_FALSE;
 	isc_boolean_t configured = ISC_FALSE;
-	isc_boolean_t ssu_changed;
 	ldapdb_rdatalist_t rdatalist;
 	settings_set_t *zone_settings = NULL;
 	const char *fake_mname = NULL;
@@ -1900,61 +1980,7 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 		goto cleanup;
 
 	CHECK(zr_get_zone_settings(inst->zone_register, &name, &zone_settings));
-
-	result = setting_update_from_ldap_entry("dyn_update", zone_settings,
-				       "idnsAllowDynUpdate", entry, inst->task);
-	if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE)
-		goto cleanup;
-	ssu_changed = (result == ISC_R_SUCCESS);
-
-	result = setting_update_from_ldap_entry("sync_ptr", zone_settings,
-				       "idnsAllowSyncPTR", entry, inst->task);
-	if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE)
-		goto cleanup;
-
-	result = setting_update_from_ldap_entry("update_policy", zone_settings,
-				       "idnsUpdatePolicy", entry, inst->task);
-	if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE)
-		goto cleanup;
-
-	if (result == ISC_R_SUCCESS || ssu_changed) {
-		isc_boolean_t ssu_enabled;
-		const char *ssu_policy = NULL;
-
-		log_debug(2, "Setting SSU table for %p: %s", raw, dn);
-		CHECK(setting_get_bool("dyn_update", zone_settings, &ssu_enabled));
-		if (ssu_enabled) {
-			/* Get the update policy and update the zone with it. */
-			CHECK(setting_get_str("update_policy", zone_settings,
-					      &ssu_policy));
-			CHECK(configure_zone_ssutable(raw, ssu_policy));
-		} else {
-			/* Empty policy will prevent the update from reaching
-			 * LDAP driver and error will be logged. */
-			CHECK(configure_zone_ssutable(raw, ""));
-		}
-	}
-
-	/* Fetch allow-query and allow-transfer ACLs */
-	log_debug(2, "Setting allow-query for %p: %s", raw, dn);
-	result = ldap_entry_getvalues(entry, "idnsAllowQuery", &values);
-	if (result == ISC_R_SUCCESS) {
-		CHECK(configure_zone_acl(inst->mctx, raw, &dns_zone_setqueryacl,
-					 HEAD(values)->value, acl_type_query));
-	} else {
-		log_debug(2, "allow-query not set");
-		dns_zone_clearqueryacl(raw);
-	}
-
-	log_debug(2, "Setting allow-transfer for %p: %s", raw, dn);
-	result = ldap_entry_getvalues(entry, "idnsAllowTransfer", &values);
-	if (result == ISC_R_SUCCESS) {
-		CHECK(configure_zone_acl(inst->mctx, raw, &dns_zone_setxfracl,
-					 HEAD(values)->value, acl_type_transfer));
-	} else {
-		log_debug(2, "allow-transfer not set");
-		dns_zone_clearxfracl(raw);
-	}
+	CHECK(zone_master_reconfigure(entry, zone_settings, raw, task));
 
 	sync_state_get(inst->sctx, &sync_state);
 	if (new_zone == ISC_TRUE && sync_state == sync_finished)
-- 
1.9.0

From a9403a9ca932448e6405c38a0040a750ad1b9b3a Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Thu, 17 Apr 2014 19:57:48 +0200
Subject: [PATCH] Refactor zone apex synchronization and serial maintenance.

ldap_parse_master_zoneentry() is way too long and unmanageable.

https://fedorahosted.org/bind-dyndb-ldap/ticket/56

Signed-off-by: Petr Spacek <pspa...@redhat.com>
---
 src/ldap_helper.c | 231 ++++++++++++++++++++++++++++++------------------------
 1 file changed, 130 insertions(+), 101 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 816080b6f3d8e5721a6b08939f280f89489cf9e4..d9f9adb93ca4e386ba05d8f7533a692b1c68f4e2 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -1895,49 +1895,154 @@ cleanup:
 	return result;
 }
 
+/**
+ * Synchronize internal RBTDB with master zone object in LDAP and update serial
+ * as necessary.
+ *
+ * @param[in]  new_zone Is the RBTDB empty? (I.e. even without SOA record.)
+ * @param[in]  version  LDAP DB opened for reading and writing.
+ * @param[out] diff     Initialized diff. It will be filled with differences
+ *                      between RBTDB and LDAP object + SOA serial update.
+ * @param[out] new_serial     SOA serial after update;
+ *                            valid if ldap_writeback = ISC_TRUE.
+ * @param[out] ldap_writeback SOA serial was updated.
+ * @param[out] data_changed   Other data were updated.
+ *
+ */
+static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
+zone_sync_apex(const ldap_instance_t * const inst,
+	       ldap_entry_t * const entry, dns_name_t name,
+	       const sync_state_t sync_state, const isc_boolean_t new_zone,
+	       dns_db_t * const ldapdb, dns_db_t * const rbtdb,
+	       dns_dbversion_t * const version, dns_diff_t * const diff,
+	       isc_uint32_t * const new_serial,
+	       isc_boolean_t * const ldap_writeback,
+	       isc_boolean_t * const data_changed) {
+	isc_result_t result;
+	const char *fake_mname = NULL;
+	ldapdb_rdatalist_t rdatalist;
+	dns_rdatasetiter_t *rbt_rds_iterator = NULL;
+	/* RBTDB's origin node cannot be detached until the node is non-empty.
+	 * This is workaround for ISC-Bug #35080. */
+	dns_dbnode_t *node = NULL;
+	dns_difftuple_t *soa_tuple = NULL;
+	isc_boolean_t soa_tuple_alloc = ISC_FALSE;
+	isc_uint32_t curr_serial;
+
+	INIT_LIST(rdatalist);
+	CHECK(setting_get_str("fake_mname", inst->local_settings,
+			      &fake_mname));
+	CHECK(ldap_parse_rrentry(inst->mctx, entry, &name, fake_mname,
+				 &rdatalist));
+
+	CHECK(dns_db_getoriginnode(rbtdb, &node));
+	result = dns_db_allrdatasets(rbtdb, node, version, 0,
+				     &rbt_rds_iterator);
+	if (result == ISC_R_SUCCESS) {
+		CHECK(diff_ldap_rbtdb(inst->mctx, &name, &rdatalist,
+				      rbt_rds_iterator, diff));
+		dns_rdatasetiter_destroy(&rbt_rds_iterator);
+	} else if (result != ISC_R_NOTFOUND)
+		goto cleanup;
+
+	/* New zone doesn't have serial defined yet. */
+	if (new_zone != ISC_TRUE)
+		CHECK(dns_db_getsoaserial(rbtdb, version, &curr_serial));
+
+	/* Detect if SOA serial is affected by the update or not.
+	 * Always bump serial in case of re-synchronization. */
+	CHECK(diff_analyze_serial(diff, &soa_tuple, data_changed));
+	if (new_zone == ISC_TRUE || *data_changed == ISC_TRUE ||
+	    sync_state != sync_finished) {
+		if (soa_tuple == NULL) {
+			/* The diff doesn't contain new SOA serial
+			 * => generate new serial and write it back to LDAP. */
+			*ldap_writeback = ISC_TRUE;
+			soa_tuple_alloc = ISC_TRUE;
+			CHECK(dns_db_createsoatuple(ldapdb, version, inst->mctx,
+						    DNS_DIFFOP_DEL, &soa_tuple));
+			dns_diff_appendminimal(diff, &soa_tuple);
+			CHECK(dns_db_createsoatuple(ldapdb, version, inst->mctx,
+						    DNS_DIFFOP_ADD, &soa_tuple));
+			CHECK(update_soa_serial(dns_updatemethod_unixtime,
+						soa_tuple, new_serial));
+			dns_diff_appendminimal(diff, &soa_tuple);
+		} else if (new_zone == ISC_TRUE || sync_state != sync_finished ||
+			   isc_serial_le(dns_soa_getserial(&soa_tuple->rdata),
+					 curr_serial)) {
+			/* The diff tries to send SOA serial back!
+			 * => generate new serial and write it back to LDAP.
+			 * Force serial update if we are adding a new zone. */
+			*ldap_writeback = ISC_TRUE;
+			CHECK(update_soa_serial(dns_updatemethod_unixtime,
+						soa_tuple, new_serial));
+		} else {
+			/* The diff contains new serial already
+			 * => do nothing. */
+			*ldap_writeback = ISC_FALSE;
+		}
+
+	} else {/* if (data_changed == ISC_FALSE) */
+		*ldap_writeback = ISC_FALSE;
+		if (soa_tuple == NULL) {
+			/* The diff is empty => do nothing. */
+			INSIST(EMPTY(diff->tuples));
+		} else if (isc_serial_le(dns_soa_getserial(&soa_tuple->rdata),
+					 curr_serial)) {
+			/* Attempt to move serial backwards without any data
+			 * => ignore it. */
+			dns_diff_clear(diff);
+		}/* else:
+		  * The diff contains new serial already
+		  * => do nothing. */
+	}
+
+cleanup:
+	/* New zone has to have at least SOA record and NS record. */
+	if (new_zone == ISC_TRUE
+	    && (*data_changed == ISC_FALSE || soa_tuple == NULL)) {
+		if (result == ISC_R_SUCCESS)
+			result = ISC_R_FAILURE;
+	}
+	if (soa_tuple_alloc == ISC_TRUE && soa_tuple != NULL)
+		dns_difftuple_free(&soa_tuple);
+	if (node != NULL)
+		dns_db_detachnode(rbtdb, &node);
+	if (rbt_rds_iterator != NULL)
+		dns_rdatasetiter_destroy(&rbt_rds_iterator);
+	ldapdb_rdatalist_destroy(inst->mctx, &rdatalist);
+	return result;
+}
+
 /* Parse the master zone entry */
 static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
 ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 			    isc_task_t *task)
 {
 	const char *dn;
 	dns_name_t name;
 	dns_zone_t *raw = NULL;
-	dns_zone_t *zone_raw = NULL;
 	isc_result_t result;
 	isc_boolean_t unlock = ISC_FALSE;
 	isc_boolean_t new_zone = ISC_FALSE;
-	isc_boolean_t configured = ISC_FALSE;
-	ldapdb_rdatalist_t rdatalist;
 	settings_set_t *zone_settings = NULL;
-	const char *fake_mname = NULL;
-	isc_boolean_t data_changed;
 	isc_boolean_t ldap_writeback;
-	isc_uint32_t curr_serial;
+	isc_boolean_t data_changed;
 	isc_uint32_t new_serial;
 
 	dns_db_t *rbtdb = NULL;
 	dns_db_t *ldapdb = NULL;
 	dns_diff_t diff;
 	dns_dbversion_t *version = NULL;
-	/* RBTDB's origin node cannot be detached until the node is non-empty.
-	 * This is workaround for possible bug in bind-9.9.3-P2. */
-	dns_dbnode_t *node = NULL;
-	dns_rdatasetiter_t *rbt_rds_iterator = NULL;
-	dns_difftuple_t *soa_tuple = NULL;
-	isc_boolean_t soa_tuple_alloc = ISC_FALSE;
-
 	sync_state_t sync_state;
 	dns_journal_t *journal = NULL;
 	char *journal_filename = NULL;
 
+	REQUIRE(entry != NULL);
+	REQUIRE(inst != NULL);
+
 	dns_diff_init(inst->mctx, &diff);
-
-	REQUIRE(entry != NULL);
-	REQUIRE(inst != NULL);
-
 	dns_name_init(&name, NULL);
-	INIT_LIST(rdatalist);
 
 	/* Derive the dns name of the zone from the DN. */
 	dn = entry->dn;
@@ -1987,73 +2092,12 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 		CHECK(publish_zone(task, inst, raw));
 
 	/* synchronize zone origin with LDAP */
-	CHECK(setting_get_str("fake_mname", inst->local_settings,
-			      &fake_mname));
-	CHECK(ldap_parse_rrentry(inst->mctx, entry, &name, fake_mname,
-				 &rdatalist));
-
 	CHECK(zr_get_zone_dbs(inst->zone_register, &name, &ldapdb, &rbtdb));
 	CHECK(dns_db_newversion(ldapdb, &version));
-	CHECK(dns_db_getoriginnode(rbtdb, &node));
-	result = dns_db_allrdatasets(rbtdb, node, version, 0,
-				     &rbt_rds_iterator);
-	if (result == ISC_R_SUCCESS) {
-		CHECK(diff_ldap_rbtdb(inst->mctx, &name, &rdatalist,
-				      rbt_rds_iterator, &diff));
-		dns_rdatasetiter_destroy(&rbt_rds_iterator);
-	} else if (result != ISC_R_NOTFOUND)
-		goto cleanup;
-
-	/* New zone doesn't have serial defined yet. */
-	if (new_zone == ISC_FALSE)
-		CHECK(dns_db_getsoaserial(rbtdb, version, &curr_serial));
-
-	/* Detect if SOA serial is affected by the update or not.
-	 * Always bump serial in case of re-synchronization. */
-	CHECK(diff_analyze_serial(&diff, &soa_tuple, &data_changed));
-	if (data_changed == ISC_TRUE || sync_state != sync_finished) {
-		if (soa_tuple == NULL) {
-			/* The diff doesn't contain new SOA serial
-			 * => generate new serial and write it back to LDAP. */
-			ldap_writeback = ISC_TRUE;
-			soa_tuple_alloc = ISC_TRUE;
-			CHECK(dns_db_createsoatuple(ldapdb, version, inst->mctx,
-						    DNS_DIFFOP_DEL, &soa_tuple));
-			dns_diff_appendminimal(&diff, &soa_tuple);
-			CHECK(dns_db_createsoatuple(ldapdb, version, inst->mctx,
-						    DNS_DIFFOP_ADD, &soa_tuple));
-			CHECK(update_soa_serial(dns_updatemethod_unixtime,
-						soa_tuple, &new_serial));
-			dns_diff_appendminimal(&diff, &soa_tuple);
-		} else if (new_zone == ISC_TRUE || sync_state != sync_finished ||
-			   isc_serial_le(dns_soa_getserial(&soa_tuple->rdata),
-					 curr_serial)) {
-			/* The diff tries to send SOA serial back!
-			 * => generate new serial and write it back to LDAP.
-			 * Force serial update if we are adding a new zone. */
-			ldap_writeback = ISC_TRUE;
-			CHECK(update_soa_serial(dns_updatemethod_unixtime,
-						soa_tuple, &new_serial));
-		} else {
-			/* The diff contains new serial already
-			 * => do nothing. */
-			ldap_writeback = ISC_FALSE;
-		}
-
-	} else {/* if (data_changed == ISC_FALSE) */
-		ldap_writeback = ISC_FALSE;
-		if (soa_tuple == NULL) {
-			/* The diff is empty => do nothing. */
-			INSIST(EMPTY(diff.tuples));
-		} else if (isc_serial_le(dns_soa_getserial(&soa_tuple->rdata),
-					 curr_serial)) {
-			/* Attempt to move serial backwards without any data
-			 * => ignore it. */
-			dns_diff_clear(&diff);
-		}/* else:
-		  * The diff contains new serial already
-		  * => do nothing. */
-	}
+	CHECK(zone_sync_apex(inst, entry, name, sync_state, new_zone,
+			     ldapdb, rbtdb, version,
+			     &diff, &new_serial, &ldap_writeback,
+			     &data_changed));
 
 #if RBTDB_DEBUG >= 2
 	dns_diff_print(&diff, stdout);
@@ -2073,11 +2117,7 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 	if (!EMPTY(diff.tuples)) {
 		if (sync_state == sync_finished && new_zone == ISC_FALSE) {
 			/* write the transaction to journal */
-			dns_zone_getraw(raw, &zone_raw);
-			if (zone_raw == NULL)
-				journal_filename = dns_zone_getjournal(raw);
-			else
-				journal_filename = dns_zone_getjournal(zone_raw);
+			journal_filename = dns_zone_getjournal(raw);
 			CHECK(dns_journal_open(inst->mctx, journal_filename,
 					       DNS_JOURNAL_CREATE, &journal));
 			CHECK(dns_journal_write_transaction(journal, &diff));
@@ -2088,32 +2128,22 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst,
 		dns_db_closeversion(ldapdb, &version, ISC_TRUE);
 	}
 
-	/* Make sure that zone has at least SOA record. */
-	if (new_zone == ISC_FALSE
-	    || (data_changed == ISC_TRUE && soa_tuple != NULL))
-		configured = ISC_TRUE;
-
 	/* Do zone load only if the initial LDAP synchronization is done. */
 	if (sync_state == sync_finished && data_changed == ISC_TRUE)
 		CHECK(load_zone(raw));
 
 cleanup:
 	dns_diff_clear(&diff);
-	if (soa_tuple_alloc == ISC_TRUE && soa_tuple != NULL)
-		dns_difftuple_free(&soa_tuple);
-	if (rbt_rds_iterator != NULL)
-		dns_rdatasetiter_destroy(&rbt_rds_iterator);
-	if (node != NULL)
-		dns_db_detachnode(rbtdb, &node);
 	if (rbtdb != NULL && version != NULL)
 		dns_db_closeversion(ldapdb, &version, ISC_FALSE); /* rollback */
 	if (rbtdb != NULL)
 		dns_db_detach(&rbtdb);
 	if (journal != NULL)
 		dns_journal_destroy(&journal);
 	if (ldapdb != NULL)
 		dns_db_detach(&ldapdb);
-	if (new_zone && !configured) { /* Failure in ACL parsing or so. */
+	if (new_zone && result != ISC_R_SUCCESS) {
+		/* Failure in ACL parsing or so. */
 		log_error_r("zone '%s': publishing failed, rolling back due to",
 			    entry->dn);
 		result = ldap_delete_zone2(inst, &name, ISC_TRUE, ISC_FALSE);
@@ -2126,7 +2156,6 @@ cleanup:
 		dns_name_free(&name, inst->mctx);
 	if (raw != NULL)
 		dns_zone_detach(&raw);
-	ldapdb_rdatalist_destroy(inst->mctx, &rdatalist);
 
 	return result;
 }
-- 
1.9.0

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to