README revision be7d3e641c1f426185cc65950c8b587a3365f038
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinDLZ (Dynamically Loadable Zones) is an extention to BIND 9 that
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinallows zone data to be retrieved directly from an external database.
ddccd5811feff696ba460dabfb666ce61040f545Andreas GustafssonThere is no required format or schema. DLZ drivers exist for several
ddccd5811feff696ba460dabfb666ce61040f545Andreas Gustafssondifferent database backends including PostgreSQL, MySQL, and LDAP and
ddccd5811feff696ba460dabfb666ce61040f545Andreas Gustafssoncan be written for any other.
8a66318e41ed14c5a88130e8c362610e8faa2121Mark AndrewsHistorically, DLZ drivers had to be statically linked with the named
8a66318e41ed14c5a88130e8c362610e8faa2121Mark Andrewsbinary and were turned on via a configure option at compile time (for
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinexample, "configure --with-dlz-ldap"). Currently, the drivers provided
8a66318e41ed14c5a88130e8c362610e8faa2121Mark Andrewsin the BIND 9 tarball in contrib/dlz/drivers are still linked this way.
8a66318e41ed14c5a88130e8c362610e8faa2121Mark AndrewsHowever, as of BIND 9.8, it is also possible to link some DLZ modules
8a66318e41ed14c5a88130e8c362610e8faa2121Mark Andrewsdynamically at runtime, via the DLZ "dlopen" driver, which acts as a
ddccd5811feff696ba460dabfb666ce61040f545Andreas Gustafssongeneric wrapper around a shared object that implements the DLZ API. The
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein"dlopen" driver is linked into named by default, so configure options are
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinno longer necessary unless using older DLZ drivers.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinWhen the DLZ module provides data to named, it does so in text format.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThe response is converted to DNS wire format by named. This conversion,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinand the lack of any internal caching, places significant limits on the
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinquery performance of DLZ modules. Consequently, DLZ is not recommended
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinfor use on high-volume servers. However, it can be used in a hidden
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinmaster configuration, with slaves retrieving zone updates via AXFR.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein(Note, however, that DLZ has no built-in support for DNS notify; slaves
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinare not automatically informed of changes to the zones in the database.)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinCONFIGURING DLZ:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinA DLZ database is configured with a "dlz" statement in named.conf.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dlz example {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein database "dlopen driver.so <args>";
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThis specifies a DLZ module to search when answering queries; the module
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinis implemented in "driver.so" and is loaded at runtime by the dlopen DLZ
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindriver. Multiple "dlz" statements can be specified; when answering a
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinquery, all DLZ modules with the "search" option set to "yes" will be
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinchecked for an answer, and the best available answer will be returned
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinto the client.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThe "search" option in this example can be omitted, as "yes" is the
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindefault value. If it is set to "no", then this DLZ module is *not*
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinsearched for best-match when a query is received. Instead, zones in
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinthis DLZ must be separately specified in a zone statement. This can
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinbe useful when conventional zone semantics are desired but you wish
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinto use a different back-end storage mechanism than the standard zone
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindatabase. For example, to use a DLZ module for an NXDOMAIN redirection
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein database "dlopen driver.so <args>";
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein type redirect;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinEXAMPLE DRIVER:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThis directory contains an example of an externally-lodable DLZ module,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindlz_example.c, which demonstrates the features of the DLZ API. It sets up
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeina single zone, whose name is configured in named.conf. The zone can answer
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinqueries and AXFR requests, and accept DDNS updates.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinBy default, at runtime, the zone implemented by this driver will contain
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinan SOA, NS, and a single A record at the apex. If configured in named.conf
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinto use the name "example.nil", then, the zone will look like this:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein example.nil. 3600 IN SOA example.nil. hostmaster.example.nil. (
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein 123 900 600 86400 3600
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein example.nil. 1800 IN A 10.53.0.1
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThe driver is also capable of retrieving information about the querying
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinclient, and altering its response on the basis of this information. To
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindemonstrate this feature, the example driver responds to queries for
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein"source-addr.<zonename>/TXT" with the source address of the query.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinNote, however, that this record will *not* be included in AXFR or ANY
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinresponses. (Normally, this feature would be used to alter responses in
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinsome other fashion, e.g., by providing different address records for
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeina particular name depending on the network from which the query arrived.)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinDYNAMIC UPDATES AND TRANSACTIONS:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinIf a DLZ module wants to implement dynamic DNS updates (DDNS), the
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinnormal calling sequence is
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - dlz_newversion (start a 'transaction')
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - dlz_addrdataset (add records)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - dlz_subrdataset (remove records)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - dlz_closeversion (end a 'transaction')
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinHowever, BIND may also query the database during the transaction
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein(e.g., to check prerequisites), and your DLZ might need to know whether
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinthe lookup is against the pre-existing data, or the new data.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindlz_lookup() doesn't give you access to the 'versionp' pointer
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindirectly, so it must be passed via 'clientinfo' structure if
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinit is needed.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThe dlz_example.c code has sample code to show how to get the 'versionp'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinpointer from within dlz_lookup(). If it's set to NULL, we query
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinthe standard database; if non-NULL, we query against the in-flight
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindata within the appropriate uncommitted transaction.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinIMPLEMENTATION NOTES:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThe minimal set of type definitions, prototypes, and macros needed
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinfor implementing a DLZ driver is in ../modules/dlz_minimal.h. Copy this
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinheader file into your source tree when creating an external DLZ module.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThe DLZ dlopen driver provides a set of callback functions:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - void log(int level, const char *fmt, ...);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Writes the specified string to the named log, at the specified
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein log level. Uses printf() format semantics.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t putrr(dns_sdlzlookup_t *lookup, const char *type,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_ttl_t ttl, const char *data);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Puts a DNS resource record into the query response, which
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein referenced by the opaque structure 'lookup' provided by named.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t putnamedrr(dns_sdlzallnotes_t *allnodes,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein const char *name, const char *type,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_ttl_t ttl, const char *data);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Puts a DNS resource record into an AXFR response, which is
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein referenced by the opaque structure 'allnodes' provided by named.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t writeable_zone(dns_view_t *view, const char *zone_name);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Allows the DLZ module to inform named that a given zone can recieve
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein DDNS updates. (Note: This is not currently supported for DLZ
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein databases that are configured as 'search no;')
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinThe external DLZ module can define the following functions (some of these
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinare mandatory, others optional).
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - int dlz_version(unsigned int *flags);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Required for alL external DLZ modules, to indicate the version number
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein of the DLZ dlopen driver that this module supports. It should return
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein the value DLZ_DLOPEN_VERSION, which is defined in the file
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein contrib/dlz/modules/dlz_minimal.h and is currently 3. 'flags' is
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein updated to indicate capabilities of the module. In particular, if
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein the module is thread-safe then it sets 'flags' to include
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein DNS_SDLZFLAG_THREADSAFE. (Other capability flags may be added in
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein the future.)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t dlz_create(const char *dlzname,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein unsigned int argc, char *argv[],
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein void **dbdata, ...);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Required for all external DLZ modules; this call initializes the
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - void dlz_destroy(void *dbdata);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional. If supplied, this will be called when the driver is
8eea877894ea5bcf5cdd9ca124a8601ad421d753Andreas Gustafsson - isc_result_t dlz_findzonedb(void *dbdata, const char *name,
8eea877894ea5bcf5cdd9ca124a8601ad421d753Andreas Gustafsson dns_clientinfomethods_t *methods,
8eea877894ea5bcf5cdd9ca124a8601ad421d753Andreas Gustafsson dns_clientinfo_t *clientinfo);
8eea877894ea5bcf5cdd9ca124a8601ad421d753Andreas Gustafsson Required for all external DLZ modules. This indicates whether
8eea877894ea5bcf5cdd9ca124a8601ad421d753Andreas Gustafsson the DLZ module can answer for the given name. Returns ISC_R_SUCCESS
8eea877894ea5bcf5cdd9ca124a8601ad421d753Andreas Gustafsson if so, and ISC_R_NOTFOUND if not. As an optimization, it can
8eea877894ea5bcf5cdd9ca124a8601ad421d753Andreas Gustafsson also return ISC_R_NOMORE: this indicates that the DLZ module has
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein no data for the given name or for any name above it in the DNS.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein This prevents named from searching for a zone cut.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t dlz_lookup(const char *zone, const char *name, void *dbdata,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_sdlzlookup_t *lookup,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_clientinfomethods_t *methods,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_clientinfo_t *clientinfo);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Required for all external DLZ modules. This carries out the database
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein lookup for a query.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t dlz_allowzonexfr(void *dbdata, const char *name,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein const char *client);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional. Supply this if you want the module to support AXFR
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein for the specified zone and client. A return value of ISC_R_SUCCESS
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein means AXFR is allowed, any other value means it isn't.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t dlz_allnodes(const char *zone, void *dbdata,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_sdlzallnodes_t *allnodes);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional, but must be supplied dlz_allowzonexfr() is. This function
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein returns all nodes in the zone in order to perform a zone transfer.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t dlz_newversion(const char *zone, void *dbdata,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein void **versionp);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional. Supply this if you want the module to support DDNS
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein updates. This function starts a transaction in the database.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - void dlz_closeversion(const char *zone, isc_boolean_t commit,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein void *dbdata, void **versionp);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional, but must be supplied if dlz_newversion() is. This function
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein closes a transaction. 'commit' indicates whether to commit the changes
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein to the database, or ignore them.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t dlz_configure(dns_view_t *view, void *dbdata);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional, but must be supplied in order to support DDNS updates.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_boolean_t dlz_ssumatch(const char *signer, const char *name,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein const char *tcpaddr, const char *type,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein const char *key, uint32_t keydatalen,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein uint8_t *keydata, void *dbdata);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional, but must be supplied in order to support DDNS updates.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t dlz_addrdataset(const char *name, const char *rdatastr,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein void *dbdata, void *version);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional, but must be supplied in order to support DDNS updates.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Adds the data in 'rdatastr' to a database node.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t dlz_subrdataset(const char *name, const char *rdatastr,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein void *dbdata, void *version);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional, but must be supplied in order to support DDNS updates.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Removes the data in 'rdatastr' from a database node.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein - isc_result_t dlz_delrdataset(const char *name, const char *rdatastr,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein void *dbdata, void *version);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Optional, but must be supplied in order to support DDNS updates.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Deletes all data matching the type specified in 'rdatastr' from
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein the database.