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