On 27.11.2013 16:34, Petr Spacek wrote:
Hello,

Do not load invalid zones.

Without this patch, it was possible to load an invalid zone without
proper SOA or NS records because the fake SOA and NS records allowed
checks in dns_zone_load() to pass.

With this patch, no fake SOA or NS records are created and
dns_zone_load() is not called before end of the initial synchronization.

See the function ldapdb_associate() in ldap_driver.c and it's comments.

Patch 207 v2 fixes reconnecting to LDAP.

dns_db_detachnode() call in update_record() function was moved to the cleanup section - this is workaround for ISC bug #35080.

This patch should go to master branch.

--
Petr^2 Spacek

From b3c3bb20ce89c667527f5aba41dc2709630cd6c0 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Wed, 27 Nov 2013 16:25:30 +0100
Subject: [PATCH] Do not load invalid zones.

Without this patch, it was possible to load an invalid zone without
proper SOA or NS records because the fake SOA and NS records allowed
checks in dns_zone_load() to pass.

With this patch, no fake SOA or NS records are created and
dns_zone_load() is not called before end of the initial synchronization.

See the function ldapdb_associate() in ldap_driver.c and it's comments.

Signed-off-by: Petr Spacek <pspa...@redhat.com>
---
 src/ldap_driver.c   | 124 ++++++++++++++----------------------
 src/ldap_driver.h   |  16 ++++-
 src/ldap_helper.c   | 179 +++++++++++++++++++++++++++++++++++++---------------
 src/ldap_helper.h   |   9 ++-
 src/syncrepl.c      |   4 +-
 src/types.h         |   3 +
 src/zone_register.c |  15 ++++-
 src/zone_register.h |   2 -
 8 files changed, 215 insertions(+), 137 deletions(-)

diff --git a/src/ldap_driver.c b/src/ldap_driver.c
index 56db0bf6595d3a8815504d05eb2b509ea03f6c62..96dba87609260101da4c5dba7c7a07cf0d382070 100644
--- a/src/ldap_driver.c
+++ b/src/ldap_driver.c
@@ -65,7 +65,7 @@
 #define VALID_LDAPDB(ldapdb) \
 	((ldapdb) != NULL && (ldapdb)->common.impmagic == LDAPDB_MAGIC)
 
-typedef struct {
+struct ldapdb {
 	dns_db_t			common;
 	isc_refcount_t			refs;
 	ldap_instance_t			*ldap_inst;
@@ -91,7 +91,7 @@ typedef struct {
 	 * The purpose is to detect moment when the new version is closed.
 	 * That is the right time for unlocking newversion_lock. */
 	dns_dbversion_t			*newversion;
-} ldapdb_t;
+};
 
 dns_db_t * ATTR_NONNULLS
 ldapdb_get_rbtdb(dns_db_t *db) {
@@ -908,83 +908,57 @@ dns_ns_buildrdata(dns_name_t *origin, dns_name_t *ns_name,
 				      &ns, &rdatabuf));
 }
 
-/*
- * Create an SOA record for a newly-created zone
+/**
+ * Associate a pre-existing LDAP DB instance with a new DNS zone.
+ *
+ * @warning This is a hack.
+ *
+ * Normally, an empty database is created by dns_db_create() call during
+ * dns_zone_load().
+ *
+ * In our case, we need to create and populate databases on-the-fly
+ * as we process data from LDAP.
+ * We create an empty LDAP DB (which encapsulates internal RBT DB)
+ * for each zone when the zone is being added to zone_register.
+ *
+ * The database in zone register is modified on-the-fly and subsequent
+ * dns_db_create() call associates this populated database with the DNS zone.
+ *
+ * This allows us to call dns_zone_load() later when all the data are in place,
+ * so dns_zone_load() can be postponed until synchronization state sync_finish
+ * is reached.
+ *
+ * @param[in] argv [0] is database instance name
  */
-static isc_result_t ATTR_NONNULLS
-add_soa(isc_mem_t *mctx, dns_name_t *origin, dns_db_t *db) {
+isc_result_t
+ldapdb_associate(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
+		 dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+		 void *driverarg, dns_db_t **dbp) {
+
 	isc_result_t result;
-	dns_rdata_t rdata_soa = DNS_RDATA_INIT;
-	dns_rdata_t rdata_ns = DNS_RDATA_INIT;
-	unsigned char buf_soa[DNS_SOA_BUFFERSIZE];
-	unsigned char buf_ns[DNS_SOA_BUFFERSIZE];
-	dns_fixedname_t ns_name;
-	dns_fixedname_t m_name;
-	dns_dbversion_t *ver = NULL;
-	dns_difftuple_t *tp_soa = NULL;
-	dns_difftuple_t *tp_ns = NULL;
-	dns_diff_t diff;
+	ldap_instance_t *ldap_inst = NULL;
+	zone_register_t *zr = NULL;
 
-	dns_diff_init(mctx, &diff);
-	result = dns_db_newversion(db, &ver);
-	if (result != ISC_R_SUCCESS) {
-		log_error_r("add_soa:dns_db_newversion");
-		goto failure;
-	}
+	UNUSED(driverarg); /* Currently we don't need any data */
 
-	/* Build SOA record */
-	dns_fixedname_init(&m_name);
-	dns_name_fromstring(dns_fixedname_name(&m_name), "pspacek.brq.redhat.com.", 0, mctx);
-	result = dns_soa_buildrdata(dns_fixedname_name(&m_name), dns_rootname, dns_rdataclass_in,
-				    0, 0, 0, 0, 0, buf_soa, &rdata_soa);
-	if (result != ISC_R_SUCCESS) {
-		log_error_r("add_soa:dns_soa_buildrdata");
-		goto failure;
-	}
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+	REQUIRE(argc == LDAP_DB_ARGC);
+	REQUIRE(type == LDAP_DB_TYPE);
+	REQUIRE(rdclass == LDAP_DB_RDATACLASS);
+	REQUIRE(dbp != NULL && *dbp == NULL);
 
-	result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, 3600,
-				      &rdata_soa, &tp_soa);
-	if (result != ISC_R_SUCCESS) {
-			log_error_r("add_soa:dns_difftuple_create");
-			goto failure;
-	}
-	dns_diff_append(&diff, &tp_soa);
+	CHECK(manager_get_ldap_instance(argv[0], &ldap_inst));
+	zr = ldap_instance_getzr(ldap_inst);
+	if (zr == NULL)
+		CLEANUP_WITH(ISC_R_NOTFOUND);
 
-	/* Build NS record */
-	dns_fixedname_init(&ns_name);
-	dns_name_fromstring(dns_fixedname_name(&ns_name), "localhost.", 0, mctx);
+	CHECK(zr_get_zone_dbs(zr, name, dbp, NULL));
 
-	result = dns_ns_buildrdata(origin, dns_fixedname_name(&ns_name),
-			dns_rdataclass_in,
-			buf_ns,
-			&rdata_ns);
-	if (result != ISC_R_SUCCESS) {
-			log_error_r("add_soa:dns_ns_buildrdata");
-			goto failure;
-	}
-	result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, 3600,
-				      &rdata_ns, &tp_ns);
-	if (result != ISC_R_SUCCESS) {
-			log_error_r("add_soa:dns_difftuple_create");
-			goto failure;
-	}
-	dns_diff_append(&diff, &tp_ns);
-
-	result = dns_diff_apply(&diff, db, ver);
-	if (result != ISC_R_SUCCESS) {
-			log_error_r("add_soa:dns_difftuple_create");
-			goto failure;
-	}
-
-failure:
-	dns_diff_clear(&diff);
-	if (ver != NULL)
-		dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
-
-	return (result);
+cleanup:
+	return result;
 }
 
-static isc_result_t
+isc_result_t
 ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
 	      dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
 	      void *driverarg, dns_db_t **dbp)
@@ -996,10 +970,9 @@ ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
 	UNUSED(driverarg); /* Currently we don't need any data */
 
 	/* Database instance name. */
-	REQUIRE(argc > 0);
-
-	REQUIRE(type == dns_dbtype_zone);
-	REQUIRE(rdclass == dns_rdataclass_in);
+	REQUIRE(argc == LDAP_DB_ARGC);
+	REQUIRE(type == LDAP_DB_TYPE);
+	REQUIRE(rdclass == LDAP_DB_RDATACLASS);
 	REQUIRE(dbp != NULL && *dbp == NULL);
 
 	CHECKED_MEM_GET_PTR(mctx, ldapdb);
@@ -1025,7 +998,6 @@ ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
 
 	CHECK(dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
 			    dns_rdataclass_in, 0, NULL, &ldapdb->rbtdb));
-	CHECK(add_soa(mctx, name, ldapdb->rbtdb));
 
 	*dbp = (dns_db_t *)ldapdb;
 
@@ -1071,7 +1043,7 @@ dynamic_driver_init(isc_mem_t *mctx, const char *name, const char * const *argv,
 	 */
 
 	/* Register new DNS DB implementation. */
-	result = dns_db_register(ldapdb_impname, &ldapdb_create, NULL, mctx,
+	result = dns_db_register(ldapdb_impname, &ldapdb_associate, NULL, mctx,
 				 &ldapdb_imp_new);
 	if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
 		return result;
diff --git a/src/ldap_driver.h b/src/ldap_driver.h
index 8cd026c823324dd450c8e738891310a3445dbb2c..984eca14774371602ab2e31374f94942fc27b843 100644
--- a/src/ldap_driver.h
+++ b/src/ldap_driver.h
@@ -22,9 +22,23 @@
 #define LDAP_DRIVER_H_
 
 #include <dns/diff.h>
+#include <dns/types.h>
 
 #include "util.h"
 
-dns_db_t * ldapdb_get_rbtdb(dns_db_t *db) ATTR_NONNULLS;
+/* values shared by all LDAP database instances */
+#define LDAP_DB_TYPE		dns_dbtype_zone
+#define LDAP_DB_RDATACLASS	dns_rdataclass_in
+#define LDAP_DB_ARGC		1
+
+typedef struct ldapdb ldapdb_t;
+
+isc_result_t
+ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
+	      dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+	      void *driverarg, dns_db_t **dbp) ATTR_NONNULL(1,2,6,8);
+
+dns_db_t *
+ldapdb_get_rbtdb(dns_db_t *db) ATTR_NONNULLS;
 
 #endif /* LDAP_DRIVER_H_ */
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 9b6b4b2173138af2c79a3222cd9b99596038f302..5d5046bbfedf02f7e68fbd3dc4835fa0914312ee 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -852,32 +852,99 @@ cleanup:
 }
 
 static isc_result_t ATTR_NONNULLS
-publish_zone(ldap_instance_t *inst, dns_zone_t *zone)
+load_zone(dns_zone_t *zone) {
+	isc_result_t result;
+	isc_boolean_t zone_dynamic;
+	isc_uint32_t serial;
+
+	result = dns_zone_load(zone);
+	if (result != ISC_R_SUCCESS && result != DNS_R_UPTODATE
+	    && result != DNS_R_DYNAMIC && result != DNS_R_CONTINUE)
+		goto cleanup;
+	zone_dynamic = (result == DNS_R_DYNAMIC);
+
+	CHECK(dns_zone_getserial2(zone, &serial));
+	dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", serial);
+
+	if (zone_dynamic)
+		dns_zone_notify(zone);
+
+cleanup:
+	return result;
+}
+
+/**
+ * Add zone to the view defined in inst->view.
+ */
+static isc_result_t ATTR_NONNULLS
+publish_zone(isc_task_t *task, ldap_instance_t *inst, dns_zone_t *zone)
 {
 	isc_result_t result;
 	isc_boolean_t freeze = ISC_FALSE;
+	dns_zone_t *zone_in_view = NULL;
+	dns_view_t *view_in_zone = NULL;
+	isc_boolean_t unlock = ISC_FALSE;
 
+	REQUIRE(ISCAPI_TASK_VALID(task));
 	REQUIRE(inst != NULL);
 	REQUIRE(zone != NULL);
 
+	/* Return success if the zone is already in the view as expected. */
+	result = dns_view_findzone(inst->view, dns_zone_getorigin(zone),
+				   &zone_in_view);
+	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+		goto cleanup;
+
+	view_in_zone = dns_zone_getview(zone);
+	if (view_in_zone != NULL) {
+		/* Zone has a view set -> view should contain the same zone. */
+		if (zone_in_view == zone) {
+			/* Zone is already published in the right view. */
+			CLEANUP_WITH(ISC_R_SUCCESS);
+		} else {
+			dns_zone_log(zone, ISC_LOG_ERROR, "zone->view doesn't "
+				     "match data in the view");
+			CLEANUP_WITH(ISC_R_UNEXPECTED);
+		}
+	} else if (zone_in_view != NULL) {
+		dns_zone_log(zone, ISC_LOG_ERROR, "cannot publish zone: view "
+			     "already contains another zone with this name");
+		CLEANUP_WITH(ISC_R_UNEXPECTED);
+	} /* else if (zone_in_view == NULL && view_in_zone == NULL)
+	     Publish the zone. */
+
+	result = isc_task_beginexclusive(task);
+	RUNTIME_CHECK(result == ISC_R_SUCCESS ||
+		      result == ISC_R_LOCKBUSY);
+	unlock = (result == ISC_R_SUCCESS);
+
 	if (inst->view->frozen) {
 		freeze = ISC_TRUE;
 		dns_view_thaw(inst->view);
 	}
 
 	dns_zone_setview(zone, inst->view);
 	CHECK(dns_view_addzone(inst->view, zone));
 
 cleanup:
+	if (zone_in_view != NULL)
+		dns_zone_detach(&zone_in_view);
 	if (freeze)
 		dns_view_freeze(inst->view);
+	if (unlock)
+		isc_task_endexclusive(task);
 
 	return result;
 }
 
+/**
+ * Add all zones in zone register to DNS view specified in inst->view
+ * and load zones.
+ */
 isc_result_t
-publish_zones(ldap_instance_t *inst) {
+activate_zones(isc_task_t *task, ldap_instance_t *inst) {
 	isc_result_t result;
+	isc_boolean_t loaded;
 	rbt_iterator_t *iter = NULL;
 	dns_zone_t *zone = NULL;
 	DECLARE_BUFFERED_NAME(name);
@@ -889,12 +956,24 @@ publish_zones(ldap_instance_t *inst) {
 	do {
 		++total_cnt;
 		CHECK(zr_get_zone_ptr(inst->zone_register, &name, &zone));
-		result = publish_zone(inst, zone);
+		/*
+		 * Don't bother if load fails, server will return
+		 * SERVFAIL for queries beneath this zone. This is
+		 * admin's problem.
+		 */
+		result = load_zone(zone);
+		loaded = (result == ISC_R_SUCCESS);
+		if (loaded == ISC_FALSE)
+			dns_zone_log(zone, ISC_LOG_ERROR,
+				     "unable to load zone: %s",
+				     dns_result_totext(result));
+
+		result = publish_zone(task, inst, zone);
 		if (result != ISC_R_SUCCESS)
 			dns_zone_log(zone, ISC_LOG_ERROR,
 				     "cannot add zone to view: %s",
 				     dns_result_totext(result));
-		else
+		else if (loaded == ISC_TRUE)
 			++published_cnt;
 		dns_zone_detach(&zone);
 
@@ -1549,12 +1628,15 @@ diff_analyze_serial(dns_diff_t *diff, dns_difftuple_t **soa_latest,
 			} else if (t->op == DNS_DIFFOP_ADD ||
 				   t->op == DNS_DIFFOP_ADDRESIGN) {
 				/* add operation has to follow a delete */
-				INSIST(del_soa != NULL);
 				*soa_latest = t;
 
-				/* detect if fields other than serial
-				 * were changed (compute only if necessary) */
-				if (*data_changed == ISC_FALSE) {
+				/* we are adding SOA without preceding delete
+				 * -> we are initializing new empty zone */
+				if (del_soa == NULL) {
+					*data_changed = ISC_TRUE;
+				} else if (*data_changed == ISC_FALSE) {
+					/* detect if fields other than serial
+					 * were changed (compute only if necessary) */
 					CHECK(dns_difftuple_copy(t, &tmp_tuple));
 					dns_soa_setserial(dns_soa_getserial(del_soa),
 							  &tmp_tuple->rdata);
@@ -1648,21 +1730,20 @@ cleanup:
 
 /* Parse the master zone entry */
 static isc_result_t ATTR_NONNULLS
-ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
+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 *zone = NULL;
 	dns_zone_t *zone_raw = NULL;
 	isc_result_t result;
 	isc_boolean_t unlock = ISC_FALSE;
-	isc_boolean_t publish = ISC_FALSE;
+	isc_boolean_t new_zone = ISC_FALSE;
 	isc_boolean_t configured = ISC_FALSE;
 	isc_boolean_t ssu_changed;
-	isc_task_t *task = inst->task;
 	ldapdb_rdatalist_t rdatalist;
-	isc_boolean_t zone_dynamic = ISC_FALSE;
 	settings_set_t *zone_settings = NULL;
 	const char *fake_mname = NULL;
 	isc_boolean_t data_changed;
@@ -1674,6 +1755,8 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
 	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;
@@ -1726,7 +1809,7 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
 		CHECK(create_zone(inst, &name, &zone));
 		CHECK(configure_paths(inst->mctx, inst, zone, ISC_FALSE));
 		CHECK(zr_add_zone(inst->zone_register, zone, dn));
-		publish = ISC_TRUE;
+		new_zone = ISC_TRUE;
 		log_debug(2, "created zone %p: %s", zone, dn);
 	} else if (result != ISC_R_SUCCESS)
 		goto cleanup;
@@ -1789,29 +1872,14 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
 	}
 
 	sync_state_get(inst->sctx, &sync_state);
-	if (publish == ISC_TRUE && sync_state == sync_finished)
-		CHECK(publish_zone(inst, zone));
-	configured = ISC_TRUE;
-
-	/*
-	 * Don't bother if load fails, server will return
-	 * SERVFAIL for queries beneath this zone. This is
-	 * admin's problem.
-	 */
-
-	/* !!! We should parse existing zone records before dns_zone_load(). */
-	result = dns_zone_load(zone);
-	if (result != ISC_R_SUCCESS && result != DNS_R_UPTODATE
-		&& result != DNS_R_DYNAMIC && result != DNS_R_CONTINUE)
-		goto cleanup;
-	zone_dynamic = (result == DNS_R_DYNAMIC);
+	if (new_zone == ISC_TRUE && sync_state == sync_finished)
+		CHECK(publish_zone(task, inst, zone));
 
 	/* 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(dns_zone_getserial2(zone, &curr_serial));
 
 	CHECK(zr_get_zone_dbs(inst->zone_register, &name, &ldapdb, &rbtdb));
 	CHECK(dns_db_newversion(ldapdb, &version));
@@ -1825,11 +1893,12 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
 	} else if (result != ISC_R_NOTFOUND)
 		goto cleanup;
 
-	dns_db_detachnode(rbtdb, &node);
+	/* 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. */
-	sync_state_get(inst->sctx, &sync_state);
 	CHECK(diff_analyze_serial(&diff, &soa_tuple, &data_changed));
 	if (data_changed == ISC_TRUE || sync_state != sync_finished) {
 		if (soa_tuple == NULL) {
@@ -1845,9 +1914,9 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
 			CHECK(update_soa_serial(dns_updatemethod_unixtime,
 						soa_tuple, &new_serial));
 			dns_diff_appendminimal(&diff, &soa_tuple);
-		} else if (sync_state != sync_finished ||
+		} else if (new_zone == ISC_TRUE || sync_state != sync_finished ||
 			   isc_serial_le(dns_soa_getserial(&soa_tuple->rdata),
-					 curr_serial) || publish == ISC_TRUE) {
+					 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. */
@@ -1866,7 +1935,7 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
 			/* The diff is empty => do nothing. */
 			INSIST(EMPTY(diff.tuples));
 		} else if (isc_serial_le(dns_soa_getserial(&soa_tuple->rdata),
-				       curr_serial)) {
+					 curr_serial)) {
 			/* Attempt to move serial backwards without any data
 			 * => ignore it. */
 			dns_diff_clear(&diff);
@@ -1891,7 +1960,7 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
 	}
 
 	if (!EMPTY(diff.tuples)) {
-		if (sync_state == sync_finished) {
+		if (sync_state == sync_finished && new_zone == ISC_FALSE) {
 			/* write the transaction to journal */
 			dns_zone_getraw(zone, &zone_raw);
 			if (zone_raw == NULL)
@@ -1908,11 +1977,14 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
 		dns_db_closeversion(ldapdb, &version, ISC_TRUE);
 	}
 
-	CHECK(dns_zone_getserial2(zone, &curr_serial));
-	if (publish)
-		dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", curr_serial);
-	if (zone_dynamic)
-		dns_zone_notify(zone);
+	/* 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(zone));
 
 cleanup:
 	dns_diff_clear(&diff);
@@ -1930,17 +2002,12 @@ cleanup:
 		dns_journal_destroy(&journal);
 	if (ldapdb != NULL)
 		dns_db_detach(&ldapdb);
-	if (publish && !configured) { /* Failure in ACL parsing or so. */
+	if (new_zone && !configured) { /* Failure in ACL parsing or so. */
 		log_error_r("zone '%s': publishing failed, rolling back due to",
 			    entry->dn);
-		result = delete_forwarding_table(inst, &name, "zone", entry->dn);
+		result = ldap_delete_zone2(inst, &name, ISC_TRUE, ISC_FALSE);
 		if (result != ISC_R_SUCCESS)
-			log_error_r("zone '%s': rollback failed: forwarding",
-				    entry->dn);
-		result = zr_del_zone(inst->zone_register, &name);
-		if (result != ISC_R_SUCCESS)
-			log_error_r("zone '%s': rollback failed: zone register",
-				    entry->dn);
+			log_error_r("zone '%s': rollback failed: ", entry->dn);
 	}
 	if (unlock)
 		isc_task_endexclusive(task);
@@ -3749,7 +3816,7 @@ update_zone(isc_task_t *task, isc_event_t *event)
 	if (zone_active) {
 		CHECK(ldap_entry_getclass(entry, &objclass));
 		if (objclass & LDAP_ENTRYCLASS_MASTER)
-			CHECK(ldap_parse_master_zoneentry(entry, inst));
+			CHECK(ldap_parse_master_zoneentry(entry, inst, task));
 		else if (objclass & LDAP_ENTRYCLASS_FORWARD)
 			CHECK(ldap_parse_fwd_zoneentry(entry, inst));
 
@@ -4631,3 +4698,15 @@ ldap_instance_getsettings_local(ldap_instance_t *ldap_inst)
 {
 	return ldap_inst->local_settings;
 }
+
+const char *
+ldap_instance_getdbname(ldap_instance_t *ldap_inst)
+{
+	return ldap_inst->db_name;
+}
+
+zone_register_t *
+ldap_instance_getzr(ldap_instance_t *ldap_inst)
+{
+	return ldap_inst->zone_register;
+}
diff --git a/src/ldap_helper.h b/src/ldap_helper.h
index bab8bf556ef97612790b7fcddf28a0df7626e8d6..1166ab5fa38e19caf0f13f0f0b8d02c9434ff0e0 100644
--- a/src/ldap_helper.h
+++ b/src/ldap_helper.h
@@ -24,13 +24,12 @@
 
 #include "settings.h"
 #include "types.h"
+#include "zone_register.h"
 
 #include <isc/util.h>
 
 #define LDAPDB_EVENTCLASS 		ISC_EVENTCLASS(0xDDDD)
 
-typedef struct ldap_instance	ldap_instance_t;
-
 isc_result_t ldapdb_rdatalist_findrdatatype(ldapdb_rdatalist_t *rdatalist,
 					    dns_rdatatype_t rdtype,
 					    dns_rdatalist_t **rdlistp) ATTR_NONNULLS;
@@ -100,6 +99,10 @@ remove_entry_from_ldap(dns_name_t *owner, ldap_instance_t *ldap_inst) ATTR_NONNU
 
 settings_set_t * ldap_instance_getsettings_local(ldap_instance_t *ldap_inst) ATTR_NONNULLS;
 
-isc_result_t publish_zones(ldap_instance_t *inst);
+const char * ldap_instance_getdbname(ldap_instance_t *ldap_inst) ATTR_NONNULLS;
+
+zone_register_t * ldap_instance_getzr(ldap_instance_t *ldap_inst) ATTR_NONNULLS;
+
+isc_result_t activate_zones(isc_task_t *task, ldap_instance_t *inst);
 
 #endif /* !_LD_LDAP_HELPER_H_ */
diff --git a/src/syncrepl.c b/src/syncrepl.c
index 967557c395ead0d579c8e49a9196225d3084cf7b..d3a8ca681a1ed7d15b3b9e3f790bbc837546694e 100644
--- a/src/syncrepl.c
+++ b/src/syncrepl.c
@@ -113,7 +113,7 @@ barrier_decrement(isc_task_t *task, isc_event_t *event) {
 	sync_barrierev_t *bev = NULL;
 	isc_uint32_t cnt;
 
-	UNUSED(task);
+	REQUIRE(ISCAPI_TASK_VALID(task));
 	REQUIRE(event != NULL);
 
 	bev = (sync_barrierev_t *)event;
@@ -126,7 +126,7 @@ barrier_decrement(isc_task_t *task, isc_event_t *event) {
 		bev->sctx->state = sync_finished;
 		isc_condition_broadcast(&bev->sctx->cond);
 		UNLOCK(&bev->sctx->mutex);
-		publish_zones(inst);
+		activate_zones(task, inst);
 	}
 
 cleanup:
diff --git a/src/types.h b/src/types.h
index c5053924be48385f4ac01f0ec95fc12cac49a128..1ca1411d1d29ce1e8475a3f9fa888519e08a730a 100644
--- a/src/types.h
+++ b/src/types.h
@@ -46,4 +46,7 @@ typedef struct enum_txt_assoc {
 	const char	*description;
 } enum_txt_assoc_t;
 
+typedef struct ldap_instance	ldap_instance_t;
+typedef struct zone_register	zone_register_t;
+
 #endif /* !_LD_TYPES_H_ */
diff --git a/src/zone_register.c b/src/zone_register.c
index a7d55c8d34bbef210c0ec676cd9a9635e8dfef71..f25c15b5d6581a7033345fb411a23f9c49937bcc 100644
--- a/src/zone_register.c
+++ b/src/zone_register.c
@@ -60,6 +60,7 @@ typedef struct {
 	dns_zone_t	*zone;
 	char		*dn;
 	settings_set_t	*settings;
+	dns_db_t	*ldapdb;
 } zone_info_t;
 
 /* Callback for dns_rbt_create(). */
@@ -231,12 +232,14 @@ cleanup:
 #define PRINT_BUFF_SIZE 255
 static isc_result_t ATTR_NONNULLS
 create_zone_info(isc_mem_t *mctx, dns_zone_t *zone, const char *dn,
-		settings_set_t *global_settings, zone_info_t **zinfop)
+		 settings_set_t *global_settings, const char *db_name,
+		 zone_info_t **zinfop)
 {
 	isc_result_t result;
 	zone_info_t *zinfo;
 	char settings_name[PRINT_BUFF_SIZE];
 	ld_string_t *zone_dir = NULL;
+	char *argv[1];
 
 	REQUIRE(zone != NULL);
 	REQUIRE(dn != NULL);
@@ -259,6 +262,11 @@ create_zone_info(isc_mem_t *mctx, dns_zone_t *zone, const char *dn,
 			       NULL, &zone_dir));
 	CHECK(fs_dir_create(str_buf(zone_dir)));
 
+	DE_CONST(db_name, argv[0]);
+	CHECK(ldapdb_create(mctx, dns_zone_getorigin(zone), LDAP_DB_TYPE,
+			    LDAP_DB_RDATACLASS, sizeof(argv)/sizeof(argv[0]),
+			    argv, NULL, &zinfo->ldapdb));
+
 cleanup:
 	if (result == ISC_R_SUCCESS)
 		*zinfop = zinfo;
@@ -285,6 +293,7 @@ delete_zone_info(void *arg1, void *arg2)
 	settings_set_free(&zinfo->settings);
 	isc_mem_free(mctx, zinfo->dn);
 	dns_zone_detach(&zinfo->zone);
+	dns_db_detach(&zinfo->ldapdb);
 	SAFE_MEM_PUT_PTR(mctx, zinfo);
 }
 
@@ -325,6 +334,7 @@ zr_add_zone(zone_register_t *zr, dns_zone_t *zone, const char *dn)
 	}
 
 	CHECK(create_zone_info(zr->mctx, zone, dn, zr->global_settings,
+			       ldap_instance_getdbname(zr->ldap_inst),
 			       &new_zinfo));
 	CHECK(dns_rbt_addname(zr->rbt, name, new_zinfo));
 
@@ -397,14 +407,13 @@ zr_get_zone_dbs(zone_register_t *zr, dns_name_t *name, dns_db_t **ldapdbp,
 	if (result == DNS_R_PARTIALMATCH)
 		result = ISC_R_SUCCESS;
 	if (result == ISC_R_SUCCESS) {
-		CHECK(dns_zone_getdb(((zone_info_t *)zinfo)->zone, &ldapdb));
+		dns_db_attach(((zone_info_t *)zinfo)->ldapdb, &ldapdb);
 		if (ldapdbp != NULL)
 			dns_db_attach(ldapdb, ldapdbp);
 		if (rbtdbp != NULL)
 			dns_db_attach(ldapdb_get_rbtdb(ldapdb), rbtdbp);
 	}
 
-cleanup:
 	RWUNLOCK(&zr->rwlock, isc_rwlocktype_read);
 	if (ldapdb)
 		dns_db_detach(&ldapdb);
diff --git a/src/zone_register.h b/src/zone_register.h
index 6ff184dc2935952f1d568d0694a6ebc874fda49e..21dc869b17d7779aa2e67796fb3c1a52490803a1 100644
--- a/src/zone_register.h
+++ b/src/zone_register.h
@@ -25,8 +25,6 @@
 #include "rbt_helper.h"
 #include "ldap_helper.h"
 
-typedef struct zone_register zone_register_t;
-
 isc_result_t
 zr_create(isc_mem_t *mctx, ldap_instance_t *ldap_inst,
 	  settings_set_t *glob_settings, zone_register_t **zrp) ATTR_NONNULLS;
-- 
1.8.3.1

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

Reply via email to