pspacek's pull request #1: "[WIP] Port bind-dyndb-ldap to BIND 9.11" was 
synchronize

See the full pull-request at https://github.com/freeipa/bind-dyndb-ldap/pull/1
... or pull the PR as Git branch:
git remote add ghbind-dyndb-ldap https://github.com/freeipa/bind-dyndb-ldap
git fetch ghbind-dyndb-ldap pull/1/head:pr1
git checkout pr1
From 74b1f81c8bd4ebae62691dc321f7a0ab55daadc5 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 15 Aug 2016 18:01:06 +0200
Subject: [PATCH 1/9] BIND 9.11: Remove #if blocks for older BIND versions.

---
 src/Makefile.am   |   1 -
 src/compat.h      |  44 -----------------------
 src/fwd.c         |  60 ++-----------------------------
 src/ldap_driver.c | 103 +++---------------------------------------------------
 4 files changed, 6 insertions(+), 202 deletions(-)
 delete mode 100644 src/compat.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 238d8ef..c5de9ce 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,7 +4,6 @@ bindplugindir=$(libdir)/bind
 HDRS =				\
 	acl.h			\
 	bindcfg.h		\
-	compat.h		\
 	empty_zones.h		\
 	fs.h			\
 	fwd.h			\
diff --git a/src/compat.h b/src/compat.h
deleted file mode 100644
index 00e3da5..0000000
--- a/src/compat.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2009  bind-dyndb-ldap authors; see COPYING for license
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#else
-#error "Can't compile without config.h"
-#endif
-
-/*
- * dns_rdatalist_fromrdataset() did not exist in older versions of libdns.
- * Add a substitude function here.
- */
-#if LIBDNS_VERSION_MAJOR < 40
-static inline isc_result_t
-dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
-			   dns_rdatalist_t **rdatalist)
-{
-	REQUIRE(rdatalist != NULL && rdataset != NULL);
-
-	*rdatalist = rdataset->private1;
-
-	return ISC_R_SUCCESS;
-}
-#endif /* LIBDNS_VERSION_MAJOR < 40 */
-
-/*
- * In older libdns versions, isc_refcount_init() was defined as a macro.
- * However, in newer versions, it is a function returning isc_result_t type.
- * This piece of code should take care of that problem.
- */
-#if LIBDNS_VERSION_MAJOR < 30
-#include <isc/refcount.h>
-
-static inline isc_result_t
-isc_refcount_init_func(isc_refcount_t *ref, unsigned int n)
-{
-	isc_refcount_init(ref, n);
-	return ISC_R_SUCCESS;
-}
-#undef isc_refcount_init
-#define isc_refcount_init isc_refcount_init_func
-#endif /* LIBDNS_VERSION_MAJOR < 30 */
diff --git a/src/fwd.c b/src/fwd.c
index 1f6a9e5..840f0e8 100644
--- a/src/fwd.c
+++ b/src/fwd.c
@@ -69,11 +69,7 @@ fwd_list_len(dns_forwarders_t *fwdrs) {
 
 	REQUIRE(fwdrs != NULL);
 
-#if LIBDNS_VERSION_MAJOR < 140
-	for (isc_sockaddr_t *fwdr = ISC_LIST_HEAD(fwdrs->addrs);
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 	for (dns_forwarder_t *fwdr = ISC_LIST_HEAD(fwdrs->fwdrs);
-#endif
 	     fwdr != NULL;
 	     fwdr = ISC_LIST_NEXT(fwdr, link)) {
 		len++;
@@ -169,11 +165,7 @@ fwd_print_list_buff(isc_mem_t *mctx, dns_forwarders_t *fwdrs,
 	const cfg_obj_t *faddresses;
 	const cfg_listelt_t *fwdr_cfg; /* config representation */
 	/* internal representation */
-#if LIBDNS_VERSION_MAJOR < 140
-	isc_sockaddr_t *fwdr_int;
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 	dns_forwarder_t *fwdr_int;
-#endif
 
 	isc_buffer_initnull(&tmp_buf);
 	tmp_buf.mctx = mctx;
@@ -197,20 +189,12 @@ fwd_print_list_buff(isc_mem_t *mctx, dns_forwarders_t *fwdrs,
 	 * data from the internal one to cfg data structures.*/
 	faddresses = cfg_tuple_get(forwarders_cfg, "addresses");
 	for (fwdr_int = ISC_LIST_HEAD(
-#if LIBDNS_VERSION_MAJOR < 140
-			fwdrs->addrs
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 			fwdrs->fwdrs
-#endif
 			), fwdr_cfg = cfg_list_first(faddresses);
 	     INSIST((fwdr_int == NULL) == (fwdr_cfg == NULL)), fwdr_int != NULL;
 	     fwdr_int = ISC_LIST_NEXT(fwdr_int, link), fwdr_cfg = cfg_list_next(fwdr_cfg)) {
-#if LIBDNS_VERSION_MAJOR < 140
-		fwdr_cfg->obj->value.sockaddr = *fwdr_int;
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 		fwdr_cfg->obj->value.sockaddrdscp.sockaddr = fwdr_int->addr;
 		fwdr_cfg->obj->value.sockaddrdscp.dscp = fwdr_int->dscp;
-#endif
 	}
 	cfg_print(faddresses, buffer_append_str, &tmp_buf);
 
@@ -259,12 +243,7 @@ fwd_print_list_buff(isc_mem_t *mctx, dns_forwarders_t *fwdrs,
 
 static isc_result_t
 fwd_parse_str(const char *fwdrs_str, isc_mem_t *mctx,
-#if LIBDNS_VERSION_MAJOR < 140
-	isc_sockaddrlist_t *fwdrs
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
-	dns_forwarderlist_t *fwdrs
-#endif
-	)
+	      dns_forwarderlist_t *fwdrs)
 {
 	isc_result_t result = ISC_R_SUCCESS;
 	cfg_parser_t *parser = NULL;
@@ -274,11 +253,7 @@ fwd_parse_str(const char *fwdrs_str, isc_mem_t *mctx,
 	const cfg_listelt_t *listel;
 	const cfg_obj_t *fwdr_cfg;
 	isc_sockaddr_t addr;
-#if LIBDNS_VERSION_MAJOR < 140
-	isc_sockaddr_t *fwdr;
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 	dns_forwarder_t *fwdr;
-#endif
 
 	in_port_t port = 53;
 
@@ -301,12 +276,8 @@ fwd_parse_str(const char *fwdrs_str, isc_mem_t *mctx,
 		if (isc_sockaddr_getport(&addr) == 0)
 			isc_sockaddr_setport(&addr, port);
 		CHECKED_MEM_GET_PTR(mctx, fwdr);
-#if LIBDNS_VERSION_MAJOR < 140
-		*fwdr = addr;
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 		fwdr->addr = addr;
 		fwdr->dscp = cfg_obj_getdscp(fwdr_cfg);
-#endif
 		ISC_LINK_INIT(fwdr, link);
 		ISC_LIST_APPEND(*fwdrs, fwdr, link);
 	}
@@ -320,18 +291,8 @@ fwd_parse_str(const char *fwdrs_str, isc_mem_t *mctx,
 }
 
 static void
-fwdr_list_free(isc_mem_t *mctx,
-#if LIBDNS_VERSION_MAJOR < 140
-	isc_sockaddrlist_t *fwdrs
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
-	dns_forwarderlist_t *fwdrs
-#endif
-	) {
-#if LIBDNS_VERSION_MAJOR < 140
-	isc_sockaddr_t *fwdr;
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
+fwdr_list_free(isc_mem_t *mctx, dns_forwarderlist_t *fwdrs) {
 	dns_forwarder_t *fwdr;
-#endif
 	while (!ISC_LIST_EMPTY(*fwdrs)) {
 		fwdr = ISC_LIST_HEAD(*fwdrs);
 		ISC_LIST_UNLINK(*fwdrs, fwdr, link);
@@ -357,11 +318,7 @@ fwd_setting_isexplicit(isc_mem_t *mctx, const settings_set_t *set,
 	isc_result_t result;
 	setting_t *setting = NULL;
 	dns_fwdpolicy_t	fwdpolicy;
-#if LIBDNS_VERSION_MAJOR < 140
-	isc_sockaddrlist_t fwdrs;
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 	dns_forwarderlist_t fwdrs;
-#endif
 
 	REQUIRE(isexplicit != NULL);
 	ISC_LIST_INIT(fwdrs);
@@ -440,11 +397,7 @@ fwd_parse_ldap(ldap_entry_t *entry, settings_set_t *set) {
 	ldap_valuelist_t values;
 	ldap_value_t *value;
 	isc_buffer_t *tmp_buf = NULL; /* hack: only the base buffer is allocated */
-#if LIBDNS_VERSION_MAJOR < 140
-	isc_sockaddrlist_t fwdrs;
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 	dns_forwarderlist_t fwdrs;
-#endif
 	const char *setting_str = NULL;
 
 	/**
@@ -547,11 +500,7 @@ fwd_configure_zone(const settings_set_t *set, ldap_instance_t *inst,
 	isc_mem_t *mctx = NULL;
 	dns_view_t *view = NULL;
 	isc_result_t lock_state = ISC_R_IGNORE;
-#if LIBDNS_VERSION_MAJOR < 140
-	isc_sockaddrlist_t fwdrs;
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 	dns_forwarderlist_t fwdrs;
-#endif
 	isc_boolean_t is_global_config;
 	dns_fixedname_t foundname;
 	const char *msg_use_global_fwds;
@@ -630,13 +579,8 @@ fwd_configure_zone(const settings_set_t *set, ldap_instance_t *inst,
 	run_exclusive_enter(inst, &lock_state);
 	CHECK(fwd_delete_table(view, name, msg_obj_type, set->name));
 	if (isconfigured == ISC_TRUE) {
-#if LIBDNS_VERSION_MAJOR < 140
-		CHECK(dns_fwdtable_add(view->fwdtable, name, &fwdrs,
-				       fwdpolicy));
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 		CHECK(dns_fwdtable_addfwd(view->fwdtable, name, &fwdrs,
 					  fwdpolicy));
-#endif
 	}
 	dns_view_flushcache(view);
 	run_exclusive_exit(inst, lock_state);
diff --git a/src/ldap_driver.c b/src/ldap_driver.c
index 83ec00a..930489e 100644
--- a/src/ldap_driver.c
+++ b/src/ldap_driver.c
@@ -29,7 +29,6 @@
 
 #include <string.h> /* For memcpy */
 
-#include "compat.h"
 #include "ldap_driver.h"
 #include "ldap_helper.h"
 #include "ldap_convert.h"
@@ -181,18 +180,9 @@ detach(dns_db_t **dbp)
 
 /* !!! This could be required for optimizations (like on-disk cache). */
 static isc_result_t
-#if LIBDNS_VERSION_MAJOR < 140
-beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp)
-{
-
-	UNUSED(db);
-	UNUSED(addp);
-	UNUSED(dbloadp);
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
 	UNUSED(db);
 	UNUSED(callbacks);
-#endif /* LIBDNS_VERSION_MAJOR >= 140 */
 
 	fatal_error("ldapdb: method beginload() should never be called");
 
@@ -207,17 +197,9 @@ beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
 
 /* !!! This could be required for optimizations (like on-disk cache). */
 static isc_result_t
-#if LIBDNS_VERSION_MAJOR < 140
-endload(dns_db_t *db, dns_dbload_t **dbloadp)
-{
-
-	UNUSED(db);
-	UNUSED(dbloadp);
-#else /* LIBDNS_VERSION_MAJOR >= 140 */
 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
 	UNUSED(db);
 	UNUSED(callbacks);
-#endif /* LIBDNS_VERSION_MAJOR >= 140 */
 
 	fatal_error("ldapdb: method endload() should never be called");
 
@@ -225,7 +207,6 @@ endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
 	return ISC_R_SUCCESS;
 }
 
-#if LIBDNS_VERSION_MAJOR >= 140
 static isc_result_t
 serialize(dns_db_t *db, dns_dbversion_t *version, FILE *file)
 {
@@ -235,23 +216,17 @@ serialize(dns_db_t *db, dns_dbversion_t *version, FILE *file)
 
 	return dns_db_serialize(ldapdb->rbtdb, version, file);
 }
-#endif /* LIBDNS_VERSION_MAJOR >= 140 */
 
 /* !!! This could be required for optimizations (like on-disk cache). */
 static isc_result_t
-dump(dns_db_t *db, dns_dbversion_t *version, const char *filename
-#if LIBDNS_VERSION_MAJOR >= 31
-     , dns_masterformat_t masterformat
-#endif
-     )
+dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
+     dns_masterformat_t masterformat)
 {
 
 	UNUSED(db);
 	UNUSED(version);
 	UNUSED(filename);
-#if LIBDNS_VERSION_MAJOR >= 31
 	UNUSED(masterformat);
-#endif
 
 	fatal_error("ldapdb: method dump() should never be called");
 
@@ -422,22 +397,14 @@ printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out)
 }
 
 static isc_result_t
-createiterator(dns_db_t *db,
-#if LIBDNS_VERSION_MAJOR >= 50
-	       unsigned int options,
-#else
-	       isc_boolean_t relative_names,
-#endif
+createiterator(dns_db_t *db,  unsigned int options,
 	       dns_dbiterator_t **iteratorp)
 {
 	ldapdb_t *ldapdb = (ldapdb_t *) db;
 
 	REQUIRE(VALID_LDAPDB(ldapdb));
-#if LIBDNS_VERSION_MAJOR >= 50
+
 	return dns_db_createiterator(ldapdb->rbtdb, options, iteratorp);
-#else
-	return dns_db_createiterator(ldapdb->rbtdb, relative_names, iteratorp);
-#endif
 }
 
 static isc_result_t
@@ -675,7 +642,6 @@ settask(dns_db_t *db, isc_task_t *task)
 	dns_db_settask(ldapdb->rbtdb, task);
 }
 
-#if LIBDNS_VERSION_MAJOR >= 31
 static isc_result_t
 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep)
 {
@@ -685,9 +651,7 @@ getoriginnode(dns_db_t *db, dns_dbnode_t **nodep)
 
 	return dns_db_getoriginnode(ldapdb->rbtdb, nodep);
 }
-#endif /* LIBDNS_VERSION_MAJOR >= 31 */
 
-#if LIBDNS_VERSION_MAJOR >= 45
 static void
 transfernode(dns_db_t *db, dns_dbnode_t **sourcep, dns_dbnode_t **targetp)
 {
@@ -698,9 +662,7 @@ transfernode(dns_db_t *db, dns_dbnode_t **sourcep, dns_dbnode_t **targetp)
 	dns_db_transfernode(ldapdb->rbtdb, sourcep, targetp);
 
 }
-#endif /* LIBDNS_VERSION_MAJOR >= 45 */
 
-#if LIBDNS_VERSION_MAJOR >= 50
 static isc_result_t
 getnsec3parameters(dns_db_t *db, dns_dbversion_t *version,
 			  dns_hash_t *hash, isc_uint8_t *flags,
@@ -767,9 +729,7 @@ isdnssec(dns_db_t *db)
 
 	return dns_db_isdnssec(ldapdb->rbtdb);
 }
-#endif /* LIBDNS_VERSION_MAJOR >= 50 */
 
-#if LIBDNS_VERSION_MAJOR >= 45
 static dns_stats_t *
 getrrsetstats(dns_db_t *db) {
 	ldapdb_t *ldapdb = (ldapdb_t *) db;
@@ -779,35 +739,7 @@ getrrsetstats(dns_db_t *db) {
 	return dns_db_getrrsetstats(ldapdb->rbtdb);
 
 }
-#endif /* LIBDNS_VERSION_MAJOR >= 45 */
-
-#if LIBDNS_VERSION_MAJOR >= 82 && LIBDNS_VERSION_MAJOR < 140
-static isc_result_t
-rpz_enabled(dns_db_t *db, dns_rpz_st_t *st)
-{
-	ldapdb_t *ldapdb = (ldapdb_t *) db;
-
-	REQUIRE(VALID_LDAPDB(ldapdb));
-
-	return dns_db_rpz_enabled(ldapdb->rbtdb, st);
-}
 
-static void
-rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
-		   dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
-		   dns_rdataset_t *ardataset, dns_rpz_st_t *st,
-		   dns_name_t *query_qname)
-{
-	ldapdb_t *ldapdb = (ldapdb_t *) db;
-
-	REQUIRE(VALID_LDAPDB(ldapdb));
-
-	dns_db_rpz_findips(rpz, rpz_type, zone, ldapdb->rbtdb, version,
-			   ardataset, st, query_qname);
-}
-#endif /* LIBDNS_VERSION_MAJOR >= 82 && LIBDNS_VERSION_MAJOR < 140 */
-
-#if LIBDNS_VERSION_MAJOR >= 140
 void
 rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num)
 {
@@ -827,9 +759,7 @@ rpz_ready(dns_db_t *db)
 
 	return dns_db_rpz_ready(ldapdb->rbtdb);
 }
-#endif /* LIBDNS_VERSION_MAJOR >= 140 */
 
-#if LIBDNS_VERSION_MAJOR >= 90
 static isc_result_t
 findnodeext(dns_db_t *db, dns_name_t *name,
 		   isc_boolean_t create, dns_clientinfomethods_t *methods,
@@ -858,9 +788,7 @@ findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
 			      nodep, foundname, methods, clientinfo, rdataset,
 			      sigrdataset);
 }
-#endif /* LIBDNS_VERSION_MAJOR >= 90 */
 
-#if LIBDNS_VERSION_MAJOR >= 140
 isc_result_t
 setcachestats(dns_db_t *db, isc_stats_t *stats)
 {
@@ -871,11 +799,7 @@ setcachestats(dns_db_t *db, isc_stats_t *stats)
 	return dns_db_setcachestats(ldapdb->rbtdb, stats);
 }
 
-#if LIBDNS_VERSION_MAJOR >= 164
 size_t
-#else
-unsigned int
-#endif /* LIBDNS_VERSION_MAJOR >= 164 */
 hashsize(dns_db_t *db)
 {
 	ldapdb_t *ldapdb = (ldapdb_t *) db;
@@ -884,16 +808,13 @@ hashsize(dns_db_t *db)
 
 	return dns_db_hashsize(ldapdb->rbtdb);
 }
-#endif /* LIBDNS_VERSION_MAJOR >= 140 */
 
 static dns_dbmethods_t ldapdb_methods = {
 	attach,
 	detach,
 	beginload,
 	endload,
-#if LIBDNS_VERSION_MAJOR >= 140
 	serialize, /* see dns_db_serialize(), implementation is not mandatory */
-#endif /* LIBDNS_VERSION_MAJOR >= 140 */
 	dump,
 	currentversion,
 	newversion,
@@ -917,37 +838,21 @@ static dns_dbmethods_t ldapdb_methods = {
 	ispersistent,
 	overmem,
 	settask,
-#if LIBDNS_VERSION_MAJOR >= 31
 	getoriginnode,
-#endif /* LIBDNS_VERSION_MAJOR >= 31 */
-#if LIBDNS_VERSION_MAJOR >= 45
 	transfernode,
-#if LIBDNS_VERSION_MAJOR >= 50
 	getnsec3parameters,
 	findnsec3node,
 	setsigningtime,
 	getsigningtime,
 	resigned,
 	isdnssec,
-#endif /* LIBDNS_VERSION_MAJOR >= 50 */
 	getrrsetstats,
-#endif /* LIBDNS_VERSION_MAJOR >= 45 */
-#if LIBDNS_VERSION_MAJOR >= 82 && LIBDNS_VERSION_MAJOR < 140
-	rpz_enabled,
-	rpz_findips,
-#endif /* LIBDNS_VERSION_MAJOR >= 82 && LIBDNS_VERSION_MAJOR < 140 */
-#if LIBDNS_VERSION_MAJOR >= 140
 	rpz_attach,
 	rpz_ready,
-#endif /* LIBDNS_VERSION_MAJOR >= 140 */
-#if LIBDNS_VERSION_MAJOR >= 90
 	findnodeext,
 	findext,
-#endif /* LIBDNS_VERSION_MAJOR >= 90 */
-#if LIBDNS_VERSION_MAJOR >= 140
 	setcachestats,
 	hashsize
-#endif /* LIBDNS_VERSION_MAJOR >= 140 */
 };
 
 isc_result_t ATTR_NONNULLS

From 958b759234b00123328c8eb7c2efdc4b684121d6 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 15 Aug 2016 18:13:15 +0200
Subject: [PATCH 2/9] BIND 9.11: Add wrapper for new DB API method
 nodefullname.

---
 src/ldap_driver.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/ldap_driver.c b/src/ldap_driver.c
index 930489e..5d67cda 100644
--- a/src/ldap_driver.c
+++ b/src/ldap_driver.c
@@ -809,6 +809,16 @@ hashsize(dns_db_t *db)
 	return dns_db_hashsize(ldapdb->rbtdb);
 }
 
+isc_result_t
+nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name)
+{
+	ldapdb_t *ldapdb = (ldapdb_t *) db;
+
+	REQUIRE(VALID_LDAPDB(ldapdb));
+
+	return dns_db_nodefullname(ldapdb->rbtdb, node, name);
+}
+
 static dns_dbmethods_t ldapdb_methods = {
 	attach,
 	detach,
@@ -852,7 +862,8 @@ static dns_dbmethods_t ldapdb_methods = {
 	findnodeext,
 	findext,
 	setcachestats,
-	hashsize
+	hashsize,
+	nodefullname
 };
 
 isc_result_t ATTR_NONNULLS

From 5e9b5665013f7f8c1227d747cf184d2957eea21c Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 15 Aug 2016 19:18:11 +0200
Subject: [PATCH 3/9] BIND 9.11: Port to new dyndb API.

This is first step which allows the plugin to run.
It requires configuration in format
dyndb <name> <library> {
	{option1 value}
	{option2 value}
};

This will be improved in another patch.
---
 README              |  28 +++----
 configure.ac        |   2 +-
 src/Makefile.am     |   2 -
 src/ldap_driver.c   | 135 ++++++++++++++++++++++++----------
 src/ldap_driver.h   |   8 +-
 src/ldap_helper.c   |  98 +++++++++++--------------
 src/ldap_helper.h   |   6 +-
 src/settings.c      |   6 +-
 src/settings.h      |   2 +-
 src/syncrepl.c      |  28 +++----
 src/syncrepl.h      |   2 +-
 src/types.h         |   2 +-
 src/zone_manager.c  | 205 ----------------------------------------------------
 src/zone_manager.h  |  29 --------
 src/zone_register.c |  11 +--
 15 files changed, 180 insertions(+), 384 deletions(-)
 delete mode 100644 src/zone_manager.c
 delete mode 100644 src/zone_manager.h

diff --git a/README b/README
index 2fd09b5..e90fc26 100644
--- a/README
+++ b/README
@@ -2,15 +2,9 @@
 ===============
 
 The dynamic LDAP back-end is a plug-in for BIND that provides an LDAP
-database back-end capabilities. For now, it requires that BIND is patched
-to support dynamic loading of database back-ends. You can get a patch
-for your version here:
+database back-end capabilities. It requires dyndb interface which is present
+in BIND versions >= 9.11.0rc1.
 
-  https://github.com/pspacek/bind-dynamic_db
-
-Hopefully, the patch will once be included in the official BIND release.
-
-BIND >= 9.9.0 is required.
 
 2. Features
 ===========
@@ -309,19 +303,17 @@ Attributes:
 5. Configuration
 ================
 
-To configure dynamic loading of back-end, you must put a "dynamic-db"
+To configure dynamic loading of back-end, you must put a "dyndb"
 clause into your named.conf. The clause must then be followed by a
-string denoting the name. The name is not that much important, it is
-passed to the plug-in and might be used for example, for logging
-purposes. Following after that is a set of options enclosed between
-curly brackets.
+string denoting the name of the instance and path to dyndb library.
 
-The most important option here is "library". It names a shared object
-file that will be opened and loaded. The "arg" option specifies a string
-that is passed directly to the plugin. You can specify multiple "arg"
-options. The LDAP back-end follows the convention that the first word of
-this string is the name of the setting and the rest is the value.
+The name is not that much important, it is passed to the plug-in
+and is used for logging purposes and for naming working directories.
 
+Library path must point to a shared object file that will be opened and loaded.
+
+Name and library path have to be followed by set of options enclosed between
+curly brackets.
 
 5.1 Configuration options
 -------------------------
diff --git a/configure.ac b/configure.ac
index 9b26058..0311560 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@ AC_INIT([bind-dyndb-ldap], [10.1], [freeipa-devel@redhat.com])
 
 AM_INIT_AUTOMAKE([-Wall foreign dist-bzip2])
 
-AC_CONFIG_SRCDIR([src/zone_manager.h])
+AC_CONFIG_SRCDIR([src/ldap_driver.c])
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIR([m4])
 
diff --git a/src/Makefile.am b/src/Makefile.am
index c5de9ce..e1e3968 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,7 +26,6 @@ HDRS =				\
 	types.h			\
 	util.h			\
 	zone.h			\
-	zone_manager.h		\
 	zone_register.h
 
 ldap_la_SOURCES =		\
@@ -53,7 +52,6 @@ ldap_la_SOURCES =		\
 	syncrepl.c		\
 	str.c			\
 	zone.c			\
-	zone_manager.c		\
 	zone_register.c
 
 ldap_la_CFLAGS = -Wall -Wextra @WERROR@ -std=gnu99 -O2
diff --git a/src/ldap_driver.c b/src/ldap_driver.c
index 5d67cda..7cf877b 100644
--- a/src/ldap_driver.c
+++ b/src/ldap_driver.c
@@ -9,13 +9,17 @@
 #endif
 
 #include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/hash.h>
+#include <isc/lib.h>
 #include <isc/mem.h>
+#include <isc/once.h>
 #include <isc/refcount.h>
 #include <isc/util.h>
 
 #include <dns/db.h>
 #include <dns/diff.h>
-#include <dns/dynamic_db.h>
+#include <dns/dyndb.h>
 #include <dns/dbiterator.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
@@ -29,12 +33,12 @@
 
 #include <string.h> /* For memcpy */
 
+#include "bindcfg.h"
 #include "ldap_driver.h"
 #include "ldap_helper.h"
 #include "ldap_convert.h"
 #include "log.h"
 #include "util.h"
-#include "zone_manager.h"
 #include "zone_register.h"
 
 #ifdef HAVE_VISIBILITY
@@ -918,18 +922,17 @@ ldapdb_associate(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
 		 void *driverarg, dns_db_t **dbp) {
 
 	isc_result_t result;
-	ldap_instance_t *ldap_inst = NULL;
+	ldap_instance_t *ldap_inst = driverarg;
 	zone_register_t *zr = NULL;
 
-	UNUSED(driverarg); /* Currently we don't need any data */
-
 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
-	REQUIRE(argc == LDAP_DB_ARGC);
 	REQUIRE(type == LDAP_DB_TYPE);
 	REQUIRE(rdclass == LDAP_DB_RDATACLASS);
+	REQUIRE(argc == 0);
+	UNUSED(argv);
+	REQUIRE(driverarg != NULL);
 	REQUIRE(dbp != NULL && *dbp == NULL);
 
-	CHECK(manager_get_ldap_instance(argv[0], &ldap_inst));
 	zr = ldap_instance_getzr(ldap_inst);
 	if (zr == NULL)
 		CLEANUP_WITH(ISC_R_NOTFOUND);
@@ -942,19 +945,16 @@ ldapdb_associate(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
 
 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)
+	      dns_rdataclass_t rdclass, void *driverarg, dns_db_t **dbp)
 {
 	ldapdb_t *ldapdb = NULL;
 	isc_result_t result;
 	isc_boolean_t lock_ready = ISC_FALSE;
 
-	UNUSED(driverarg); /* Currently we don't need any data */
-
 	/* Database instance name. */
-	REQUIRE(argc == LDAP_DB_ARGC);
 	REQUIRE(type == LDAP_DB_TYPE);
 	REQUIRE(rdclass == LDAP_DB_RDATACLASS);
+	REQUIRE(driverarg != NULL);
 	REQUIRE(dbp != NULL && *dbp == NULL);
 
 	CHECKED_MEM_GET_PTR(mctx, ldapdb);
@@ -976,7 +976,7 @@ ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
 	CHECK(dns_name_dupwithoffsets(name, mctx, &ldapdb->common.origin));
 
 	CHECK(isc_refcount_init(&ldapdb->refs, 1));
-	CHECK(manager_get_ldap_instance(argv[0], &ldapdb->ldap_inst));
+	ldapdb->ldap_inst = driverarg;
 
 	CHECK(dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
 			    dns_rdataclass_in, 0, NULL, &ldapdb->rbtdb));
@@ -1000,50 +1000,105 @@ ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
 	return result;
 }
 
-static dns_dbimplementation_t *ldapdb_imp;
-const char *ldapdb_impname = "dynamic-ldap";
+static void
+library_init(void)
+{
+       log_info("bind-dyndb-ldap version " VERSION
+                " compiled at " __TIME__ " " __DATE__
+                ", compiler " __VERSION__);
+       cfg_init_types();
+}
+
+/*
+ * Driver version is called when loading the driver to ensure there
+ * is no API mismatch betwen the driver and the caller.
+ */
+VISIBLE int
+dyndb_version(unsigned int *flags) {
+	UNUSED(flags);
 
+	return (DNS_DYNDB_VERSION);
+}
 
+/*
+ * Driver init is called for each dyndb section in named.conf
+ * once during startup and then again on every reload.
+ *
+ * @code
+ * dyndb example-name "sample.so" { param1 param2 };
+ * @endcode
+ *
+ * @param[in] name        User-defined string from dyndb "name" {}; definition
+ *                        in named.conf.
+ *                        The example above will have name = "example-name".
+ * @param[in] parameters  User-defined parameters from dyndb section as one
+ *                        string. The example above will have
+ *                        params = "param1 param2";
+ * @param[out] instp      Pointer to instance-specific data
+ *                        (for one dyndb section).
+ */
 VISIBLE isc_result_t
-dynamic_driver_init(isc_mem_t *mctx, const char *name, const char * const *argv,
-		    dns_dyndb_arguments_t *dyndb_args)
+dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters,
+	   const char *file, unsigned long line, const dns_dyndbctx_t *dctx,
+	   void **instp)
 {
-	dns_dbimplementation_t *ldapdb_imp_new = NULL;
+	unsigned int argc;
+	char **argv = NULL;
+	char *tmps = NULL;
+	ldap_instance_t *inst = NULL;
 	isc_result_t result;
+	static isc_once_t library_init_once = ISC_ONCE_INIT;
 
 	REQUIRE(name != NULL);
-	REQUIRE(argv != NULL);
-	REQUIRE(dyndb_args != NULL);
+	REQUIRE(parameters != NULL);
+	REQUIRE(dctx != NULL);
+	REQUIRE(instp != NULL && *instp == NULL);
 
-	log_debug(2, "registering dynamic ldap driver for %s.", name);
+	RUNTIME_CHECK(isc_once_do(&library_init_once, library_init)
+		      == ISC_R_SUCCESS);
 
 	/*
-	 * We need to discover what rdataset methods does
-	 * dns_rdatalist_tordataset use. We then make a copy for ourselves
-	 * with the exception that we modify the disassociate method to free
-	 * the rdlist we allocate for it in clone_rdatalist_to_rdataset().
+	 * Depending on how dlopen() was called, we may not have
+	 * access to named's global namespace, in which case we need
+	 * to initialize libisc/libdns
 	 */
+	if (dctx->refvar != &isc_bind9) {
+		isc_lib_register();
+		isc_log_setcontext(dctx->lctx);
+		dns_log_setcontext(dctx->lctx);
+	}
 
-	/* Register new DNS DB implementation. */
-	result = dns_db_register(ldapdb_impname, &ldapdb_associate, NULL, mctx,
-				 &ldapdb_imp_new);
-	if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
-		return result;
-	else if (result == ISC_R_SUCCESS)
-		ldapdb_imp = ldapdb_imp_new;
+	isc_hash_set_initializer(dctx->hashinit);
+
+	log_debug(2, "registering dynamic ldap driver for %s.", name);
+
+	tmps = isc_mem_strdup(mctx, parameters);
+	if (tmps == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto cleanup;
+	}
+	CHECK(isc_commandline_strtoargv(mctx, tmps, &argc, &argv, 0));
 
 	/* Finally, create the instance. */
-	result = manager_create_db_instance(mctx, name, argv, dyndb_args);
+	CHECK(new_ldap_instance(mctx, name, argc, argv, dctx, &inst));
+	*instp = inst;
+
+cleanup:
+	if (tmps != NULL)
+		isc_mem_free(mctx, tmps);
+	if (argv != NULL)
+		isc_mem_put(mctx, argv, argc * sizeof(*argv));
 
 	return result;
 }
 
+/*
+ * Driver destroy is called for every instance on every reload and then once
+ * during shutdown.
+ *
+ * @param[out] instp Pointer to instance-specific data (for one dyndb section).
+ */
 VISIBLE void
-dynamic_driver_destroy(void)
-{
-	/* Only unregister the implementation if it was registered by us. */
-	if (ldapdb_imp != NULL)
-		dns_db_unregister(&ldapdb_imp);
-
-	destroy_manager();
+dyndb_destroy(void **instp) {
+	destroy_ldap_instance((ldap_instance_t **)instp);
 }
diff --git a/src/ldap_driver.h b/src/ldap_driver.h
index 73c4827..62d50f6 100644
--- a/src/ldap_driver.h
+++ b/src/ldap_driver.h
@@ -19,9 +19,13 @@ 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_rdataclass_t rdclass, void *driverarg, dns_db_t **dbp)
+	      ATTR_NONNULL(1,2,5,6);
 
+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) ATTR_NONNULL(1,2,7,8);
 dns_db_t *
 ldapdb_get_rbtdb(dns_db_t *db) ATTR_NONNULLS;
 
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index ad6e417..58b1d7b 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -4,7 +4,7 @@
 
 #include "config.h"
 
-#include <dns/dynamic_db.h>
+#include <dns/dyndb.h>
 #include <dns/diff.h>
 #include <dns/journal.h>
 #include <dns/rbt.h>
@@ -77,7 +77,6 @@
 #include "syncrepl.h"
 #include "util.h"
 #include "zone.h"
-#include "zone_manager.h"
 #include "zone_register.h"
 #include "rbt_helper.h"
 #include "fwd_register.h"
@@ -133,7 +132,8 @@ struct ldap_instance {
 	isc_mem_t		*mctx;
 
 	/* These are needed for zone creation. */
-	const char *		db_name;
+	char *			db_name;
+	dns_dbimplementation_t	*db_imp;
 	dns_view_t		*view;
 	dns_zonemgr_t		*zmgr;
 
@@ -184,12 +184,6 @@ struct ldap_connection {
 	unsigned int		tries;
 };
 
-/*
- * Constants.
- */
-
-extern const char *ldapdb_impname;
-
 /* Supported authentication types. */
 const ldap_auth_pair_t supported_ldap_auth[] = {
 	{ AUTH_NONE,	"none"		},
@@ -505,13 +499,12 @@ validate_local_instance_settings(ldap_instance_t *inst, settings_set_t *set) {
 
 #define PRINT_BUFF_SIZE 255
 isc_result_t
-new_ldap_instance(isc_mem_t *mctx, const char *db_name,
-		  const char * const *argv, dns_dyndb_arguments_t *dyndb_args,
-		  isc_task_t *task, ldap_instance_t **ldap_instp)
+new_ldap_instance(isc_mem_t *mctx, const char *db_name, unsigned int argc,
+		  char **argv, const dns_dyndbctx_t *dctx,
+		  ldap_instance_t **ldap_instp)
 {
 	isc_result_t result;
 	ldap_instance_t *ldap_inst;
-	dns_view_t *view = NULL;
 	dns_forwarders_t *named_conf_forwarders = NULL;
 	isc_buffer_t *forwarders_list = NULL;
 	const char *forward_policy = NULL;
@@ -526,30 +519,29 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name,
 	ZERO_PTR(ldap_inst);
 	CHECK(isc_refcount_init(&ldap_inst->errors, 0));
 	isc_mem_attach(mctx, &ldap_inst->mctx);
+	CHECKED_MEM_STRDUP(mctx, db_name, ldap_inst->db_name);
+	dns_view_attach(dctx->view, &ldap_inst->view);
+	dns_zonemgr_attach(dctx->zmgr, &ldap_inst->zmgr);
+	isc_task_attach(dctx->task, &ldap_inst->task);
 
-	ldap_inst->db_name = db_name;
-	view = dns_dyndb_get_view(dyndb_args);
-	dns_view_attach(view, &ldap_inst->view);
-	ldap_inst->zmgr = dns_dyndb_get_zonemgr(dyndb_args);
-	ldap_inst->task = task;
 	ldap_inst->watcher = 0;
 	CHECK(sync_ctx_init(ldap_inst->mctx, ldap_inst, &ldap_inst->sctx));
 
 	isc_string_printf_truncate(settings_name, PRINT_BUFF_SIZE,
 				   SETTING_SET_NAME_LOCAL " for database %s",
-				   db_name);
+				   ldap_inst->db_name);
 	CHECK(settings_set_create(mctx, settings_local_default,
 	      sizeof(settings_local_default), settings_name,
 	      &settings_default_set, &ldap_inst->local_settings));
 
 	isc_string_printf_truncate(settings_name, PRINT_BUFF_SIZE,
 				   SETTING_SET_NAME_GLOBAL " for database %s",
-				   db_name);
+				   ldap_inst->db_name);
 	CHECK(settings_set_create(mctx, settings_global_default,
 	      sizeof(settings_global_default), settings_name,
 	      ldap_inst->local_settings, &ldap_inst->global_settings));
 
-	CHECK(settings_set_fill(ldap_inst->local_settings, argv));
+	CHECK(settings_set_fill(ldap_inst->local_settings, argc, argv));
 
 	/* copy global forwarders setting for configuration roll back in
 	 * configure_zone_forwarders() */
@@ -573,7 +565,7 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name,
 		 *
 		 * Warn-only semantics is implemented in BIND RT#41441,
 		 * this code can be removed when we rebase to BIND 9.11. */
-		CHECK(sync_task_add(ldap_inst->sctx, task));
+		CHECK(sync_task_add(ldap_inst->sctx, ldap_inst->task));
 		gfwdevent = (ldap_globalfwd_handleez_t *)isc_event_allocate(
 					ldap_inst->mctx, ldap_inst,
 					LDAPDB_EVENT_GLOBALFWD_HANDLEEZ,
@@ -586,7 +578,7 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name,
 		gfwdevent->warn_only = (named_conf_forwarders->fwdpolicy
 					== dns_fwdpolicy_first);
 
-		isc_task_send(task, (isc_event_t **)&gfwdevent);
+		isc_task_send(ldap_inst->task, (isc_event_t **)&gfwdevent);
 
 	} else if (result == ISC_R_NOTFOUND) {
 		/* global forwarders are not configured */
@@ -639,6 +631,10 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name,
 	CHECK(ldap_pool_create(mctx, connections, &ldap_inst->pool));
 	CHECK(ldap_pool_connect(ldap_inst->pool, ldap_inst));
 
+	/* Register new DNS DB implementation. */
+	CHECK(dns_db_register(ldap_inst->db_name, &ldapdb_associate, ldap_inst,
+			      mctx, &ldap_inst->db_imp));
+
 	/* Start the watcher thread */
 	result = isc_thread_create(ldap_syncrepl_watcher, ldap_inst,
 				   &ldap_inst->watcher);
@@ -663,7 +659,6 @@ void
 destroy_ldap_instance(ldap_instance_t **ldap_instp)
 {
 	ldap_instance_t *ldap_inst;
-	const char *db_name;
 
 	REQUIRE(ldap_instp != NULL);
 
@@ -671,8 +666,6 @@ destroy_ldap_instance(ldap_instance_t **ldap_instp)
 	if (ldap_inst == NULL)
 		return;
 
-	db_name = ldap_inst->db_name; /* points to DB instance: outside ldap_inst */
-
 	if (ldap_inst->watcher != 0) {
 		ldap_inst->exiting = ISC_TRUE;
 		/*
@@ -695,7 +688,14 @@ destroy_ldap_instance(ldap_instance_t **ldap_instp)
 	mldap_destroy(&ldap_inst->mldapdb);
 
 	ldap_pool_destroy(&ldap_inst->pool);
-	dns_view_detach(&ldap_inst->view);
+	if (ldap_inst->db_imp != NULL)
+		dns_db_unregister(&ldap_inst->db_imp);
+	if (ldap_inst->view != NULL)
+		dns_view_detach(&ldap_inst->view);
+	if (ldap_inst->zmgr != NULL)
+		dns_zonemgr_detach(&ldap_inst->zmgr);
+	if (ldap_inst->task != NULL)
+		isc_task_detach(&ldap_inst->task);
 
 	DESTROYLOCK(&ldap_inst->kinit_lock);
 
@@ -709,10 +709,13 @@ destroy_ldap_instance(ldap_instance_t **ldap_instp)
 				     ldap_instance_untaint_start(ldap_inst));
 	isc_refcount_destroy(&ldap_inst->errors);
 
+	if (ldap_inst->db_name != NULL) {
+		log_debug(1, "LDAP instance '%s' destroyed", ldap_inst->db_name);
+		isc_mem_free(ldap_inst->mctx, ldap_inst->db_name);
+	}
 	MEM_PUT_AND_DETACH(ldap_inst);
 
 	*ldap_instp = NULL;
-	log_debug(1, "LDAP instance '%s' destroyed", db_name);
 }
 
 static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
@@ -916,7 +919,7 @@ create_zone(ldap_instance_t * const inst, const char * const dn,
 	isc_result_t result;
 	dns_zone_t *raw = NULL;
 	dns_zone_t *secure = NULL;
-	const char *ldap_argv[2];
+	const char *ldap_argv[1] = { inst->db_name };
 	const char *rbt_argv[1] = { "rbt" };
 	sync_state_t sync_state;
 	isc_task_t *task = NULL;
@@ -926,9 +929,6 @@ create_zone(ldap_instance_t * const inst, const char * const dn,
 	REQUIRE(name != NULL);
 	REQUIRE(rawp != NULL && *rawp == NULL);
 
-	ldap_argv[0] = ldapdb_impname;
-	ldap_argv[1] = inst->db_name;
-
 	result = zone_unload_ifempty(inst->view, name);
 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
 		goto cleanup;
@@ -938,7 +938,8 @@ create_zone(ldap_instance_t * const inst, const char * const dn,
 	dns_zone_setclass(raw, dns_rdataclass_in);
 	dns_zone_settype(raw, dns_zone_master);
 	/* dns_zone_setview(raw, view); */
-	CHECK(dns_zone_setdbtype(raw, 2, ldap_argv));
+	CHECK(dns_zone_setdbtype(raw, sizeof(ldap_argv)/sizeof(ldap_argv[0]),
+				 ldap_argv));
 	CHECK(configure_paths(inst->mctx, inst, raw, ISC_FALSE));
 
 	if (want_secure == ISC_FALSE) {
@@ -3654,7 +3655,7 @@ update_zone(isc_task_t *task, isc_event_t *event)
 {
 	ldap_syncreplevent_t *pevent = (ldap_syncreplevent_t *)event;
 	isc_result_t result ;
-	ldap_instance_t *inst = NULL;
+	ldap_instance_t *inst = pevent->inst;
 	isc_mem_t *mctx;
 	dns_name_t prevname;
 	ldap_entry_t *entry = pevent->entry;
@@ -3662,7 +3663,6 @@ update_zone(isc_task_t *task, isc_event_t *event)
 	mctx = pevent->mctx;
 	dns_name_init(&prevname, NULL);
 
-	CHECK(manager_get_ldap_instance(pevent->dbname, &inst));
 	INSIST(task == inst->task); /* For task-exclusive mode */
 
 	if (SYNCREPL_DEL(pevent->chgtype)) {
@@ -3673,6 +3673,9 @@ update_zone(isc_task_t *task, isc_event_t *event)
 							  task));
 		else if (entry->class & LDAP_ENTRYCLASS_FORWARD)
 			CHECK(ldap_parse_fwd_zoneentry(entry, inst));
+		else
+			FATAL_ERROR(__FILE__, __LINE__,
+				    "update_zone: unexpected entry class");
 	}
 
 cleanup:
@@ -3687,7 +3690,6 @@ update_zone(isc_task_t *task, isc_event_t *event)
 			    "Zones can be outdated, run `rndc reload`",
 			    ldap_entry_logname(entry));
 
-	isc_mem_free(mctx, pevent->dbname);
 	if (pevent->prevdn != NULL)
 		isc_mem_free(mctx, pevent->prevdn);
 	ldap_entry_destroy(&entry);
@@ -3701,13 +3703,12 @@ update_config(isc_task_t * task, isc_event_t *event)
 {
 	ldap_syncreplevent_t *pevent = (ldap_syncreplevent_t *)event;
 	isc_result_t result;
-	ldap_instance_t *inst = NULL;
+	ldap_instance_t *inst = pevent->inst;
 	ldap_entry_t *entry = pevent->entry;
 	isc_mem_t *mctx;
 
 	mctx = pevent->mctx;
 
-	CHECK(manager_get_ldap_instance(pevent->dbname, &inst));
 	INSIST(task == inst->task); /* For task-exclusive mode */
 	CHECK(ldap_parse_configentry(entry, inst));
 
@@ -3722,7 +3723,6 @@ update_config(isc_task_t * task, isc_event_t *event)
 			    ldap_entry_logname(entry));
 
 	ldap_entry_destroy(&entry);
-	isc_mem_free(mctx, pevent->dbname);
 	isc_mem_detach(&mctx);
 	isc_event_free(&event);
 	isc_task_detach(&task);
@@ -3733,13 +3733,12 @@ update_serverconfig(isc_task_t * task, isc_event_t *event)
 {
 	ldap_syncreplevent_t *pevent = (ldap_syncreplevent_t *)event;
 	isc_result_t result;
-	ldap_instance_t *inst = NULL;
+	ldap_instance_t *inst = pevent->inst;
 	ldap_entry_t *entry = pevent->entry;
 	isc_mem_t *mctx;
 
 	mctx = pevent->mctx;
 
-	CHECK(manager_get_ldap_instance(pevent->dbname, &inst));
 	INSIST(task == inst->task); /* For task-exclusive mode */
 	CHECK(ldap_parse_serverconfigentry(entry, inst));
 
@@ -3754,7 +3753,6 @@ update_serverconfig(isc_task_t * task, isc_event_t *event)
 			    ldap_entry_logname(entry));
 
 	ldap_entry_destroy(&entry);
-	isc_mem_free(mctx, pevent->dbname);
 	isc_mem_detach(&mctx);
 	isc_event_free(&event);
 	isc_task_detach(&task);
@@ -3774,7 +3772,7 @@ update_record(isc_task_t *task, isc_event_t *event)
 	/* syncrepl event */
 	ldap_syncreplevent_t *pevent = (ldap_syncreplevent_t *)event;
 	isc_result_t result;
-	ldap_instance_t *inst = NULL;
+	ldap_instance_t *inst = pevent->inst;
 	isc_mem_t *mctx;
 	settings_set_t *zone_settings = NULL;
 	dns_zone_t *raw = NULL;
@@ -3811,7 +3809,6 @@ update_record(isc_task_t *task, isc_event_t *event)
 	dns_name_init(&prevname, NULL);
 	dns_name_init(&prevorigin, NULL);
 
-	CHECK(manager_get_ldap_instance(pevent->dbname, &inst));
 	CHECK(zr_get_zone_ptr(inst->zone_register, &entry->zone_name, &raw, &secure));
 	zone_found = ISC_TRUE;
 
@@ -3984,7 +3981,6 @@ update_record(isc_task_t *task, isc_event_t *event)
 	if (secure != NULL)
 		dns_zone_detach(&secure);
 	ldapdb_rdatalist_destroy(mctx, &rdatalist);
-	isc_mem_free(mctx, pevent->dbname);
 	if (pevent->prevdn != NULL)
 		isc_mem_free(mctx, pevent->prevdn);
 	ldap_entry_destroy(&entry);
@@ -4055,7 +4051,6 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t **entryp, int chgtype)
 	dns_name_t *zone_name = NULL;
 	dns_zone_t *zone_ptr = NULL;
 	char *dn = NULL;
-	char *dbname = NULL;
 	isc_mem_t *mctx = NULL;
 	isc_taskaction_t action = NULL;
 	isc_task_t *task = NULL;
@@ -4071,8 +4066,6 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t **entryp, int chgtype)
 
 	isc_mem_attach(inst->mctx, &mctx);
 
-	CHECKED_MEM_STRDUP(mctx, inst->db_name, dbname);
-
 	if (entry->class & LDAP_ENTRYCLASS_MASTER)
 		zone_name = &entry->fqdn;
 	else
@@ -4129,7 +4122,7 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t **entryp, int chgtype)
 	}
 
 	pevent->mctx = mctx;
-	pevent->dbname = dbname;
+	pevent->inst = inst;
 	pevent->prevdn = NULL;
 	pevent->chgtype = chgtype;
 	pevent->entry = entry;
@@ -4148,9 +4141,6 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t **entryp, int chgtype)
 	if (pevent != NULL) {
 		/* Event was not sent */
 		sync_concurr_limit_signal(inst->sctx);
-
-		if (dbname != NULL)
-			isc_mem_free(mctx, dbname);
 		if (mctx != NULL)
 			isc_mem_detach(&mctx);
 		ldap_entry_destroy(entryp);
@@ -4394,7 +4384,7 @@ int ldap_sync_intermediate (
 
 	sync_state_get(inst->sctx, &state);
 	if (state == sync_datainit) {
-		result = sync_barrier_wait(inst->sctx, inst->db_name);
+		result = sync_barrier_wait(inst->sctx, inst);
 		if (result != ISC_R_SUCCESS) {
 			log_error_r("%s: sync_barrier_wait() failed for "
 				    "instance '%s'", __func__, inst->db_name);
@@ -4447,7 +4437,7 @@ int ATTR_NONNULLS ATTR_CHECKRESULT ldap_sync_search_result (
 	INSIST(state == sync_configinit || state == sync_finished);
 
 	if (state == sync_configinit) {
-		result = sync_barrier_wait(inst->sctx, inst->db_name);
+		result = sync_barrier_wait(inst->sctx, inst);
 		if (result != ISC_R_SUCCESS) {
 			log_error_r("%s: sync_barrier_wait() failed for "
 				    "instance '%s'", __func__, inst->db_name);
diff --git a/src/ldap_helper.h b/src/ldap_helper.h
index a491bae..773091c 100644
--- a/src/ldap_helper.h
+++ b/src/ldap_helper.h
@@ -40,9 +40,9 @@ void free_rdatalist(isc_mem_t *mctx, dns_rdatalist_t *rdlist) ATTR_NONNULLS;
  */
 
 isc_result_t
-new_ldap_instance(isc_mem_t *mctx, const char *db_name,
-		  const char * const *argv, dns_dyndb_arguments_t *dyndb_args,
-		  isc_task_t *task, ldap_instance_t **ldap_instp) ATTR_NONNULLS;
+new_ldap_instance(isc_mem_t *mctx, const char *db_name, unsigned int argc,
+		  char **argv, const dns_dyndbctx_t *dctx,
+		  ldap_instance_t **ldap_instp) ATTR_NONNULLS;
 void destroy_ldap_instance(ldap_instance_t **ldap_inst) ATTR_NONNULLS;
 
 isc_result_t
diff --git a/src/settings.c b/src/settings.c
index 3692dae..bdcfd67 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -579,14 +579,14 @@ settings_set_free(settings_set_t **set) {
  * @endcode
  */
 isc_result_t
-settings_set_fill(settings_set_t *set, const char *const *argv)
+settings_set_fill(settings_set_t *set, unsigned int argc, char **argv)
 {
 	isc_result_t result;
-	int i;
+	unsigned int i;
 	const char *name;
 	char *value;
 
-	for (i = 0; argv[i] != NULL; i++) {
+	for (i = 0; i < argc; i++) {
 		char buff[SETTING_LINE_MAXLENGTH] = "";
 		CHECK(isc_string_copy(buff, SETTING_LINE_MAXLENGTH, argv[i]));
 		value = buff;
diff --git a/src/settings.h b/src/settings.h
index 9bc4176..b77fcf8 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -82,7 +82,7 @@ void
 settings_set_free(settings_set_t **set) ATTR_NONNULLS;
 
 isc_result_t
-settings_set_fill(settings_set_t *set, const char *const *argv)
+settings_set_fill(settings_set_t *set, unsigned int argc, char **argv)
 		  ATTR_NONNULLS ATTR_CHECKRESULT;
 
 isc_boolean_t
diff --git a/src/syncrepl.c b/src/syncrepl.c
index 0079644..6ed8051 100644
--- a/src/syncrepl.c
+++ b/src/syncrepl.c
@@ -15,7 +15,6 @@
 #include "util.h"
 #include "semaphore.h"
 #include "syncrepl.h"
-#include "zone_manager.h"
 
 #define LDAPDB_EVENT_SYNCREPL_BARRIER	(LDAPDB_EVENTCLASS + 2)
 #define LDAPDB_EVENT_SYNCREPL_FINISH	(LDAPDB_EVENTCLASS + 3)
@@ -109,7 +108,7 @@ struct sync_ctx {
  */
 struct sync_barrierev {
 	ISC_EVENT_COMMON(sync_barrierev_t);
-	const char	*dbname;
+	ldap_instance_t	*inst;
 	sync_ctx_t	*sctx;
 };
 
@@ -122,7 +121,6 @@ struct sync_barrierev {
 void
 finish(isc_task_t *task, isc_event_t *event) {
 	isc_result_t result = ISC_R_SUCCESS;
-	ldap_instance_t *inst = NULL;
 	sync_barrierev_t *bev = NULL;
 	sync_state_t new_state;
 
@@ -130,7 +128,6 @@ finish(isc_task_t *task, isc_event_t *event) {
 	REQUIRE(event != NULL);
 
 	bev = (sync_barrierev_t *)event;
-	CHECK(manager_get_ldap_instance(bev->dbname, &inst));
 	log_debug(1, "sync_barrier_wait(): finish reached");
 	LOCK(&bev->sctx->mutex);
 	switch (bev->sctx->state) {
@@ -152,9 +149,8 @@ finish(isc_task_t *task, isc_event_t *event) {
 	BROADCAST(&bev->sctx->cond);
 	UNLOCK(&bev->sctx->mutex);
 	if (new_state == sync_finished)
-		activate_zones(task, inst);
+		activate_zones(task, bev->inst);
 
-cleanup:
 	if (result != ISC_R_SUCCESS)
 		log_error_r("syncrepl finish() failed");
 	isc_event_free(&event);
@@ -162,12 +158,12 @@ finish(isc_task_t *task, isc_event_t *event) {
 }
 
 static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
-sync_finishev_create(sync_ctx_t *sctx, const char *inst_name,
+sync_finishev_create(sync_ctx_t *sctx, ldap_instance_t *inst,
 		      sync_barrierev_t **evp) {
 	sync_barrierev_t *ev = NULL;
 
 	REQUIRE(sctx != NULL);
-	REQUIRE(inst_name != NULL);
+	REQUIRE(inst != NULL);
 	REQUIRE(evp != NULL && *evp == NULL);
 
 	ev = (sync_barrierev_t *)isc_event_allocate(sctx->mctx,
@@ -177,7 +173,7 @@ sync_finishev_create(sync_ctx_t *sctx, const char *inst_name,
 	if (ev == NULL)
 		return ISC_R_NOMEMORY;
 
-	ev->dbname = inst_name;
+	ev->inst = inst;
 	ev->sctx = sctx;
 	*evp = ev;
 
@@ -203,7 +199,6 @@ sync_finishev_create(sync_ctx_t *sctx, const char *inst_name,
 void
 barrier_decrement(isc_task_t *task, isc_event_t *event) {
 	isc_result_t result = ISC_R_SUCCESS;
-	ldap_instance_t *inst = NULL;
 	sync_barrierev_t *bev = NULL;
 	sync_barrierev_t *fev = NULL;
 	isc_event_t *ev = NULL;
@@ -214,13 +209,12 @@ barrier_decrement(isc_task_t *task, isc_event_t *event) {
 	REQUIRE(event != NULL);
 
 	bev = (sync_barrierev_t *)event;
-	CHECK(manager_get_ldap_instance(bev->dbname, &inst));
 	isc_refcount_decrement(&bev->sctx->task_cnt, &cnt);
 	if (cnt == 0) {
 		log_debug(1, "sync_barrier_wait(): barrier reached");
 		LOCK(&bev->sctx->mutex);
 		locked = ISC_TRUE;
-		CHECK(sync_finishev_create(bev->sctx, bev->dbname, &fev));
+		CHECK(sync_finishev_create(bev->sctx, bev->inst, &fev));
 		ev = (isc_event_t *)fev;
 		isc_task_send(ldap_instance_gettask(bev->sctx->inst), &ev);
 	}
@@ -235,12 +229,12 @@ barrier_decrement(isc_task_t *task, isc_event_t *event) {
 }
 
 static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
-sync_barrierev_create(sync_ctx_t *sctx, const char *inst_name,
+sync_barrierev_create(sync_ctx_t *sctx, ldap_instance_t *inst,
 		      sync_barrierev_t **evp) {
 	sync_barrierev_t *ev = NULL;
 
 	REQUIRE(sctx != NULL);
-	REQUIRE(inst_name != NULL);
+	REQUIRE(inst != NULL);
 	REQUIRE(evp != NULL && *evp == NULL);
 
 	ev = (sync_barrierev_t *)isc_event_allocate(sctx->mctx,
@@ -250,7 +244,7 @@ sync_barrierev_create(sync_ctx_t *sctx, const char *inst_name,
 	if (ev == NULL)
 		return ISC_R_NOMEMORY;
 
-	ev->dbname = inst_name;
+	ev->inst = inst;
 	ev->sctx = sctx;
 	*evp = ev;
 
@@ -488,7 +482,7 @@ sync_task_add(sync_ctx_t *sctx, isc_task_t *task) {
  *       enqueued before sync_barrier_wait() call.
  */
 isc_result_t
-sync_barrier_wait(sync_ctx_t *sctx, const char *inst_name) {
+sync_barrier_wait(sync_ctx_t *sctx, ldap_instance_t *inst) {
 	isc_result_t result;
 	isc_event_t *ev = NULL;
 	sync_barrierev_t *bev = NULL;
@@ -524,7 +518,7 @@ sync_barrier_wait(sync_ctx_t *sctx, const char *inst_name) {
 	     taskel != NULL;
 	     taskel = next_taskel) {
 		bev = NULL;
-		CHECK(sync_barrierev_create(sctx, inst_name, &bev));
+		CHECK(sync_barrierev_create(sctx, inst, &bev));
 		next_taskel = NEXT(taskel, link);
 		UNLINK(sctx->tasks, taskel, link);
 		ev = (isc_event_t *)bev;
diff --git a/src/syncrepl.h b/src/syncrepl.h
index ba3070a..14684ea 100644
--- a/src/syncrepl.h
+++ b/src/syncrepl.h
@@ -49,7 +49,7 @@ isc_result_t
 sync_task_add(sync_ctx_t *sctx, isc_task_t *task) ATTR_NONNULLS ATTR_CHECKRESULT;
 
 isc_result_t
-sync_barrier_wait(sync_ctx_t *sctx, const char *inst_name) ATTR_NONNULLS ATTR_CHECKRESULT;
+sync_barrier_wait(sync_ctx_t *sctx, ldap_instance_t *inst) ATTR_NONNULLS ATTR_CHECKRESULT;
 
 isc_result_t
 sync_concurr_limit_wait(sync_ctx_t *sctx) ATTR_NONNULLS ATTR_CHECKRESULT;
diff --git a/src/types.h b/src/types.h
index 57d5579..25ef3b9 100644
--- a/src/types.h
+++ b/src/types.h
@@ -43,7 +43,7 @@ typedef struct ldap_syncreplevent ldap_syncreplevent_t;
 struct ldap_syncreplevent {
 	ISC_EVENT_COMMON(ldap_syncreplevent_t);
 	isc_mem_t *mctx;
-	char *dbname;
+	ldap_instance_t	*inst;
 	char *prevdn;
 	int chgtype;
 	ldap_entry_t *entry;
diff --git a/src/zone_manager.c b/src/zone_manager.c
deleted file mode 100644
index 85e19fb..0000000
--- a/src/zone_manager.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2009-2014  bind-dyndb-ldap authors; see COPYING for license
- */
-
-#include <isc/mem.h>
-#include <isc/once.h>
-#include <isc/result.h>
-#include <isc/task.h>
-#include <isc/timer.h>
-#include <isc/boolean.h>
-#include <isc/util.h>
-
-#include <dns/dynamic_db.h>
-#include <dns/view.h>
-#include <dns/zone.h>
-
-#include <string.h>
-#include <unistd.h>
-
-#include "config.h"
-
-#include "bindcfg.h"
-#include "ldap_convert.h"
-#include "ldap_helper.h"
-#include "log.h"
-#include "settings.h"
-#include "util.h"
-#include "zone_manager.h"
-
-struct db_instance {
-	isc_mem_t		*mctx;
-	char			*name;
-	ldap_instance_t		*ldap_inst;
-	isc_timer_t		*timer;
-	LINK(db_instance_t)	link;
-};
-
-static isc_once_t initialize_once = ISC_ONCE_INIT;
-static isc_mutex_t instance_list_lock;
-static LIST(db_instance_t) instance_list;
-
-static void initialize_manager(void);
-static void destroy_db_instance(db_instance_t **db_instp) ATTR_NONNULLS;
-static isc_result_t find_db_instance(const char *name, db_instance_t **instance) ATTR_NONNULLS ATTR_CHECKRESULT;
-
-
-static void
-initialize_manager(void)
-{
-	INIT_LIST(instance_list);
-	isc_mutex_init(&instance_list_lock);
-	log_info("bind-dyndb-ldap version " VERSION
-		 " compiled at " __TIME__ " " __DATE__
-		 ", compiler " __VERSION__);
-	cfg_init_types();
-}
-
-void
-destroy_manager(void)
-{
-	db_instance_t *db_inst;
-	db_instance_t *next;
-
-	RUNTIME_CHECK(isc_once_do(&initialize_once, initialize_manager)
-		      == ISC_R_SUCCESS);
-
-	LOCK(&instance_list_lock);
-	db_inst = HEAD(instance_list);
-	while (db_inst != NULL) {
-		next = NEXT(db_inst, link);
-		UNLINK(instance_list, db_inst, link);
-		destroy_db_instance(&db_inst);
-		db_inst = next;
-	}
-	UNLOCK(&instance_list_lock);
-}
-
-static void ATTR_NONNULLS
-destroy_db_instance(db_instance_t **db_instp)
-{
-	db_instance_t *db_inst;
-
-	REQUIRE(db_instp != NULL && *db_instp != NULL);
-
-	db_inst = *db_instp;
-
-	if (db_inst->timer != NULL)
-		isc_timer_detach(&db_inst->timer);
-	if (db_inst->ldap_inst != NULL)
-		destroy_ldap_instance(&db_inst->ldap_inst);
-	if (db_inst->name != NULL)
-		isc_mem_free(db_inst->mctx, db_inst->name);
-
-	MEM_PUT_AND_DETACH(db_inst);
-
-	*db_instp = NULL;
-}
-
-isc_result_t
-manager_create_db_instance(isc_mem_t *mctx, const char *name,
-			   const char * const *argv,
-			   dns_dyndb_arguments_t *dyndb_args)
-{
-	isc_result_t result;
-	db_instance_t *db_inst = NULL;
-	isc_task_t *task;
-	settings_set_t *local_settings = NULL;
-
-	REQUIRE(name != NULL);
-	REQUIRE(dyndb_args != NULL);
-
-	RUNTIME_CHECK(isc_once_do(&initialize_once, initialize_manager)
-		      == ISC_R_SUCCESS);
-
-	result = find_db_instance(name, &db_inst);
-	if (result == ISC_R_SUCCESS) {
-		db_inst = NULL;
-		log_error("LDAP instance '%s' already exists", name);
-		CLEANUP_WITH(ISC_R_EXISTS);
-	}
-
-	CHECKED_MEM_GET_PTR(mctx, db_inst);
-	ZERO_PTR(db_inst);
-
-	isc_mem_attach(mctx, &db_inst->mctx);
-	CHECKED_MEM_STRDUP(mctx, name, db_inst->name);
-	task = dns_dyndb_get_task(dyndb_args);
-	CHECK(new_ldap_instance(mctx, db_inst->name, argv, dyndb_args, task,
-				&db_inst->ldap_inst));
-
-	local_settings = ldap_instance_getsettings_local(db_inst->ldap_inst);
-	CHECK(setting_get_bool("verbose_checks", local_settings, &verbose_checks));
-
-	/* instance must be in list while calling refresh_zones_from_ldap() */
-	LOCK(&instance_list_lock);
-	APPEND(instance_list, db_inst, link);
-	UNLOCK(&instance_list_lock);
-
-	return ISC_R_SUCCESS;
-
-cleanup:
-	if (db_inst != NULL)
-		destroy_db_instance(&db_inst);
-
-	return result;
-}
-
-isc_result_t
-manager_get_ldap_instance(const char *name, ldap_instance_t **ldap_inst)
-{
-	isc_result_t result;
-	db_instance_t *db_inst;
-
-	REQUIRE(name != NULL);
-	REQUIRE(ldap_inst != NULL);
-
-	RUNTIME_CHECK(isc_once_do(&initialize_once, initialize_manager)
-		      == ISC_R_SUCCESS);
-	db_inst = NULL;
-	CHECK(find_db_instance(name, &db_inst));
-
-	*ldap_inst = db_inst->ldap_inst;
-
-cleanup:
-	return result;
-}
-
-static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
-find_db_instance(const char *name, db_instance_t **instance)
-{
-	db_instance_t *iterator;
-
-	REQUIRE(name != NULL);
-	REQUIRE(instance != NULL && *instance == NULL);
-
-	LOCK(&instance_list_lock);
-	iterator = HEAD(instance_list);
-	while (iterator != NULL) {
-		if (strcmp(name, iterator->name) == 0)
-			break;
-		iterator = NEXT(iterator, link);
-	}
-	UNLOCK(&instance_list_lock);
-
-	if (iterator != NULL) {
-		*instance = iterator;
-		return ISC_R_SUCCESS;
-	}
-
-	return ISC_R_NOTFOUND;
-}
-
-isc_result_t
-manager_get_db_timer(const char *name, isc_timer_t **timer) {
-	isc_result_t result;
-	db_instance_t *db_inst = NULL;
-
-	REQUIRE(name != NULL);
-
-	result = find_db_instance(name, &db_inst);
-	if (result == ISC_R_SUCCESS)
-		*timer = db_inst->timer;
-
-	return result;
-}
diff --git a/src/zone_manager.h b/src/zone_manager.h
deleted file mode 100644
index 1e06365..0000000
--- a/src/zone_manager.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2009-2014  bind-dyndb-ldap authors; see COPYING for license
- */
-
-#ifndef _LD_ZONE_MANAGER_H_
-#define _LD_ZONE_MANAGER_H_
-
-#include <dns/types.h>
-
-#include "types.h"
-
-typedef struct db_instance db_instance_t;
-
-void destroy_manager(void);
-
-isc_result_t
-manager_create_db_instance(isc_mem_t *mctx, const char *name,
-			   const char * const *argv,
-			   dns_dyndb_arguments_t *dyndb_args) ATTR_NONNULLS ATTR_CHECKRESULT;
-
-isc_result_t
-manager_get_ldap_instance(const char *name,
-			  ldap_instance_t **ldap_inst) ATTR_NONNULLS ATTR_CHECKRESULT;
-
-isc_result_t
-manager_get_db_timer(const char *name,
-			  isc_timer_t **timer) ATTR_NONNULLS ATTR_CHECKRESULT;
-
-#endif /* !_LD_ZONE_MANAGER_H_ */
diff --git a/src/zone_register.c b/src/zone_register.c
index bde4a7c..d8525e9 100644
--- a/src/zone_register.c
+++ b/src/zone_register.c
@@ -260,15 +260,15 @@ zr_get_zone_path(isc_mem_t *mctx, settings_set_t *settings,
 static isc_result_t ATTR_NONNULL(1,2,4,5,6,8)
 create_zone_info(isc_mem_t * const mctx, dns_zone_t * const raw,
 		dns_zone_t * const secure, const char * const dn,
-		 settings_set_t *global_settings, const char *db_name,
+		 settings_set_t *global_settings, ldap_instance_t *inst,
 		 dns_db_t * const ldapdb, 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(inst != NULL);
 	REQUIRE(raw != NULL);
 	REQUIRE(dn != NULL);
 	REQUIRE(zinfop != NULL && *zinfop == NULL);
@@ -294,11 +294,9 @@ create_zone_info(isc_mem_t * const mctx, dns_zone_t * const raw,
 	CHECK(fs_dirs_create(str_buf(zone_dir)));
 
 	if (ldapdb == NULL) { /* create new empty database */
-		DE_CONST(db_name, argv[0]);
 		CHECK(ldapdb_create(mctx, dns_zone_getorigin(raw),
 				    LDAP_DB_TYPE, LDAP_DB_RDATACLASS,
-				    sizeof(argv)/sizeof(argv[0]),
-				    argv, NULL, &zinfo->ldapdb));
+				    inst, &zinfo->ldapdb));
 	} else { /* re-use existing database */
 		dns_db_attach(ldapdb, &zinfo->ldapdb);
 	}
@@ -396,8 +394,7 @@ zr_add_zone(zone_register_t * const zr, dns_db_t * const ldapdb,
 	}
 
 	CHECK(create_zone_info(zr->mctx, raw, secure, dn, zr->global_settings,
-			       ldap_instance_getdbname(zr->ldap_inst), ldapdb,
-			       &new_zinfo));
+			       zr->ldap_inst, ldapdb, &new_zinfo));
 	CHECK(dns_rbt_addname(zr->rbt, name, new_zinfo));
 
 cleanup:

From 9b8f146899037e758b1af656d1d830f15a63bae1 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Thu, 18 Aug 2016 13:29:55 +0200
Subject: [PATCH 4/9] BIND 9.11: use new public header isc/errno.h instead of
 private isc/errno2result.h

---
 configure.ac | 12 ++++++------
 src/fs.c     |  6 +++---
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/configure.ac b/configure.ac
index 0311560..a246b4f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -105,18 +105,18 @@ int main(void) {
 [AC_MSG_ERROR([Cross compiling is not supported.])]
 )
 
-dnl isc__errno2result() is typically not present in standard header files
-AC_MSG_CHECKING([isc__errno2result availability in header files])
+dnl isc_errno_toresult() was not available in older header files
+AC_MSG_CHECKING([isc_errno_toresult availability])
 AC_TRY_RUN([
-#include <isc/errno2result.h>
+#include <isc/errno.h>
 int main(void) {
-	isc__errno2result(0);
+	isc_errno_toresult(0);
 	return 0;
 }],
 [AC_MSG_RESULT([yes])],
 [AC_MSG_ERROR([
- Can't find isc__errno2result() or header isc/errno2result.h:
- Please install bind-lite-devel package or similar.])],
+ Can't find isc_errno_toresult() or header isc/errno.h:
+ Please install bind-devel package or similar.])],
 [AC_MSG_ERROR([Cross compiling is not supported.])]
 )
 
diff --git a/src/fs.c b/src/fs.c
index 09b71d7..61c46b5 100644
--- a/src/fs.c
+++ b/src/fs.c
@@ -10,7 +10,7 @@
 
 #include <isc/dir.h>
 #include <isc/file.h>
-#include <isc/errno2result.h>
+#include <isc/errno.h>
 #include <isc/result.h>
 #include <isc/string.h>
 #include <isc/util.h>
@@ -37,7 +37,7 @@ fs_dir_create(const char *dir_name)
 	if (ret == 0)
 		result = ISC_R_SUCCESS;
 	else
-		result = isc__errno2result(errno);
+		result = isc_errno_toresult(errno);
 
 	if (result != ISC_R_SUCCESS && result != ISC_R_FILEEXISTS) {
 		log_error_r("unable to create directory '%s', working directory "
@@ -50,7 +50,7 @@ fs_dir_create(const char *dir_name)
 		 * solely for this purpose. */
 		ret = chmod(dir_name, dir_mode);
 		if (ret != 0) {
-			result = isc__errno2result(errno);
+			result = isc_errno_toresult(errno);
 			log_error_r("unable to chmod directory '%s', "
 				    "working directory is '%s'",
 				    dir_name, dir_curr);

From 6eb624a24f4445084a43588ea8b404014d7b51d7 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Fri, 19 Aug 2016 13:53:22 +0200
Subject: [PATCH 5/9] Fix error handling in syncrepl_update() to avoid hung
 mctx.

---
 src/ldap_helper.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 58b1d7b..a03e140 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -4051,7 +4051,6 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t **entryp, int chgtype)
 	dns_name_t *zone_name = NULL;
 	dns_zone_t *zone_ptr = NULL;
 	char *dn = NULL;
-	isc_mem_t *mctx = NULL;
 	isc_taskaction_t action = NULL;
 	isc_task_t *task = NULL;
 	isc_boolean_t synchronous;
@@ -4064,8 +4063,6 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t **entryp, int chgtype)
 		  SYNCREPL_ADD(chgtype), SYNCREPL_DEL(chgtype),
 		  SYNCREPL_MOD(chgtype));
 
-	isc_mem_attach(inst->mctx, &mctx);
-
 	if (entry->class & LDAP_ENTRYCLASS_MASTER)
 		zone_name = &entry->fqdn;
 	else
@@ -4121,7 +4118,8 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t **entryp, int chgtype)
 		goto cleanup;
 	}
 
-	pevent->mctx = mctx;
+	pevent->mctx = NULL;
+	isc_mem_attach(inst->mctx, &pevent->mctx);
 	pevent->inst = inst;
 	pevent->prevdn = NULL;
 	pevent->chgtype = chgtype;
@@ -4141,8 +4139,8 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t **entryp, int chgtype)
 	if (pevent != NULL) {
 		/* Event was not sent */
 		sync_concurr_limit_signal(inst->sctx);
-		if (mctx != NULL)
-			isc_mem_detach(&mctx);
+		if (pevent->mctx != NULL)
+			isc_mem_detach(&pevent->mctx);
 		ldap_entry_destroy(entryp);
 		if (task != NULL)
 			isc_task_detach(&task);

From 09091baf598a139594384729ee668045300ebad7 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Fri, 19 Aug 2016 14:10:24 +0200
Subject: [PATCH 6/9] Remove obsolete options: cache_ttl, psearch,
 serial_autoincrement, zone_refresh.

---
 src/ldap_helper.c | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index a03e140..3e5c574 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -200,7 +200,6 @@ static const setting_t settings_local_default[] = {
 	{ "connections",		no_default_uint		},
 	{ "reconnect_interval",		no_default_uint		},
 	{ "timeout",			no_default_uint		},
-	{ "cache_ttl",			no_default_string	}, /* No longer supported */
 	{ "base",			no_default_string	},
 	{ "auth_method",		no_default_string	},
 	{ "auth_method_enum",		no_default_uint		},
@@ -214,12 +213,9 @@ static const setting_t settings_local_default[] = {
 	{ "sasl_password",		no_default_string	},
 	{ "krb5_keytab",		no_default_string	},
 	{ "fake_mname",			no_default_string	},
-	{ "zone_refresh",		no_default_string	}, /* No longer supported */
-	{ "psearch",			no_default_string	}, /* No longer supported */
 	{ "ldap_hostname",		no_default_string	},
 	{ "sync_ptr",			no_default_boolean	},
 	{ "dyn_update",			no_default_boolean	},
-	{ "serial_autoincrement",	no_default_string	}, /* No longer supported */
 	{ "verbose_checks",		no_default_boolean	},
 	{ "directory",			no_default_string	},
 	{ "nsec3param",			default_string("0 0 0 00")	}, /* NSEC only */
@@ -345,14 +341,6 @@ validate_local_instance_settings(ldap_instance_t *inst, settings_set_t *set) {
 	const char *dir_name = NULL;
 	isc_boolean_t dir_default;
 	ld_string_t *buff = NULL;
-
-	/* handle cache_ttl, psearch, serial_autoincrement, and zone_refresh
-	 * in special way */
-	const char *obsolete_value = NULL;
-	char *obsolete_options[] = {"cache_ttl", "psearch",
-				    "serial_autoincrement", "zone_refresh",
-				    NULL};
-
 	char print_buff[PRINT_BUFF_SIZE];
 	const char *auth_method_str = NULL;
 	ldap_auth_t auth_method_enum = AUTH_INVALID;
@@ -479,12 +467,6 @@ validate_local_instance_settings(ldap_instance_t *inst, settings_set_t *set) {
 			 "are untested; expect problems");
 	}
 
-	for (char **option = obsolete_options; *option != NULL; option++) {
-		CHECK(setting_get_str(*option, set, &obsolete_value));
-		if (memcmp("", obsolete_value, 1) != 0)
-			log_error("option '%s' is not supported, ignoring", *option);
-	}
-
 	if (settings_set_isfilled(set) != ISC_TRUE)
 		result = ISC_R_FAILURE;
 

From ab05d28ae30bbef66bbc1ad194e6c0183b10fd18 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Thu, 1 Sep 2016 15:19:19 +0200
Subject: [PATCH 7/9] Use ISC configuration parser for dyndb section.

This plugin now uses the same configuration conventions and error
reporting facilities and native BIND.

Configuration format is:
dyndb <name> <library> {
        option1 "string value";
        option2 integer-value;
};
---
 README            |  25 ++++----
 src/ldap_driver.c |  18 +-----
 src/ldap_helper.c |  55 ++++++++++++++++--
 src/ldap_helper.h |   7 ++-
 src/settings.c    | 168 ++++++++++++++++++++++++++++++++++++++----------------
 src/settings.h    |  11 ++--
 6 files changed, 199 insertions(+), 85 deletions(-)

diff --git a/README b/README
index e90fc26..5f02f99 100644
--- a/README
+++ b/README
@@ -313,7 +313,12 @@ and is used for logging purposes and for naming working directories.
 Library path must point to a shared object file that will be opened and loaded.
 
 Name and library path have to be followed by set of options enclosed between
-curly brackets.
+curly brackets. Example:
+dyndb "example-ldap" "/usr/lib64/bind/ldap.so" {
+	uri "ldap://ldap.example.com";;
+	base "cn=dns, dc=example,dc=com";
+	auth_method "none";
+};
 
 5.1 Configuration options
 -------------------------
@@ -325,7 +330,7 @@ uri
 	The Uniform Resource Identifier pointing to the LDAP server we
 	wish to connect to. This string is directly passed to the
 	ldap_initialize(3) function. This option is mandatory.
-	Example: ldap://ldap.example.com
+	Example: "ldap://ldap.example.com";
 
 connections (default 2)
 	Number of connections the LDAP driver should try to establish to
@@ -336,7 +341,8 @@ connections (default 2)
 
 base
 	This is the search base that will be used by the LDAP back-end
-	to search for DNS zones. It is mandatory.
+	to search for DNS zones. This option is mandatory.
+	Example: "cn=dns, dc=example,dc=com";
 
 auth_method (default "none")
 	The method used to authenticate to the LDAP server. Currently
@@ -371,7 +377,7 @@ sasl_realm
 krb5_keytab
 	Path to the kerberos keytab containing service credentials to be used
 	for SASL authentication. Append the "FILE:" prefix to the file path.
-	(FILE:/etc/named.keytab, for example)
+	Example: "FILE:/etc/named.keytab"
 
 krb5_principal
 	Kerberos principal of the service, used for SASL authentication.
@@ -398,7 +404,7 @@ ldap_hostname (default "")
 
 5.1.2 Special DNS features
 --------------------------
-fake_mname (default "")
+fake_mname
 	Ignore value of the idnsSOAmName (primary master DNS name) attribute
 	and use this value instead. This allows multiple BIND processes to share
 	one LDAP database and every BIND reports itself as a primary master in
@@ -443,11 +449,10 @@ options {
 	directory "/var/named/";
 };
 
-dynamic-db "my_db_name" {
-	library "ldap.so";
-	arg "uri ldap://ldap.example.com";;
-	arg "base cn=dns, dc=example, dc=com";
-	arg "auth_method none";
+dyndb "my_db_name" "/usr/lib64/bind/ldap.so" {
+	uri "ldap://ldap.example.com";;
+	base "cn=dns, dc=example,dc=com";
+	auth_method "none";
 };
 
 With this configuration, the LDAP back-end will try to connect to server
diff --git a/src/ldap_driver.c b/src/ldap_driver.c
index 7cf877b..b1b7336 100644
--- a/src/ldap_driver.c
+++ b/src/ldap_driver.c
@@ -1042,9 +1042,6 @@ dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters,
 	   const char *file, unsigned long line, const dns_dyndbctx_t *dctx,
 	   void **instp)
 {
-	unsigned int argc;
-	char **argv = NULL;
-	char *tmps = NULL;
 	ldap_instance_t *inst = NULL;
 	isc_result_t result;
 	static isc_once_t library_init_once = ISC_ONCE_INIT;
@@ -1072,23 +1069,12 @@ dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters,
 
 	log_debug(2, "registering dynamic ldap driver for %s.", name);
 
-	tmps = isc_mem_strdup(mctx, parameters);
-	if (tmps == NULL) {
-		result = ISC_R_NOMEMORY;
-		goto cleanup;
-	}
-	CHECK(isc_commandline_strtoargv(mctx, tmps, &argc, &argv, 0));
-
 	/* Finally, create the instance. */
-	CHECK(new_ldap_instance(mctx, name, argc, argv, dctx, &inst));
+	CHECK(new_ldap_instance(mctx, name, parameters, file, line, dctx,
+				&inst));
 	*instp = inst;
 
 cleanup:
-	if (tmps != NULL)
-		isc_mem_free(mctx, tmps);
-	if (argv != NULL)
-		isc_mem_put(mctx, argv, argc * sizeof(*argv));
-
 	return result;
 }
 
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 3e5c574..a11751d 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -42,6 +42,7 @@
 #include <isc/string.h>
 
 #include <isccfg/cfg.h>
+#include <isccfg/grammar.h>
 
 #include <alloca.h>
 #define LDAP_DEPRECATED 1
@@ -228,6 +229,50 @@ static const setting_t settings_local_default[] = {
 	end_of_settings
 };
 
+/**
+ * This is list of values configurable in dyndb section of named.conf.
+ * Names and data types must match settings_local_default.
+ * Settings which are not user-configurable must be omitted from this structure.
+ */
+static cfg_clausedef_t
+dyndb_ldap_conf_clauses[] = {
+	{ "auth_method",        &cfg_type_qstring,	0	},
+	{ "base",               &cfg_type_qstring,	0	},
+	{ "bind_dn",            &cfg_type_qstring,	0	},
+	{ "connections",        &cfg_type_uint32,	0	},
+	{ "directory",          &cfg_type_qstring,	0	},
+	{ "dyn_update",         &cfg_type_boolean,	0	},
+	{ "fake_mname",         &cfg_type_qstring,	0	},
+	{ "krb5_keytab",        &cfg_type_qstring,	0	},
+	{ "krb5_principal",     &cfg_type_qstring,	0	},
+	{ "ldap_hostname",      &cfg_type_qstring,	0	},
+	{ "password",           &cfg_type_sstring,	0	},
+	{ "reconnect_interval", &cfg_type_uint32,	0	},
+	{ "sasl_auth_name",     &cfg_type_qstring,	0	},
+	{ "sasl_mech",          &cfg_type_qstring,	0	},
+	{ "sasl_password",      &cfg_type_qstring,	0	},
+	{ "sasl_realm",         &cfg_type_qstring,	0	},
+	{ "sasl_user",          &cfg_type_qstring,	0	},
+	{ "server_id",          &cfg_type_qstring,	0	},
+	{ "sync_ptr",           &cfg_type_boolean,	0	},
+	{ "timeout",            &cfg_type_uint32,	0	},
+	{ "uri",                &cfg_type_qstring,	0	},
+	{ "verbose_checks",     &cfg_type_boolean,	0	},
+	{ NULL,			NULL,			0	}
+};
+
+static cfg_clausedef_t *
+dyndb_ldap_clausulesets[] = {
+	dyndb_ldap_conf_clauses,
+	NULL
+};
+
+/** Entry point for configuration parser used on dyndb section of named.conf. */
+static cfg_type_t cfg_type_dyndb_conf = {
+	"dyndb_ldap_conf", cfg_parse_mapbody, cfg_print_mapbody,
+	cfg_doc_mapbody, &cfg_rep_map, dyndb_ldap_clausulesets
+};
+
 /** Global settings from idnsConfig object. */
 static setting_t settings_global_default[] = {
 	{ "dyn_update",		no_default_boolean					},
@@ -481,9 +526,9 @@ validate_local_instance_settings(ldap_instance_t *inst, settings_set_t *set) {
 
 #define PRINT_BUFF_SIZE 255
 isc_result_t
-new_ldap_instance(isc_mem_t *mctx, const char *db_name, unsigned int argc,
-		  char **argv, const dns_dyndbctx_t *dctx,
-		  ldap_instance_t **ldap_instp)
+new_ldap_instance(isc_mem_t *mctx, const char *db_name, const char *parameters,
+		  const char *file, unsigned long line,
+		  const dns_dyndbctx_t *dctx, ldap_instance_t **ldap_instp)
 {
 	isc_result_t result;
 	ldap_instance_t *ldap_inst;
@@ -523,7 +568,9 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name, unsigned int argc,
 	      sizeof(settings_global_default), settings_name,
 	      ldap_inst->local_settings, &ldap_inst->global_settings));
 
-	CHECK(settings_set_fill(ldap_inst->local_settings, argc, argv));
+	CHECK(setting_set_parse_conf(mctx, ldap_inst->db_name,
+				     &cfg_type_dyndb_conf, parameters, file,
+				     line, ldap_inst->local_settings));
 
 	/* copy global forwarders setting for configuration roll back in
 	 * configure_zone_forwarders() */
diff --git a/src/ldap_helper.h b/src/ldap_helper.h
index 773091c..6cfece5 100644
--- a/src/ldap_helper.h
+++ b/src/ldap_helper.h
@@ -9,6 +9,7 @@
 
 #include <isc/eventclass.h>
 #include <isc/util.h>
+#include <isccfg/cfg.h>
 
 #include <ldap.h>
 
@@ -40,9 +41,9 @@ void free_rdatalist(isc_mem_t *mctx, dns_rdatalist_t *rdlist) ATTR_NONNULLS;
  */
 
 isc_result_t
-new_ldap_instance(isc_mem_t *mctx, const char *db_name, unsigned int argc,
-		  char **argv, const dns_dyndbctx_t *dctx,
-		  ldap_instance_t **ldap_instp) ATTR_NONNULLS;
+new_ldap_instance(isc_mem_t *mctx, const char *db_name, const char *parameters,
+		  const char *file, unsigned long line,
+		  const dns_dyndbctx_t *dctx, ldap_instance_t **ldap_instp) ATTR_NONNULLS;
 void destroy_ldap_instance(ldap_instance_t **ldap_inst) ATTR_NONNULLS;
 
 isc_result_t
diff --git a/src/settings.c b/src/settings.c
index bdcfd67..20cc1aa 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -9,6 +9,7 @@
 #include <isc/string.h>
 #include <isc/int.h>
 #include <isc/parseint.h>
+
 #include <dns/name.h>
 
 #include <ctype.h>
@@ -553,66 +554,72 @@ settings_set_free(settings_set_t **set) {
 }
 
 /**
- * Set all values specified by vector of strings to setting set. Setting name
- * is separated from it's argument with one or more characters defined by
- * @link SETTING_NAME_SEPARATORS@endlink.
- *
- * @retval ISC_R_SUCCESS All strings in argument vector were processed and set.
- * @retval Others        Memory or parsing errors.
- *
- * @warning One string in argument vector is limited to
- * @link SETTING_LINE_MAXLENGTH@endlink.
- *
- * @note
- * @code{.txt}
- * Calling settings_set_fill() with argument array
+ * Append textlen bytes from text to isc_buffer pointed to by closure.
  *
- * {"setting1	value 1 ",
- *  "bind_dn cn=Directory manager" }
- *
- * will result in setting values to two separate settings:
+ * @pre closure is an initialized isc_buffer with autoreallocation enabled.
+ */
+static void
+cfg_printer(void *closure, const char *text, int textlen) {
+	isc_buffer_t *logbuffer = closure;
+
+	REQUIRE(logbuffer != NULL);
+	REQUIRE(logbuffer->autore == ISC_TRUE);
+
+	isc_buffer_putmem(logbuffer, (const unsigned char *)text, textlen);
+}
+
+/**
+ * Copy values from cfg map to set of settings.
+ * Only setting names specified in set of settings are copied.
  *
- * "setting1" = "value 1 "
- * "bind_dn"  = "cn=Directory manager"
+ * @param[in]  config
+ * @param[out] set
  *
- * Please note the positions of white spaces.
- * @endcode
+ * @retval ISC_R_SUCCESS Items listed in set of settings were copied from cfg map.
+ * @retval Others        Memory or parsing errors.
  */
-isc_result_t
-settings_set_fill(settings_set_t *set, unsigned int argc, char **argv)
+static isc_result_t
+settings_set_fill(const cfg_obj_t *config, settings_set_t *set)
 {
 	isc_result_t result;
-	unsigned int i;
-	const char *name;
-	char *value;
-
-	for (i = 0; i < argc; i++) {
-		char buff[SETTING_LINE_MAXLENGTH] = "";
-		CHECK(isc_string_copy(buff, SETTING_LINE_MAXLENGTH, argv[i]));
-		value = buff;
-		name = isc_string_separate(&value, SETTING_NAME_SEPARATORS);
-		if (name == NULL || value == NULL)
-			CLEANUP_WITH(ISC_R_UNEXPECTEDEND);
-		value += strspn(value, SETTING_NAME_SEPARATORS);
-		if (setting_find(name, set, ISC_FALSE, ISC_TRUE, NULL)
-		    != ISC_R_NOTFOUND) {
-			log_error("multiple definitions of setting '%s' in "
-				  "set of settings '%s'", name, set->name);
-			CLEANUP_WITH(ISC_R_EXISTS);
+	setting_t *setting;
+	isc_buffer_t *buf_value = NULL;
+	const cfg_obj_t *cfg_value;
+	const char *str_value;
+
+	REQUIRE(cfg_obj_ismap(config) == ISC_TRUE);
+
+	CHECK(isc_buffer_allocate(set->mctx, &buf_value, ISC_BUFFER_INCR));
+	isc_buffer_setautorealloc(buf_value, ISC_TRUE);
+
+	for (setting = set->first_setting;
+	     setting->name != NULL;
+	     setting++) {
+		cfg_value = NULL;
+		result = cfg_map_get(config, setting->name, &cfg_value);
+		if (result == ISC_R_NOTFOUND)
+			continue; /* setting not configured in map */
+		else if (result != ISC_R_SUCCESS)
+			goto cleanup;
+		if (cfg_obj_isstring(cfg_value)) {
+			/* this avoids additional quotes around the string */
+			str_value = cfg_obj_asstring(cfg_value);
+		} else {
+			cfg_printx(cfg_value, 0, cfg_printer, buf_value);
+			isc_buffer_putmem(buf_value, (unsigned char *)"\0", 1);
+			str_value = isc_buffer_base(buf_value);
 		}
-		result = setting_set(name, set, value);
+		result = set_value(set->mctx, set, setting, str_value);
 		if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE)
 			goto cleanup;
+		isc_buffer_clear(buf_value);
 	}
 
-	return ISC_R_SUCCESS;
-
 cleanup:
-	log_error_r("cannot parse settings from '%s': "
-		    "problematic configuration line:"
-		    "\n%s\n"
-		    "error code", set->name, argv[i]);
-	/* TODO: Free memory in case of error. */
+	if (result != ISC_R_SUCCESS)
+		log_error_r("cannot parse settings for '%s'", set->name);
+	if (buf_value != NULL)
+		isc_buffer_free(&buf_value);
 	return result;
 }
 
@@ -644,6 +651,71 @@ settings_set_isfilled(settings_set_t *set) {
 	return isfiled;
 }
 
+/**
+ * Parse string with dyndb configuration and fill in settings_set_t structure.
+ *
+ * @param[in]  name		name of dyndb instance
+ * @param[in]  cfg_type_conf	configuration grammar for ISC parser
+ * @param[in]  parameters	string with complete dyndb configuration
+ * @param[in]  file		name of configuration file
+ * @param[in]  line		line on which config starts
+ * @param[out] settings		set of settings filled with values from config
+ *
+ * @pre Names and data types of respective paremeters
+ * 	in cfg_type_conf and set of settings must match.
+ */
+isc_result_t
+setting_set_parse_conf(isc_mem_t *mctx, const char *name,
+		       cfg_type_t *cfg_type_conf, const char *parameters,
+		       const char *file, unsigned long line,
+		       settings_set_t *settings)
+{
+	isc_result_t result;
+	cfg_obj_t *config = NULL;
+	isc_buffer_t in_buf;
+	isc_buffer_t *log_buf = NULL;
+	cfg_parser_t *parser = NULL;
+	unsigned int len;
+
+	REQUIRE(parameters != NULL);
+
+	CHECK(isc_buffer_allocate(mctx, &log_buf, ISC_BUFFER_INCR));
+	isc_buffer_setautorealloc(log_buf, ISC_TRUE);
+
+	len = strlen(parameters);
+	isc_buffer_constinit(&in_buf, parameters, len);
+	isc_buffer_add(&in_buf, len);
+
+	CHECK(cfg_parser_create(mctx, dns_lctx, &parser));
+	result = cfg_parse_buffer2(parser, &in_buf, name, cfg_type_conf,
+				   &config);
+	if (result == ISC_R_SUCCESS) {
+		cfg_printx(config, CFG_PRINTER_XKEY, cfg_printer, log_buf);
+		cfg_obj_log(config, dns_lctx, ISC_LOG_DEBUG(10),
+			    "configuration for dyndb instance '%s' "
+			    "(starting in file %s on line %lu):\n"
+			    "%.*s",
+			    name, file, line, isc_buffer_usedlength(log_buf),
+			    (char *)isc_buffer_base(log_buf));
+	} else {
+		log_error("configuration for dyndb instance '%s' "
+			  "(starting in file %s on line %lu) is invalid",
+			  name, file, line);
+		goto cleanup;
+	}
+
+	CHECK(settings_set_fill(config, settings));
+
+cleanup:
+	if (log_buf != NULL)
+		isc_buffer_free(&log_buf);
+	if (config != NULL)
+		cfg_obj_destroy(parser, &config);
+	if (parser != NULL)
+		cfg_parser_destroy(&parser);
+	return result;
+}
+
 isc_result_t
 get_enum_description(const enum_txt_assoc_t *map, int value, const char **desc) {
 	const enum_txt_assoc_t *record;
diff --git a/src/settings.h b/src/settings.h
index b77fcf8..16a1e63 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -6,12 +6,13 @@
 #define _LD_SETTINGS_H_
 
 #include <isc/types.h>
+
+#include <isccfg/grammar.h>
+
 #include "types.h"
 #include "str.h"
 #include "ldap_entry.h"
 
-#define SETTING_LINE_MAXLENGTH 255
-#define SETTING_NAME_SEPARATORS " \t"
 #define SETTING_SET_NAME_LOCAL  "named.conf"
 #define SETTING_SET_NAME_SERVER "LDAP idnsServerConfig object"
 #define SETTING_SET_NAME_GLOBAL "LDAP idnsConfig object"
@@ -82,8 +83,10 @@ void
 settings_set_free(settings_set_t **set) ATTR_NONNULLS;
 
 isc_result_t
-settings_set_fill(settings_set_t *set, unsigned int argc, char **argv)
-		  ATTR_NONNULLS ATTR_CHECKRESULT;
+setting_set_parse_conf(isc_mem_t *mctx, const char *name,
+		       cfg_type_t *cfg_type_conf, const char *parameters,
+		       const char *file, unsigned long line,
+		       settings_set_t *settings) ATTR_NONNULLS ATTR_CHECKRESULT;
 
 isc_boolean_t
 settings_set_isfilled(settings_set_t *set) ATTR_NONNULLS ATTR_CHECKRESULT;

From 42c1897e600189b7efc6d51063a39984181767e7 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Thu, 1 Sep 2016 15:25:31 +0200
Subject: [PATCH 8/9] Print configuration grammar when an configuration error
 is detected.

---
 src/settings.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/settings.c b/src/settings.c
index 20cc1aa..37e6e5c 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -701,6 +701,10 @@ setting_set_parse_conf(isc_mem_t *mctx, const char *name,
 		log_error("configuration for dyndb instance '%s' "
 			  "(starting in file %s on line %lu) is invalid",
 			  name, file, line);
+		cfg_print_grammar(cfg_type_conf, cfg_printer, log_buf);
+		log_info("expected grammar:\n"
+			 "%.*s", isc_buffer_usedlength(log_buf),
+			 (char *)isc_buffer_base(log_buf));
 		goto cleanup;
 	}
 

From 574bb9744b0b65e35e2fb3e0af20163b45fe6b50 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20=C5=A0pa=C4=8Dek?= <pspa...@redhat.com>
Date: Thu, 1 Sep 2016 16:32:03 +0200
Subject: [PATCH 9/9] Create README.md

This is an attempt to markdown-ify README.
---
 README.md | 591 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 591 insertions(+)
 create mode 100644 README.md

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..de9cd1f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,591 @@
+1. Introduction
+===============
+The dynamic LDAP back-end is a plug-in for BIND that provides an LDAP
+database back-end capabilities. It requires dyndb interface which is present
+in BIND versions >= 9.11.0rc1.
+
+
+2. Features
+===========
+
+* support for dynamic updates
+* SASL authentication
+* SyncRepl (RFC 4533) for run-time synchronization with LDAP server
+* read-query performance nearly same as with plain BIND
+* AXFR and IXFR zone transfers are supported
+* DNSSEC in-line signing is supported, including dynamic updates
+
+
+3. Installation
+===============
+
+To install the LDAP back-end, extract the tarball and go to the unpacked
+directory. Then follow these steps:
+
+	$ ./configure --libdir=<libdir>
+	$ make
+
+Where `<libdir>` is a directory where your libdns is installed. This is
+typically going to be `/usr/lib` or `/usr/lib64` on 64 bit systems.
+
+If configure script complains that it `Can't obtain libdns version`,
+please verify you have installed bind development files (package bind9-dev
+or bind-devel) and you exported correct CPPFLAGS via
+
+	$ export CPPFLAGS=`isc-config.sh --cflags`
+
+Then, to install, run this as root:
+
+	$ make install
+
+This will install the file `ldap.so` into the `<libdir>/bind/` directory.
+
+Alternatively, the latest version can be obtained from Git repository.
+You can use following commands to prepare latest source tree for compilation:
+
+	$ git clone https://git.fedorahosted.org/git/bind-dyndb-ldap.git
+	$ cd bind-dyndb-ldap
+	$ autoreconf -fvi
+
+4. LDAP schema
+==============
+
+You can find the complete LDAP schema in the documentation directory. An
+example zone ldif is available in the doc directory.
+
+4.1 Master zone (idnsZone)
+--------------------------
+Object class `idnsZone` is equivalent to type `master` statement in `named.conf`.
+
+### Attributes
+* idnsAllowDynUpdate
+
+	Allow dynamic update of records in this zone. If attribute doesn't exist,
+	value `dyn_update` from plugin configuration will be used.
+
+* idnsAllowQuery
+
+	Specifies BIND9 zone ACL element as one string.
+
+	* Example 1: `idnsAllowQuery: 192.0.2.1;`
+	
+		In the first example above, only the client with 192.0.2.1
+		IP address is allowed to query records from the zone.
+
+	* Example 2: `idnsAllowQuery: !192.0.2.33; 192.0.2.0/24;`
+	
+		In the second example, queries from client 192.0.2.33
+		are refused but queries from all other clients in
+		the 192.0.2.0/24 network are allowed.
+
+	You can specify IPv4/IPv6 address, IPv4/IPv6 network address in CIDR
+	format, and `any` or `none` keywords. The `!` prefix (for example
+	`!192.0.2.33`) means negation of the ACL element.
+
+	If not set, then zone inherits global allow-query from named.conf.
+
+* idnsAllowTransfer
+
+	Uses same format as `idnsAllowQuery`. Allows zone transfers for matching
+	clients.
+
+	If not set then zone inherits global allow-transfer from named.conf.
+
+* idnsAllowSyncPTR
+
+	Allow synchronization of A/AAAA records in zone with PTR records in reverse
+	zone. Reverse zone must have Dynamic update allowed. 
+	(See `idnsAllowDynUpdate` attribute and `dyn_update` configuration parameter.)
+
+* idnsForwardPolicy (default `first`)
+
+	Specifies BIND9 zone forward policy. Proprietary value `none`
+	is equivalent to `forwarders {};` in BIND configuration,
+	i.e. effectively disables forwarding and ignores `idnsForwarders`
+	attribute.
+
+	Values `first` and `only` are relevant in conjunction with a valid
+	idnsForwarders attribute. Their meaning is same as in BIND9.
+
+* idnsForwarders
+
+	Defines multiple IP addresses to which recursive queries will be
+	forwarded. This is equivalent to `forwarders` statement in `master`
+	zone configuration.
+
+	I.e. local BIND replies authoritatively to queries when possible
+	(including authoritative NXDOMAIN answers) so forwarding affects only
+	queries made by BIND to answer recursive queries which cannot be
+	answered locally. Please see
+	https://lists.isc.org/pipermail/bind-users/2006-January/060810.html
+	https://lists.isc.org/pipermail/bind-users/2011-March/083244.html
+
+	It is multi-value attribute: Each IP address (and optional port) has to
+	be in own value. BIND9 syntax for `forwarders` is required.
+	Optional port can be specified by adding ` port <number>` after IP 
+	address. IPv4 and IPv6 addresses are supported.
+	Examples:
+	* `1.2.3.4`
+	* `1.2.3.4 port 553`
+	* `A::B`
+	* `A::B port 553`
+
+* idnsName
+
+	Absolute name of DNS zone. It is recommended to use names with trailing
+	period, e.g. `example.com.`
+
+* idnsSecInlineSigning (default `FALSE`)
+
+	DNSSEC in-line signing configuration. Value TRUE is equivalent to
+	following zone configuration in named.conf (default BIND values):
+
+		auto-dnssec maintain;
+		sig-validity-interval 2592000; # 30 days
+		# re-sign interval will be 648000 seconds = 7.5 days
+		sig-signing-signatures 10;
+		sig-signing-nodes 10;
+		sig-signing-type 65534;
+		update-check-ksk yes;
+		dnssec-loadkeys-interval 60;   # minutes
+		key-directory "<plugin-instance-dir>/<zone-name>/keys";
+
+	There is no way to change those values at this moment.
+
+* idnsSOAserial
+
+	SOA serial number. It is automatically incremented after each change
+	in LDAP. External changes done by other LDAP clients are detected via
+	RFC 4533 (so-called syncrepl).
+
+	If serial number is lower than current UNIX timestamp, then
+	it is set to the timestamp value. If SOA serial is greater or equal
+	to current timestamp, then the serial is incremented by one.
+	(This is equivalent to BIND option 'serial-update-method unix'.)
+
+	In multi-master LDAP environments it is recommended to make
+	idnsSOAserial attribute non-replicated (locally significant).
+	It is recommended not to use multiple masters for single slave zone
+	if SOA serial is locally significant because serial numbers between
+	masters	aren't synchronized. It will cause problems with zone
+	transfers from multiple masters to single slave.
+
+* idnsZoneActive
+
+	Boolean which speicifies if particular DNS zone should be visible
+	to clients or not. This attribute can be changed at run-time.
+
+	Inactive zones are loaded into memory in the same way as active zones.
+	The only difference is that inactive zones are not added to DNS view
+	used by bind-dyndb-ldap.
+
+	Zone will be re-added to DNS view if idnsActiveZone attribute is
+	changed to TRUE so the change should be almost immediate.
+
+	Usual zone maintenance (serial number maintenance, DNSSEC in-line
+	signing etc.) is done for all zones, no matter if the zone
+	is active or not. This allows us to maintain zone journal so IXFR
+	works correctly even after zone re-activation.
+
+* nSEC3PARAMRecord
+
+	NSEC3PARAM resource record definition according to RFC5155.
+	Zone without NSEC3PARAM RR will use NSEC by default.
+
+
+4.2 Forward zone (idnsForwardZone)
+----------------------------------
+Object class `idnsForwardZone` is equivalent to type `forward` statement
+in named.conf.
+
+### Attributes
+* idnsForwarders
+
+	Defines multiple IP addresses to which all queries for sub-tree of DNS
+	will be forwarded. This is equivalent to `forwarders` statement in
+	`forward` zone configuration.
+
+	It is multi-value attribute: Each IP address (and optional port) has to
+	be in own value. BIND9 syntax for `forwarders` is required.
+	Optional port can be specified by adding ` port <number>` after IP 
+	address. IPv4 and IPv6 addresses are supported.
+	Examples:
+	* `1.2.3.4`
+	* `1.2.3.4 port 553`
+	* `A::B`
+	* `A::B port 553`
+
+* idnsForwardPolicy (default `first`)
+
+	Specifies BIND9 zone forward policy. Proprietary value `none`
+	is equivalent to `forwarders {};` in BIND configuration,
+	i.e. effectively disables forwarding and ignores `idnsForwarders`
+	attribute.
+
+	Values `first` and `only` are relevant in conjunction with a valid
+	`idnsForwarders` attribute. Their meaning is same as in BIND9.
+
+* idnsName
+
+	Absolute name of DNS zone. It is recommended to use names with trailing
+	period, e.g. `example.com.`
+
+Forward zones may conflict with automatic empty zones (defined in RFC 6303)
+because empty zones are authoritative and thus have higher priority
+than forwarding.
+Bind-dyndb-ldap will automatically unload empty zones which are super/sub
+domains of a forward zones if the forwarding policy is `only`.
+A warning will be issued (and zone not unloaded) if the policy is `first`
+because this policy does not guarantee that queries will not leak to
+the public Internet.
+
+Unloaded empty zones will not be loaded back even if the forward zone is later
+deleted. The empty zones will be loaded on each BIND reload.
+
+
+4.3 Global configuration object (idnsConfigObject)
+--------------------------------------------------
+Object class idnsConfigObject provides global configuration common
+for all zones.
+
+### Attributes
+* idnsAllowSyncPTR
+
+	Semantics is equivalent to `sync_ptr` option described in plugin's
+	config and to `idnsAllowSyncPTR` attribute in `idnsZone`.
+
+* idnsForwarders
+* idnsForwardPolicy
+
+	Semantics is equivalent to `forward` statement in `named.conf`.
+	Syntax is the same as in forward zone, please see previous section.
+
+
+4.4 Per-server configuration object (idnsServerConfigObject)
+------------------------------------------------------------
+Object class idnsConfigObject provides global configuration common
+for all zones. A plugin instance will read configuration
+only from entries with matching idnsServerId.
+
+### Attributes
+* idnsServerId
+
+	Configuration identifier (arbitrary string).
+	A plugin instance will use only objects whose `idnsServerId` value
+	matches `server_id` value in plugin's config.
+
+* idnsForwarders
+* idnsForwardPolicy
+
+	Same meaning as in global configuration object (`idnsConfigObject`).
+
+* idnsSOAmName
+
+	Equivalent to `fake_mname` option in plugin's config.
+
+* idnsSubstitutionVariable
+
+	This attribute associates string value with user-defined name.
+	These named variables can be used later in record template processing.
+	Variable name is specified as LDAP sub-type. (The attribute cannot be
+	used without sub-type. Exactly one instance of each sub-type
+	is required.)
+	For further information please see
+	https://fedorahosted.org/bind-dyndb-ldap/wiki/Design/RecordGenerator
+
+	LIMITATION: Current plugin version supports only `ipalocation` variable
+
+
+4.5 Record template (idnsTemplateObject)
+----------------------------------------
+Object class idnsTemplateObject provides facility for dynamic resource record
+generation. The template entry must contain idnsTemplateAttribute with
+string template.
+
+Optionally the same entry can contain statically defined resource records
+in *Record attributes. All statically defined record values are ignored
+when template is present and substitution into template is successful.
+The substitution is successful only if all variables used
+by the template string are defined.
+
+### Attributes
+* idnsTemplateAttribute
+	String subtitution template. All occurrences of \{variable_name\}
+	are replaced with respective strings from plugin configuration.
+	Remaining parts of the original string are just copied into the output.
+
+	Double-escaped strings \\{ \\} do not trigger substitution.
+	Nested references will expand only innermost variable: \{\{var1\}\}
+	Non-matching parentheses and other garbage will be copied verbatim
+	without triggering an error.
+
+	Resulting resource record type is specified as LDAP sub-type.
+	(The attribute cannot be used without sub-type.
+	Exactly one instance of each sub-type is required.)
+
+	Example - LDIF snippet:
+	
+		idnsSubstitutionVariable;ipalocation: brno
+		idnsTemplateAttribute;CNAMERecord: server.\{substitutionvariable_ipalocation\}
+	will generate CNAME record: `server.brno`
+		
+	For further information please see
+	https://fedorahosted.org/bind-dyndb-ldap/wiki/Design/RecordGenerator
+
+
+5. Configuration
+================
+
+To configure dynamic loading of back-end, you must put a `dyndb`
+clause into your named.conf. The clause must then be followed by a
+string denoting the name of the instance and path to dyndb library.
+
+The name is not that much important, it is passed to the plug-in
+and is used for logging purposes and for naming working directories.
+
+Library path must point to a shared object file that will be opened and loaded.
+
+Name and library path have to be followed by set of options enclosed between
+curly brackets. Example:
+
+	dyndb "example-ldap" "/usr/lib64/bind/ldap.so" {
+		uri "ldap://ldap.example.com";;
+		base "cn=dns, dc=example,dc=com";
+		auth_method "none";
+	};
+
+5.1 Configuration options
+-------------------------
+List of configuration options follows:
+
+5.1.1 LDAP connection
+---------------------
+* uri
+
+	The Uniform Resource Identifier pointing to the LDAP server we
+	wish to connect to. This string is directly passed to the
+	ldap_initialize(3) function. This option is mandatory.
+	Example: "ldap://ldap.example.com";
+
+* connections (default 2)
+
+	Number of connections the LDAP driver should try to establish to
+	the LDAP server. It's best if this matches the number of threads
+	BIND creates, for performance reasons. However, your LDAP server
+	configuration might only allow certain number of connections per
+	client.
+
+* base
+	This is the search base that will be used by the LDAP back-end
+	to search for DNS zones. This option is mandatory.
+	Example: "cn=dns, dc=example,dc=com";
+
+* auth_method (default "none")
+
+	The method used to authenticate to the LDAP server. Currently
+	supported methods are "none", "simple" and "sasl". The none
+	method is effectively a simple authentication without password.
+
+* bind_dn (default "")
+
+	Distinguished Name used to bind to the LDAP server. If this is
+	empty and the auth_method is set to "simple", the LDAP back-end
+	will fall-back and use the "none" authentication method.
+
+* password (default "")
+
+	Password for simple and SASL authentication. If the authentication
+	method is set to "simple" and the password is empty, the LDAP
+	driver will fall-back to the "none" authentication method.
+
+* sasl_mech (default "GSSAPI")
+
+	Name of the SASL mechanism to be used for negotiation.
+
+* sasl_auth_name
+
+	The user name to be used for SASL authentication.
+
+* sasl_user
+
+	The user name to be used for SASL proxy authorization.
+
+* sasl_password
+
+	The password to use for the SASL authentication.
+
+* sasl_realm
+
+	The SASL realm name.
+
+* krb5_keytab
+
+	Path to the kerberos keytab containing service credentials to be used
+	for SASL authentication. Append the "FILE:" prefix to the file path.
+	Example: "FILE:/etc/named.keytab"
+
+* krb5_principal
+
+	Kerberos principal of the service, used for SASL authentication.
+	If not set then it is copied from "sasl_user" option. Principal
+	is loaded from file specified in "krb5_keytab" option.
+
+* timeout (default 10)
+
+	Timeout (in seconds) of the queries to the LDAP server. If the LDAP
+	server don't respond before this timeout then lookup is aborted and
+	BIND returns SERVFAIL. Value "0" means infinite timeout (no timeout).
+
+* reconnect_interval (default 60)
+
+	Time (in seconds) after that the plugin should try to connect to LDAP 
+	server again in case connection is lost and immediate reconnection 
+	fails.
+
+* ldap_hostname (default "")
+
+	Sets hostname of the LDAP server. When it is set to "", actual
+	`/bin/hostname` is used. Please prefer `uri` option, this option should be
+	used only in special cases, for example when GSSAPI authentication
+	is used and named service has Kerberos principal different from
+	`/bin/hostname` output.
+
+
+5.1.2 Special DNS features
+--------------------------
+* fake_mname
+
+	Ignore value of the idnsSOAmName (primary master DNS name) attribute
+	and use this value instead. This allows multiple BIND processes to share
+	one LDAP database and every BIND reports itself as a primary master in
+	SOA record, for example.
+
+* sync_ptr (default no)
+
+	Set this option to `yes` if you would like to keep PTR record 
+	synchronized with coresponding A/AAAA record for all zones.
+	If this option is set to `no`, the LDAP driver will check
+	the idnsAllowSyncPTR attribute which specifies the synchronization
+	policy for PTR records in a zone. When an A/AAAA record is deleted 
+	the PTR record must point to the same hostname. 
+	
+* dyn_update (default no)
+
+	Set this option to `yes` if you would like to allow dynamic zone updates.
+	This setting can be overridden for each zone individually
+	by idnsAllowDynUpdate attribute.
+
+
+5.1.3 Plumbing
+--------------
+* verbose_checks (default no)
+
+	Set this option to `yes` if you would like to log all failures
+	in internal CHECK() macros. This option is recommended only for
+	debugging purposes. It could produce huge amount of log messages
+	on a loaded system!
+
+* directory (default is
+             `dyndb-ldap/<current instance name from dynamic-db directive>`)
+        
+	Specifies working directory for plug-in. The path has to be writeable
+	by named because plug-in will create sub-directory for each zone.
+	These sub-directories will contain temporary files like zone dump, zone
+	journal, zone keys etc.
+	The path is relative to `directory` specified in BIND options.
+	See section 6 (DNSSEC) for examples.
+
+5.2 Sample configuration
+------------------------
+Let's take a look at a sample configuration:
+
+	options {
+		directory "/var/named/";
+	};
+	
+	dyndb "my_db_name" "/usr/lib64/bind/ldap.so" {
+		uri "ldap://ldap.example.com";;
+		base "cn=dns, dc=example,dc=com";
+		auth_method "none";
+	};
+
+With this configuration, the LDAP back-end will try to connect to server
+ldap.example.com with simple authentication, without any password. It
+will then use RFC 4533 refresh&persist search in the `cn=dns,dc=example,dc=com`
+base for entries with object class `idnsZone` and `idnsRecord`.
+For each idnsZone entry it will find, it will register a new zone with BIND.
+For each idnsRecord entry it will create domain name in particular zone.
+The LDAP back-end will keep each record it gets from LDAP in its memory.
+
+Working directory for the plug-in will be `/var/named/dyndb-ldap/my_db_name/`,
+so hypothetical zone `example.com` will use sub-directory
+`/var/named/dyndb-ldap/my_db_name/master/example.com/`.
+
+5.3 Configuration in LDAP
+-------------------------
+Some options can be configured in LDAP as `idnsConfigObject` attributes.
+Value configured in LDAP has priority over value in configuration file.
+(This behavior will change in future versions!)
+
+Following options are supported (option = attribute equivalent):
+option     | LDAP attribute
+-----------| --------------
+forwarders | idnsForwarders (BIND native option)
+forward    | idnsForwardPolicy (BIND native option)
+sync_ptr   | idnsAllowSyncPTR
+
+Forward policy option cannot be set without setting forwarders at the same time.
+
+
+6. DNSSEC support
+=================
+
+In-line signing support in this plugin allows to use this BIND feature
+for zones in LDAP.
+
+Signatures are automatically generated by plugin during zone loading
+and signatures are never written back to LDAP. DNSKEY, RRSIG, NSEC and NSEC3
+records in LDAP are ignored because they are automatically managed by BIND.
+
+NSEC3 can be enabled by writting NSEC3PARAM RR to particular zone object
+in LDAP.
+
+Dynamic updates made to in-line signed zones are written back to LDAP as usual
+and respective signatures are automatically re-generated as necessary.
+
+Key management has to be handled by user, i.e. user has to
+generate/delete keys and configure key timestamps as appropriate.
+
+Key directory for particular DNS zone is automatically configured to value:
+	<plugin-instance-dir>/master/<zone-name>/keys
+
+`<plugin-instance-dir>` is described in section 5.1.3 of this file.
+`<zone-name>` is (transformed) textual representation of zone name without
+trailing period.
+
+Zone name will be automatically transformed before usage:
+- root zone is translated to `@` to prevent collision with filesystem `.`
+- digits, hyphen and underscore are left intact
+- letters of English alphabet are downcased
+- all other characters are escaped using %ASCII_HEX form, e.g. `/` => `%2F`
+- final dot is omited
+- labels are separated with `.`
+
+Example:
+* BIND directory: `/var/named`
+* bind-dyndb-ldap directory: `dyndb-ldap`
+* LDAP instance name: `ipa`
+* DNS zone: `example.com.`
+* Resulting keys directory: `/var/named/dyndb-ldap/ipa/master/example.com/keys`
+
+* DNS zone: `TEST.0/1.a.`
+* Resulting keys directory: `/var/named/dyndb-ldap/ipa/master/test.0%2F1.a/keys`
+
+Make sure that keys directory and files is readable by user used for BIND.
+
+
+7. License
+==========
+
+This package is licensed under the GNU General Public License, version 2
+only. See file COPYING for more information.
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to