NameDateSize

..21-Jun-20245

dlz_example.cH A D22-Feb-202419.3 KiB

MakefileH A D22-Feb-2024870

named.confH A D24-Sep-20221.9 KiB

READMEH A D22-Feb-202410.8 KiB

README

1<!--
2Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
4SPDX-License-Identifier: MPL-2.0
5
6This Source Code Form is subject to the terms of the Mozilla Public
7License, v. 2.0.  If a copy of the MPL was not distributed with this
8file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
10See the COPYRIGHT file distributed with this work for additional
11information regarding copyright ownership.
12-->
13
14OVERVIEW:
15
16DLZ (Dynamically Loadable Zones) is an extension to BIND 9 that
17allows zone data to be retrieved directly from an external database.
18There is no required format or schema.  DLZ drivers exist for several
19different database backends including PostgreSQL, MySQL, and LDAP and
20can be written for any other.
21
22Historically, DLZ drivers had to be statically linked with the named
23binary and were turned on via a configure option at compile time (for
24example, "configure --with-dlz-ldap").  Currently, the drivers provided
25in the BIND 9 tarball in contrib/dlz/drivers are still linked this way.
26
27However, as of BIND 9.8, it is also possible to link some DLZ modules
28dynamically at runtime, via the DLZ "dlopen" driver, which acts as a
29generic wrapper around a shared object that implements the DLZ API.  The
30"dlopen" driver is linked into named by default, so configure options are
31no longer necessary unless using older DLZ drivers.
32
33When the DLZ module provides data to named, it does so in text format.
34The response is converted to DNS wire format by named.  This conversion,
35and the lack of any internal caching, places significant limits on the
36query performance of DLZ modules.  Consequently, DLZ is not recommended
37for use on high-volume servers.  However, it can be used in a hidden
38primary configuration, with secondaries retrieving zone updates via AXFR.
39(Note, however, that DLZ has no built-in support for DNS notify; secondaries
40are not automatically informed of changes to the zones in the database.)
41
42CONFIGURING DLZ:
43
44A DLZ database is configured with a "dlz" statement in named.conf.
45
46    dlz example {
47        database "dlopen driver.so <args>";
48        search yes;
49    };
50
51This specifies a DLZ module to search when answering queries; the module
52is implemented in "driver.so" and is loaded at runtime by the dlopen DLZ
53driver.  Multiple "dlz" statements can be specified; when answering a
54query, all DLZ modules with the "search" option set to "yes" will be
55checked for an answer, and the best available answer will be returned
56to the client.
57
58The "search" option in this example can be omitted, as "yes" is the
59default value.  If it is set to "no", then this DLZ module is *not*
60searched for best-match when a query is received.  Instead, zones in
61this DLZ must be separately specified in a zone statement.  This can
62be useful when conventional zone semantics are desired but you wish
63to use a different back-end storage mechanism than the standard zone
64database.  For example, to use a DLZ module for an NXDOMAIN redirection
65zone:
66
67    dlz other {
68        database "dlopen driver.so <args>";
69        search no;
70    };
71
72    zone "." {
73        type redirect;
74        dlz other;
75    };
76
77EXAMPLE DRIVER:
78
79This directory contains an example of an externally-lodable DLZ module,
80dlz_example.c, which demonstrates the features of the DLZ API.  It sets up
81a single zone, whose name is configured in named.conf.  The zone can answer
82queries and AXFR requests, and accept DDNS updates.
83
84By default, at runtime, the zone implemented by this driver will contain
85an SOA, NS, and a single A record at the apex.  If configured in named.conf
86to use the name "example.nil", then, the zone will look like this:
87
88 example.nil.  3600    IN      SOA     example.nil. hostmaster.example.nil. (
89                                               123 900 600 86400 3600
90                                       )
91 example.nil.  3600    IN      NS      example.nil.
92 example.nil.  1800    IN      A       10.53.0.1
93
94The driver is also capable of retrieving information about the querying
95client, and altering its response on the basis of this information.  To
96demonstrate this feature, the example driver responds to queries for
97"source-addr.<zonename>/TXT" with the source address of the query.
98Note, however, that this record will *not* be included in AXFR or ANY
99responses.  (Normally, this feature would be used to alter responses in
100some other fashion, e.g., by providing different address records for
101a particular name depending on the network from which the query arrived.)
102
103DYNAMIC UPDATES AND TRANSACTIONS:
104
105If a DLZ module wants to implement dynamic DNS updates (DDNS), the
106normal calling sequence is
107 - dlz_newversion (start a 'transaction')
108 - dlz_addrdataset (add records)
109 - dlz_subrdataset (remove records)
110 - dlz_closeversion (end a 'transaction')
111
112However, BIND may also query the database during the transaction
113(e.g., to check prerequisites), and your DLZ might need to know whether
114the lookup is against the pre-existing data, or the new data.
115dlz_lookup() doesn't give you access to the 'versionp' pointer
116directly, so it must be passed via 'clientinfo' structure if
117it is needed.
118
119The dlz_example.c code has sample code to show how to get the 'versionp'
120pointer from within dlz_lookup(). If it's set to NULL, we query
121the standard database; if non-NULL, we query against the in-flight
122data within the appropriate uncommitted transaction.
123
124IMPLEMENTATION NOTES:
125
126The minimal set of type definitions, prototypes, and macros needed
127for implementing a DLZ driver is in ../modules/dlz_minimal.h.  Copy this
128header file into your source tree when creating an external DLZ module.
129
130The DLZ dlopen driver provides a set of callback functions:
131
132  - void log(int level, const char *fmt, ...);
133
134    Writes the specified string to the named log, at the specified
135    log level.  Uses printf() format semantics.
136
137  - isc_result_t putrr(dns_sdlzlookup_t *lookup, const char *type,
138                       dns_ttl_t ttl, const char *data);
139
140    Puts a DNS resource record into the query response, which
141    referenced by the opaque structure 'lookup' provided by named.
142
143  - isc_result_t putnamedrr(dns_sdlzallnotes_t *allnodes,
144                            const char *name, const char *type,
145                            dns_ttl_t ttl, const char *data);
146
147    Puts a DNS resource record into an AXFR response, which is
148    referenced by the opaque structure 'allnodes' provided by named.
149
150  - isc_result_t writeable_zone(dns_view_t *view, const char *zone_name);
151
152    Allows the DLZ module to inform named that a given zone can receive
153    DDNS updates.  (Note: This is not currently supported for DLZ
154    databases that are configured as 'search no;')
155
156The external DLZ module can define the following functions (some of these
157are mandatory, others optional).
158
159  - int dlz_version(unsigned int *flags);
160
161    Required for alL external DLZ modules, to indicate the version number
162    of the DLZ dlopen driver that this module supports.  It should return
163    the value DLZ_DLOPEN_VERSION, which is defined in the file
164    contrib/dlz/modules/dlz_minimal.h and is currently 3.  'flags' is
165    updated to indicate capabilities of the module.  In particular, if
166    the module is thread-safe then it sets 'flags' to include
167    DNS_SDLZFLAG_THREADSAFE.  (Other capability flags may be added in
168    the future.)
169
170  - isc_result_t dlz_create(const char *dlzname,
171                            unsigned int argc, char *argv[],
172                            void **dbdata, ...);
173
174    Required for all external DLZ modules; this call initializes the
175    module.
176
177  - void dlz_destroy(void *dbdata);
178
179    Optional.  If supplied, this will be called when the driver is
180    unloaded.
181
182  - isc_result_t dlz_findzonedb(void *dbdata, const char *name,
183                                dns_clientinfomethods_t *methods,
184                                dns_clientinfo_t *clientinfo);
185
186    Required for all external DLZ modules.  This indicates whether
187    the DLZ module can answer for the given name.  Returns ISC_R_SUCCESS
188    if so, and ISC_R_NOTFOUND if not.  As an optimization, it can
189    also return ISC_R_NOMORE: this indicates that the DLZ module has
190    no data for the given name or for any name above it in the DNS.
191    This prevents named from searching for a zone cut.
192
193   - isc_result_t dlz_lookup(const char *zone, const char *name, void *dbdata,
194                             dns_sdlzlookup_t *lookup,
195                             dns_clientinfomethods_t *methods,
196                             dns_clientinfo_t *clientinfo);
197
198    Required for all external DLZ modules.  This carries out the database
199    lookup for a query.
200
201  - isc_result_t dlz_allowzonexfr(void *dbdata, const char *name,
202                                  const char *client);
203
204    Optional.  Supply this if you want the module to support AXFR
205    for the specified zone and client.  A return value of ISC_R_SUCCESS
206    means AXFR is allowed, any other value means it isn't.
207
208  -  isc_result_t dlz_allnodes(const char *zone, void *dbdata,
209                               dns_sdlzallnodes_t *allnodes);
210
211     Optional, but must be supplied dlz_allowzonexfr() is.  This function
212     returns all nodes in the zone in order to perform a zone transfer.
213
214  - isc_result_t dlz_newversion(const char *zone, void *dbdata,
215                                void **versionp);
216
217    Optional.  Supply this if you want the module to support DDNS
218    updates.  This function starts a transaction in the database.
219
220
221  - void dlz_closeversion(const char *zone, bool commit,
222                          void *dbdata, void **versionp);
223
224    Optional, but must be supplied if dlz_newversion() is.  This function
225    closes a transaction.  'commit' indicates whether to commit the changes
226    to the database, or ignore them.
227
228  - isc_result_t dlz_configure(dns_view_t *view, void *dbdata);
229
230    Optional, but must be supplied in order to support DDNS updates.
231
232  - bool dlz_ssumatch(const char *signer, const char *name,
233                               const char *tcpaddr, const char *type,
234                               const char *key, uint32_t keydatalen,
235                               uint8_t *keydata, void *dbdata);
236
237    Optional, but must be supplied in order to support DDNS updates.
238
239  - isc_result_t dlz_addrdataset(const char *name, const char *rdatastr,
240                                 void *dbdata, void *version);
241
242    Optional, but must be supplied in order to support DDNS updates.
243    Adds the data in 'rdatastr' to a database node.
244
245  - isc_result_t dlz_subrdataset(const char *name, const char *rdatastr,
246                                 void *dbdata, void *version);
247
248    Optional, but must be supplied in order to support DDNS updates.
249    Removes the data in 'rdatastr' from a database node.
250
251  - isc_result_t dlz_delrdataset(const char *name, const char *rdatastr,
252                                 void *dbdata, void *version);
253
254    Optional, but must be supplied in order to support DDNS updates.
255    Deletes all data matching the type specified in 'rdatastr' from
256    the database.
257