1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0 AND ISC
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 /*
15  * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
16  *
17  * Permission to use, copy, modify, and distribute this software for any
18  * purpose with or without fee is hereby granted, provided that the
19  * above copyright notice and this permission notice appear in all
20  * copies.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
23  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
25  * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
26  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
27  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
28  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
29  * USE OR PERFORMANCE OF THIS SOFTWARE.
30  *
31  * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
32  * conceived and contributed by Rob Butler.
33  *
34  * Permission to use, copy, modify, and distribute this software for any
35  * purpose with or without fee is hereby granted, provided that the
36  * above copyright notice and this permission notice appear in all
37  * copies.
38  *
39  * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
40  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
42  * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
43  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
44  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
45  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
46  * USE OR PERFORMANCE OF THIS SOFTWARE.
47  */
48 
49 /*! \file dns/dlz.h */
50 
51 #ifndef DLZ_H
52 #define DLZ_H 1
53 
54 /*****
55 ***** Module Info
56 *****/
57 
58 /*
59  * DLZ Interface
60  *
61  * The DLZ interface allows zones to be looked up using a driver instead of
62  * Bind's default in memory zone table.
63  *
64  *
65  * Reliability:
66  *	No anticipated impact.
67  *
68  * Resources:
69  *
70  * Security:
71  *	No anticipated impact.
72  *
73  * Standards:
74  *	None.
75  */
76 
77 /*****
78 ***** Imports
79 *****/
80 
81 #include <stdbool.h>
82 
83 #include <isc/lang.h>
84 
85 #include <dns/clientinfo.h>
86 #include <dns/name.h>
87 #include <dns/types.h>
88 #include <dns/view.h>
89 
90 #include <dst/dst.h>
91 
92 ISC_LANG_BEGINDECLS
93 
94 /***
95  *** Types
96  ***/
97 
98 #define DNS_DLZ_MAGIC	   ISC_MAGIC('D', 'L', 'Z', 'D')
99 #define DNS_DLZ_VALID(dlz) ISC_MAGIC_VALID(dlz, DNS_DLZ_MAGIC)
100 
101 typedef isc_result_t (*dns_dlzallowzonexfr_t)(void *driverarg, void *dbdata,
102 					      isc_mem_t		*mctx,
103 					      dns_rdataclass_t	    rdclass,
104 					      const dns_name_t     *name,
105 					      const isc_sockaddr_t *clientaddr,
106 					      dns_db_t	       **dbp);
107 
108 /*%<
109  * Method prototype.  Drivers implementing the DLZ interface MUST
110  * supply an allow zone transfer method.  This method is called when
111  * the DNS server is performing a zone transfer query.  The driver's
112  * method should return ISC_R_SUCCESS and a database pointer to the
113  * name server if the zone is supported by the database, and zone
114  * transfer is allowed.  If the view's transfer acl should be used,
115  * then the driver's method should return ISC_R_DEFAULT.  Otherwise,
116  * it should return ISC_R_NOTFOUND if the zone is not supported by
117  * the database, or ISC_R_NOPERM if zone transfers are not allowed.
118  * If an error occurs, the result code should indicate the type of error.
119  */
120 
121 typedef isc_result_t (*dns_dlzcreate_t)(isc_mem_t *mctx, const char *dlzname,
122 					unsigned int argc, char *argv[],
123 					void *driverarg, void **dbdata);
124 
125 /*%<
126  * Method prototype.  Drivers implementing the DLZ interface MUST
127  * supply a create method.  This method is called when the DNS server
128  * is starting up and creating drivers for use later.
129  */
130 
131 typedef void (*dns_dlzdestroy_t)(void *driverarg, void **dbdata);
132 
133 /*%<
134  * Method prototype.  Drivers implementing the DLZ interface MUST
135  * supply a destroy method.  This method is called when the DNS server
136  * is shutting down and no longer needs the driver.
137  */
138 
139 typedef isc_result_t (*dns_dlzfindzone_t)(void *driverarg, void *dbdata,
140 					  isc_mem_t		    *mctx,
141 					  dns_rdataclass_t	   rdclass,
142 					  const dns_name_t	   *name,
143 					  dns_clientinfomethods_t *methods,
144 					  dns_clientinfo_t	   *clientinfo,
145 					  dns_db_t		   **dbp);
146 
147 /*%<
148  * Method prototype.  Drivers implementing the DLZ interface MUST
149  * supply a find zone method.  This method is called when the DNS
150  * server is performing a query.  The find zone method will be called
151  * with the longest possible name first, and continue to be called
152  * with successively shorter domain names, until any of the following
153  * occur:
154  *
155  * \li	1) a match is found, and the function returns (ISC_R_SUCCESS)
156  *
157  * \li	2) a problem occurs, and the functions returns anything other
158  *	   than (ISC_R_NOTFOUND)
159  * \li	3) we run out of domain name labels. I.E. we have tried the
160  *	   shortest domain name
161  * \li	4) the number of labels in the domain name is less than
162  *	   min_labels for dns_dlzfindzone
163  *
164  * The driver's find zone method should return ISC_R_SUCCESS and a
165  * database pointer to the name server if the zone is supported by the
166  * database.  Otherwise it will return ISC_R_NOTFOUND, and a null
167  * pointer if the zone is not supported.  If an error occurs it should
168  * return a result code indicating the type of error.
169  */
170 
171 typedef isc_result_t (*dns_dlzconfigure_t)(void *driverarg, void *dbdata,
172 					   dns_view_t  *view,
173 					   dns_dlzdb_t *dlzdb);
174 /*%<
175  * Method prototype.  Drivers implementing the DLZ interface may
176  * optionally supply a configure method. If supplied, this will be
177  * called immediately after the create method is called. The driver
178  * may call configuration functions during the configure call
179  */
180 
181 typedef bool (*dns_dlzssumatch_t)(const dns_name_t	   *signer,
182 				  const dns_name_t	   *name,
183 				  const isc_netaddr_t *tcpaddr,
184 				  dns_rdatatype_t type, const dst_key_t *key,
185 				  void *driverarg, void *dbdata);
186 /*%<
187  * Method prototype.  Drivers implementing the DLZ interface may
188  * optionally supply a ssumatch method. If supplied, this will be
189  * called to authorize update requests
190  */
191 
192 /*% the methods supplied by a DLZ driver */
193 typedef struct dns_dlzmethods {
194 	dns_dlzcreate_t	      create;
195 	dns_dlzdestroy_t      destroy;
196 	dns_dlzfindzone_t     findzone;
197 	dns_dlzallowzonexfr_t allowzonexfr;
198 	dns_dlzconfigure_t    configure;
199 	dns_dlzssumatch_t     ssumatch;
200 } dns_dlzmethods_t;
201 
202 /*% information about a DLZ driver */
203 struct dns_dlzimplementation {
204 	const char		   *name;
205 	const dns_dlzmethods_t *methods;
206 	isc_mem_t		  *mctx;
207 	void		     *driverarg;
208 	ISC_LINK(dns_dlzimplementation_t) link;
209 };
210 
211 typedef isc_result_t (*dlzconfigure_callback_t)(dns_view_t *, dns_dlzdb_t *,
212 						dns_zone_t *);
213 
214 /*% An instance of a DLZ driver */
215 struct dns_dlzdb {
216 	unsigned int		 magic;
217 	isc_mem_t		  *mctx;
218 	dns_dlzimplementation_t *implementation;
219 	void		     *dbdata;
220 	dlzconfigure_callback_t	 configure_callback;
221 	bool			 search;
222 	char		     *dlzname;
223 	ISC_LINK(dns_dlzdb_t) link;
224 	dns_ssutable_t *ssutable;
225 };
226 
227 /***
228  *** Method declarations
229  ***/
230 
231 isc_result_t
232 dns_dlzallowzonexfr(dns_view_t *view, const dns_name_t *name,
233 		    const isc_sockaddr_t *clientaddr, dns_db_t **dbp);
234 
235 /*%<
236  * This method is called when the DNS server is performing a zone
237  * transfer query.  It will call the DLZ driver's allow zone transfer
238  * method.
239  */
240 
241 isc_result_t
242 dns_dlzcreate(isc_mem_t *mctx, const char *dlzname, const char *drivername,
243 	      unsigned int argc, char *argv[], dns_dlzdb_t **dbp);
244 
245 /*%<
246  * This method is called when the DNS server is starting up and
247  * creating drivers for use later.  It will search the DLZ driver list
248  * for 'drivername' and return a DLZ driver via dbp if a match is
249  * found.  If the DLZ driver supplies a create method, this function
250  * will call it.
251  */
252 
253 void
254 dns_dlzdestroy(dns_dlzdb_t **dbp);
255 
256 /*%<
257  * This method is called when the DNS server is shutting down and no
258  * longer needs the driver.  If the DLZ driver supplies a destroy
259  * methods, this function will call it.
260  */
261 
262 isc_result_t
263 dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
264 		void *driverarg, isc_mem_t *mctx,
265 		dns_dlzimplementation_t **dlzimp);
266 
267 /*%<
268  * Register a dynamically loadable zones (DLZ) driver for the database
269  * type 'drivername', implemented by the functions in '*methods'.
270  *
271  * dlzimp must point to a NULL dlz_implementation_t pointer.  That is,
272  * dlzimp != NULL && *dlzimp == NULL.  It will be assigned a value that
273  * will later be used to identify the driver when deregistering it.
274  */
275 
276 isc_result_t
277 dns_dlzstrtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp);
278 
279 /*%<
280  * This method is called when the name server is starting up to parse
281  * the DLZ driver command line from named.conf.  Basically it splits
282  * up a string into and argc / argv.  The primary difference of this
283  * method is items between braces { } are considered only 1 word.  for
284  * example the command line "this is { one grouped phrase } and this
285  * isn't" would be parsed into:
286  *
287  * \li	argv[0]: "this"
288  * \li	argv[1]: "is"
289  * \li	argv{2]: " one grouped phrase "
290  * \li	argv[3]: "and"
291  * \li	argv[4]: "this"
292  * \li	argv{5}: "isn't"
293  *
294  * braces should NOT be nested, more than one grouping in the command
295  * line is allowed.  Notice, argv[2] has an extra space at the
296  * beginning and end.  Extra spaces are not stripped between a
297  * grouping.  You can do so in your driver if needed, or be sure not
298  * to put extra spaces before / after the braces.
299  */
300 
301 void
302 dns_dlzunregister(dns_dlzimplementation_t **dlzimp);
303 
304 /*%<
305  * Removes the dlz driver from the list of registered dlz drivers.
306  * There must be no active dlz drivers of this type when this function
307  * is called.
308  */
309 
310 typedef isc_result_t
311 dns_dlz_writeablezone_t(dns_view_t *view, dns_dlzdb_t *dlzdb,
312 			const char *zone_name);
313 dns_dlz_writeablezone_t dns_dlz_writeablezone;
314 /*%<
315  * creates a writeable DLZ zone. Must be called from within the
316  * configure() method of a DLZ driver.
317  */
318 
319 isc_result_t
320 dns_dlzconfigure(dns_view_t *view, dns_dlzdb_t *dlzdb,
321 		 dlzconfigure_callback_t callback);
322 /*%<
323  * call a DLZ drivers configure method, if supplied
324  */
325 
326 bool
327 dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase, const dns_name_t *signer,
328 		 const dns_name_t *name, const isc_netaddr_t *tcpaddr,
329 		 dns_rdatatype_t type, const dst_key_t *key);
330 /*%<
331  * call a DLZ drivers ssumatch method, if supplied. Otherwise return false
332  */
333 
334 ISC_LANG_ENDDECLS
335 
336 #endif /* DLZ_H */
337