diff --git a/bind-9.11.patch b/bind-9.11.patch new file mode 100644 index 0000000..fcdfd6c --- /dev/null +++ b/bind-9.11.patch @@ -0,0 +1,3215 @@ +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: diff --git a/bind-dyndb-ldap.spec b/bind-dyndb-ldap.spec index 2ea640f..7e1ff40 100644 --- a/bind-dyndb-ldap.spec +++ b/bind-dyndb-ldap.spec @@ -2,7 +2,7 @@ Name: bind-dyndb-ldap Version: 10.1 -Release: 1%{?dist} +Release: 2%{?dist} Summary: LDAP back-end plug-in for BIND Group: System Environment/Libraries @@ -10,9 +10,11 @@ License: GPLv2+ URL: https://fedorahosted.org/bind-dyndb-ldap Source0: https://fedorahosted.org/released/%{name}/%{name}-%{VERSION}.tar.bz2 Source1: https://fedorahosted.org/released/%{name}/%{name}-%{VERSION}.tar.bz2.asc +# Temporary workaround, until 11.0 is released +Patch1: bind-9.11.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -BuildRequires: bind-devel >= 32:9.9.0-1, bind-lite-devel >= 32:9.9.0-1 +BuildRequires: bind-devel >= 32:9.9.0-1, bind-lite-devel >= 32:9.9.0-1, bind-pkcs11-devel >= 32:9.9.0-1 BuildRequires: krb5-devel BuildRequires: openldap-devel BuildRequires: libuuid-devel @@ -28,6 +30,7 @@ off of your LDAP server. %prep %setup -q -n %{name}-%{VERSION} +%patch1 -p1 -b .bind9-11 %build autoreconf -fiv @@ -70,12 +73,18 @@ rm -rf %{buildroot} %files %defattr(-,root,root,-) -%doc NEWS README COPYING doc/{example,schema}.ldif +%doc NEWS README.md COPYING doc/{example,schema}.ldif %dir %attr(770, root, named) %{_localstatedir}/named/dyndb-ldap %{_libdir}/bind/ldap.so %changelog +* Mon Nov 21 2016 Petr Menšík - 10.1-2 +- Patched to alfa 11.0 with support for BIND 9.11 +- Configuration format in named.conf is different + and incompatible with all previous versions. Please see README.md. +- Minimal BIND version is now 9.11.0rc1. Please see NEWS. + * Wed Aug 17 2016 Petr Spacek - 10.1-1 - Update to 10.1. - Fix deletion of DNS root zone not to break global forwarding.