diff --git a/bind-9.11.patch b/bind-9.11.patch deleted file mode 100644 index fcdfd6c..0000000 --- a/bind-9.11.patch +++ /dev/null @@ -1,3215 +0,0 @@ -diff --git a/Makefile.am b/Makefile.am -index f5ff369..31ba5d6 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -2,4 +2,4 @@ ACLOCAL_AMFLAGS = -I m4 - - SUBDIRS = doc src - --doc_DATA = README NEWS -+dist_doc_DATA = README.md NEWS COPYING -diff --git a/NEWS b/NEWS -index 12aa18a..8fac0dd 100644 ---- a/NEWS -+++ b/NEWS -@@ -1,3 +1,14 @@ -+11.0 -+==== -+[1] The plugin was ported to BIND 9.11. Minimal BIND version is now 9.11.0rc1. -+ https://fedorahosted.org/bind-dyndb-ldap/ticket/161 -+ -+[2] Configuration format in named.conf is different -+ and incompatible with all previous versions. Please see README.md. -+ -+[3] Obsolete plugin options were removed: -+ cache_ttl, psearch, serial_autoincrement, zone_refresh. -+ - 10.1 - ==== - [1] Prevent crash while reloading previously invalid but now valid DNS zone. -diff --git a/README b/README -deleted file mode 100644 -index 2fd09b5..0000000 ---- a/README -+++ /dev/null -@@ -1,539 +0,0 @@ --1. Introduction --=============== -- --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: -- -- 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 --=========== -- --* 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= --$ make -- --Where 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`" command. -- --Then, to install, run this as root: --# make install -- --This will install the file ldap.so into the /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 " after IP -- address. IPv4 and IPv6 addresses are supported. -- Examples: "1.2.3.4" or "1.2.3.4 port 553" or "A::B" or "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 "//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 " after IP -- address. IPv4 and IPv6 addresses are supported. -- Examples: "1.2.3.4" or "1.2.3.4 port 553" or "A::B" or "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 "dynamic-db" --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. -- --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. -- -- --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. It is mandatory. -- --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. -- (FILE:/etc/named.keytab, for example) -- --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 (default "") -- 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/") -- 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/"; --}; -- --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"; --}; -- --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): -- --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: --/master//keys -- -- is described in section 5.1.3 of this file. -- 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. -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= -+ $ make -+ -+Where `` 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 `/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 ` 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 "//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 ` 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/`) -+ -+ 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: -+ /master//keys -+ -+`` is described in section 5.1.3 of this file. -+`` 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. -diff --git a/configure.ac b/configure.ac -index 9b26058..50e41f3 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1,9 +1,9 @@ - AC_PREREQ([2.59]) --AC_INIT([bind-dyndb-ldap], [10.1], [freeipa-devel@redhat.com]) -+AC_INIT([bind-dyndb-ldap], [11.0], [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]) - -@@ -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 -+#include - 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/doc/schema.ldif b/doc/schema.ldif -index 8fdc99f..77c5b0e 100644 ---- a/doc/schema.ldif -+++ b/doc/schema.ldif -@@ -362,9 +362,16 @@ attributeTypes: ( 2.16.840.1.113730.3.8.5.31 - NAME 'idnsServerId' - DESC 'DNS server identifier' - SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 -- EQUALITY caseIgnoreMatch -+ EQUALITY caseIgnoreMatch - SINGLE-VALUE ) - # -+attributeTypes: ( 2.16.840.1.113730.3.8.5.29 -+ NAME 'idnsTemplateAttribute' -+ DESC 'Template attribute for dynamic attribute generation' -+ EQUALITY caseIgnoreIA5Match -+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 -+ X-ORIGIN 'IPA v4.4' ) -+# - attributeTypes: ( 2.16.840.1.113730.3.8.5.30 - NAME 'idnsSubstitutionVariable' - DESC 'User defined variable for DNS plugin' -@@ -426,6 +433,6 @@ objectClasses: ( 2.16.840.1.113730.3.8.6.6 - objectClasses: ( 2.16.840.1.113730.3.8.6.5 - NAME 'idnsTemplateObject' - DESC 'Template object for dynamic DNS attribute generation' -- SUP top -+ SUP top - AUXILIARY - MUST ( idnsTemplateAttribute ) ) -diff --git a/src/Makefile.am b/src/Makefile.am -index 238d8ef..e1e3968 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 \ -@@ -27,7 +26,6 @@ HDRS = \ - types.h \ - util.h \ - zone.h \ -- zone_manager.h \ - zone_register.h - - ldap_la_SOURCES = \ -@@ -54,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/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 --#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 -- --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/fs.c b/src/fs.c -index 09b71d7..61c46b5 100644 ---- a/src/fs.c -+++ b/src/fs.c -@@ -10,7 +10,7 @@ - - #include - #include --#include -+#include - #include - #include - #include -@@ -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); -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 @@ cleanup: - - 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 @@ cleanup: - } - - 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..b1b7336 100644 ---- a/src/ldap_driver.c -+++ b/src/ldap_driver.c -@@ -9,13 +9,17 @@ - #endif - - #include -+#include -+#include -+#include - #include -+#include - #include - #include - - #include - #include --#include -+#include - #include - #include - #include -@@ -29,13 +33,12 @@ - - #include /* For memcpy */ - --#include "compat.h" -+#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 -@@ -181,18 +184,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 +201,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 +211,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 +220,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 +401,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 +646,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 +655,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 +666,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 +733,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 +743,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 +763,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 +792,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 +803,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 +812,23 @@ hashsize(dns_db_t *db) - - return dns_db_hashsize(ldapdb->rbtdb); - } --#endif /* LIBDNS_VERSION_MAJOR >= 140 */ -+ -+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, - 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 +852,22 @@ 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 */ -+ hashsize, -+ nodefullname - }; - - isc_result_t ATTR_NONNULLS -@@ -1002,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); -@@ -1026,19 +945,16 @@ cleanup: - - 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); -@@ -1060,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)); -@@ -1084,50 +1000,91 @@ cleanup: - 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; -+ 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); - - /* Finally, create the instance. */ -- result = manager_create_db_instance(mctx, name, argv, dyndb_args); -+ CHECK(new_ldap_instance(mctx, name, parameters, file, line, dctx, -+ &inst)); -+ *instp = inst; - -+cleanup: - 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..a11751d 100644 ---- a/src/ldap_helper.c -+++ b/src/ldap_helper.c -@@ -4,7 +4,7 @@ - - #include "config.h" - --#include -+#include - #include - #include - #include -@@ -42,6 +42,7 @@ - #include - - #include -+#include - - #include - #define LDAP_DEPRECATED 1 -@@ -77,7 +78,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 +133,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 +185,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" }, -@@ -206,7 +201,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 }, -@@ -220,12 +214,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 */ -@@ -238,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 }, -@@ -351,14 +386,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; -@@ -485,12 +512,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; - -@@ -505,13 +526,12 @@ cleanup: - - #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, 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; -- 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 +546,31 @@ 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(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() */ -@@ -573,7 +594,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 +607,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 +660,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 +688,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 +695,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 +717,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 +738,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 +948,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 +958,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 +967,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 +3684,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 +3692,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 +3702,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 +3719,6 @@ cleanup: - "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 +3732,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 +3752,6 @@ cleanup: - 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 +3762,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 +3782,6 @@ cleanup: - 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 +3801,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 +3838,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 +4010,6 @@ cleanup: - 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,8 +4080,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; - isc_boolean_t synchronous; -@@ -4069,10 +4092,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); -- -- CHECKED_MEM_STRDUP(mctx, inst->db_name, dbname); -- - if (entry->class & LDAP_ENTRYCLASS_MASTER) - zone_name = &entry->fqdn; - else -@@ -4128,8 +4147,9 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t **entryp, int chgtype) - goto cleanup; - } - -- pevent->mctx = mctx; -- pevent->dbname = dbname; -+ pevent->mctx = NULL; -+ isc_mem_attach(inst->mctx, &pevent->mctx); -+ pevent->inst = inst; - pevent->prevdn = NULL; - pevent->chgtype = chgtype; - pevent->entry = entry; -@@ -4148,11 +4168,8 @@ cleanup: - 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); -+ if (pevent->mctx != NULL) -+ isc_mem_detach(&pevent->mctx); - ldap_entry_destroy(entryp); - if (task != NULL) - isc_task_detach(&task); -@@ -4394,7 +4411,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 +4464,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..6cfece5 100644 ---- a/src/ldap_helper.h -+++ b/src/ldap_helper.h -@@ -9,6 +9,7 @@ - - #include - #include -+#include - - #include - -@@ -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, -- 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, 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 3692dae..37e6e5c 100644 ---- a/src/settings.c -+++ b/src/settings.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+ - #include - - #include -@@ -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, const char *const *argv) -+static isc_result_t -+settings_set_fill(const cfg_obj_t *config, settings_set_t *set) - { - isc_result_t result; -- int i; -- const char *name; -- char *value; -- -- for (i = 0; argv[i] != NULL; 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,75 @@ 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); -+ 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; -+ } -+ -+ 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 9bc4176..16a1e63 100644 ---- a/src/settings.h -+++ b/src/settings.h -@@ -6,12 +6,13 @@ - #define _LD_SETTINGS_H_ - - #include -+ -+#include -+ - #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, const char *const *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; -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 @@ cleanup: - } - - 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 @@ cleanup: - } - - 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 @@ cleanup: - * 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 --#include --#include --#include --#include --#include --#include -- --#include --#include --#include -- --#include --#include -- --#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 -- --#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 @@ cleanup: - 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: