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/sdlz.h */
50 
51 #ifndef SDLZ_H
52 #define SDLZ_H 1
53 
54 #include <inttypes.h>
55 #include <stdbool.h>
56 
57 #include <dns/clientinfo.h>
58 #include <dns/dlz.h>
59 
60 ISC_LANG_BEGINDECLS
61 
62 #define DNS_SDLZFLAG_THREADSAFE	   0x00000001U
63 #define DNS_SDLZFLAG_RELATIVEOWNER 0x00000002U
64 #define DNS_SDLZFLAG_RELATIVERDATA 0x00000004U
65 
66 /* A simple DLZ database. */
67 typedef struct dns_sdlz_db dns_sdlz_db_t;
68 
69 /* A simple DLZ database lookup in progress. */
70 typedef struct dns_sdlzlookup dns_sdlzlookup_t;
71 
72 /* A simple DLZ database traversal in progress. */
73 typedef struct dns_sdlzallnodes dns_sdlzallnodes_t;
74 
75 typedef isc_result_t (*dns_sdlzallnodesfunc_t)(const char *zone,
76 					       void *driverarg, void *dbdata,
77 					       dns_sdlzallnodes_t *allnodes);
78 /*%<
79  * Method prototype.  Drivers implementing the SDLZ interface may
80  * supply an all nodes method.  This method is called when the DNS
81  * server is performing a zone transfer query, after the allow zone
82  * transfer method has been called.  This method is only called if the
83  * allow zone transfer method returned ISC_R_SUCCESS.  This method and
84  * the allow zone transfer method are both required for zone transfers
85  * to be supported.  If the driver generates data dynamically (instead
86  * of searching in a database for it) it should not implement this
87  * function as a zone transfer would be meaningless.  A SDLZ driver
88  * does not have to implement an all nodes method.
89  */
90 
91 typedef isc_result_t (*dns_sdlzallowzonexfr_t)(void *driverarg, void *dbdata,
92 					       const char *name,
93 					       const char *client);
94 
95 /*%<
96  * Method prototype.  Drivers implementing the SDLZ interface may
97  * supply an allow zone transfer method.  This method is called when
98  * the DNS server is performing a zone transfer query, before the all
99  * nodes method can be called.  This method and the all node method
100  * are both required for zone transfers to be supported.  If the
101  * driver generates data dynamically (instead of searching in a
102  * database for it) it should not implement this function as a zone
103  * transfer would be meaningless.  A SDLZ driver does not have to
104  * implement an allow zone transfer method.
105  *
106  * This method should return ISC_R_SUCCESS if the zone is supported by
107  * the database and a zone transfer is allowed for the specified
108  * client.  If the zone is supported by the database, but zone
109  * transfers are not allowed for the specified client this method
110  * should return ISC_R_NOPERM..  Lastly the method should return
111  * ISC_R_NOTFOUND if the zone is not supported by the database.  If an
112  * error occurs it should return a result code indicating the type of
113  * error.
114  */
115 
116 typedef isc_result_t (*dns_sdlzauthorityfunc_t)(const char *zone,
117 						void *driverarg, void *dbdata,
118 						dns_sdlzlookup_t *lookup);
119 
120 /*%<
121  * Method prototype.  Drivers implementing the SDLZ interface may
122  * supply an authority method.  This method is called when the DNS
123  * server is performing a query, after both the find zone and lookup
124  * methods have been called.  This method is required if the lookup
125  * function does not supply authority information for the dns
126  * record. A SDLZ driver does not have to implement an authority
127  * method.
128  */
129 
130 typedef isc_result_t (*dns_sdlzcreate_t)(const char *dlzname, unsigned int argc,
131 					 char *argv[], void *driverarg,
132 					 void **dbdata);
133 
134 /*%<
135  * Method prototype.  Drivers implementing the SDLZ interface may
136  * supply a create method.  This method is called when the DNS server
137  * is starting up and creating drivers for use later. A SDLZ driver
138  * does not have to implement a create method.
139  */
140 
141 typedef void (*dns_sdlzdestroy_t)(void *driverarg, void *dbdata);
142 
143 /*%<
144  * Method prototype.  Drivers implementing the SDLZ interface may
145  * supply a destroy method.  This method is called when the DNS server
146  * is shutting down and no longer needs the driver.  A SDLZ driver does
147  * not have to implement a destroy method.
148  */
149 
150 typedef isc_result_t (*dns_sdlzfindzone_t)(void *driverarg, void *dbdata,
151 					   const char	      *name,
152 					   dns_clientinfomethods_t *methods,
153 					   dns_clientinfo_t	    *clientinfo);
154 /*%<
155  * Method prototype.  Drivers implementing the SDLZ interface MUST
156  * supply a find zone method.  This method is called when the DNS
157  * server is performing a query to to determine if 'name' is a
158  * supported dns zone.  The find zone method will be called with the
159  * longest possible name first, and continue to be called with
160  * successively shorter domain names, until any of the following
161  * occur:
162  *
163  * \li	1) the function returns (ISC_R_SUCCESS) indicating a zone name
164  *	   match.
165  *
166  * \li	2) a problem occurs, and the functions returns anything other than
167  *	   (ISC_R_NOTFOUND)
168  *
169  * \li	3) we run out of domain name labels. I.E. we have tried the
170  *	   shortest domain name
171  *
172  * \li	4) the number of labels in the domain name is less than min_labels
173  *	   for dns_dlzfindzone
174  *
175  * The driver's find zone method should return ISC_R_SUCCESS if the
176  * zone is supported by the database.  Otherwise it should return
177  * ISC_R_NOTFOUND, if the zone is not supported.  If an error occurs
178  * it should return a result code indicating the type of error.
179  */
180 
181 typedef isc_result_t (*dns_sdlzlookupfunc_t)(const char *zone, const char *name,
182 					     void *driverarg, void *dbdata,
183 					     dns_sdlzlookup_t	      *lookup,
184 					     dns_clientinfomethods_t *methods,
185 					     dns_clientinfo_t *clientinfo);
186 
187 /*%<
188  * Method prototype.  Drivers implementing the SDLZ interface MUST
189  * supply a lookup method.  This method is called when the
190  * DNS server is performing a query, after the find zone and before any
191  * other methods have been called.  This function returns DNS record
192  * information using the dns_sdlz_putrr and dns_sdlz_putsoa functions.
193  * If this function supplies authority information for the DNS record
194  * the authority method is not required.  If it does not, the
195  * authority function is required.
196  *
197  * The 'methods' and 'clientinfo' args allow an SDLZ driver to retrieve
198  * information about the querying client (such as source IP address)
199  * from the caller.
200  */
201 
202 typedef isc_result_t (*dns_sdlznewversion_t)(const char *zone, void *driverarg,
203 					     void *dbdata, void **versionp);
204 /*%<
205  * Method prototype.  Drivers implementing the SDLZ interface may
206  * supply a newversion method.  This method is called to start a
207  * write transaction on a zone and should only be implemented by
208  * writeable backends.
209  * When implemented, the driver should create a new transaction, and
210  * fill *versionp with a pointer to the transaction state. The
211  * closeversion function will be called to close the transaction.
212  */
213 
214 typedef void (*dns_sdlzcloseversion_t)(const char *zone, bool commit,
215 				       void *driverarg, void *dbdata,
216 				       void **versionp);
217 /*%<
218  * Method prototype.  Drivers implementing the SDLZ interface must
219  * supply a closeversion method if they supply a newversion method.
220  * When implemented, the driver should close the given transaction,
221  * committing changes if 'commit' is true. If 'commit' is not true
222  * then all changes should be discarded and the database rolled back.
223  * If the call is successful then *versionp should be set to NULL
224  */
225 
226 typedef isc_result_t (*dns_sdlzconfigure_t)(dns_view_t  *view,
227 					    dns_dlzdb_t *dlzdb, void *driverarg,
228 					    void *dbdata);
229 /*%<
230  * Method prototype.  Drivers implementing the SDLZ interface may
231  * supply a configure method. When supplied, it will be called
232  * immediately after the create method to give the driver a chance
233  * to configure writeable zones
234  */
235 
236 typedef bool (*dns_sdlzssumatch_t)(const char *signer, const char *name,
237 				   const char *tcpaddr, const char *type,
238 				   const char *key, uint32_t keydatalen,
239 				   unsigned char *keydata, void *driverarg,
240 				   void *dbdata);
241 
242 /*%<
243  * Method prototype.  Drivers implementing the SDLZ interface may
244  * supply a ssumatch method. If supplied, then ssumatch will be
245  * called to authorize any zone updates. The driver should return
246  * true to allow the update, and false to deny it. For a DLZ
247  * controlled zone, this is the only access control on updates.
248  */
249 
250 typedef isc_result_t (*dns_sdlzmodrdataset_t)(const char *name,
251 					      const char *rdatastr,
252 					      void *driverarg, void *dbdata,
253 					      void *version);
254 /*%<
255  * Method prototype.  Drivers implementing the SDLZ interface may
256  * supply addrdataset and subtractrdataset methods. If supplied, then these
257  * will be called when rdatasets are added/subtracted during
258  * updates. The version parameter comes from a call to the sdlz
259  * newversion() method from the driver. The rdataset parameter is a
260  * linearise string representation of the rdataset change. The format
261  * is the same as used by dig when displaying records. The fields are
262  * tab delimited.
263  */
264 
265 typedef isc_result_t (*dns_sdlzdelrdataset_t)(const char *name,
266 					      const char *type, void *driverarg,
267 					      void *dbdata, void *version);
268 /*%<
269  * Method prototype.  Drivers implementing the SDLZ interface may
270  * supply a delrdataset method. If supplied, then this
271  * function will be called when rdatasets are deleted during
272  * updates. The call should remove all rdatasets of the given type for
273  * the specified name.
274  */
275 
276 typedef struct dns_sdlzmethods {
277 	dns_sdlzcreate_t	create;
278 	dns_sdlzdestroy_t	destroy;
279 	dns_sdlzfindzone_t	findzone;
280 	dns_sdlzlookupfunc_t	lookup;
281 	dns_sdlzauthorityfunc_t authority;
282 	dns_sdlzallnodesfunc_t	allnodes;
283 	dns_sdlzallowzonexfr_t	allowzonexfr;
284 	dns_sdlznewversion_t	newversion;
285 	dns_sdlzcloseversion_t	closeversion;
286 	dns_sdlzconfigure_t	configure;
287 	dns_sdlzssumatch_t	ssumatch;
288 	dns_sdlzmodrdataset_t	addrdataset;
289 	dns_sdlzmodrdataset_t	subtractrdataset;
290 	dns_sdlzdelrdataset_t	delrdataset;
291 } dns_sdlzmethods_t;
292 
293 isc_result_t
294 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
295 		 void *driverarg, unsigned int flags, isc_mem_t *mctx,
296 		 dns_sdlzimplementation_t **sdlzimp);
297 /*%<
298  * Register a dynamically loadable zones (dlz) driver for the database
299  * type 'drivername', implemented by the functions in '*methods'.
300  *
301  * sdlzimp must point to a NULL dns_sdlzimplementation_t pointer.
302  * That is, sdlzimp != NULL && *sdlzimp == NULL.  It will be assigned
303  * a value that will later be used to identify the driver when
304  * deregistering it.
305  */
306 
307 void
308 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp);
309 
310 /*%<
311  * Removes the sdlz driver from the list of registered sdlz drivers.
312  * There must be no active sdlz drivers of this type when this
313  * function is called.
314  */
315 
316 typedef isc_result_t
317 dns_sdlz_putnamedrr_t(dns_sdlzallnodes_t *allnodes, const char *name,
318 		      const char *type, dns_ttl_t ttl, const char *data);
319 dns_sdlz_putnamedrr_t dns_sdlz_putnamedrr;
320 
321 /*%<
322  * Add a single resource record to the allnodes structure to be later
323  * parsed into a zone transfer response.
324  */
325 
326 typedef isc_result_t
327 dns_sdlz_putrr_t(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
328 		 const char *data);
329 dns_sdlz_putrr_t dns_sdlz_putrr;
330 /*%<
331  * Add a single resource record to the lookup structure to be later
332  * parsed into a query response.
333  */
334 
335 typedef isc_result_t
336 		  dns_sdlz_putsoa_t(dns_sdlzlookup_t *lookup, const char *mname,
337 				    const char *rname, uint32_t serial);
338 dns_sdlz_putsoa_t dns_sdlz_putsoa;
339 /*%<
340  * This function may optionally be called from the 'authority'
341  * callback to simplify construction of the SOA record for 'zone'.  It
342  * will provide a SOA listing 'mname' as as the master server and
343  * 'rname' as the responsible person mailbox.  It is the
344  * responsibility of the driver to increment the serial number between
345  * responses if necessary.  All other SOA fields will have reasonable
346  * default values.
347  */
348 
349 typedef isc_result_t
350 dns_sdlz_setdb_t(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
351 		 const dns_name_t *name, dns_db_t **dbp);
352 dns_sdlz_setdb_t dns_sdlz_setdb;
353 /*%<
354  * Create the database pointers for a writeable SDLZ zone
355  */
356 
357 ISC_LANG_ENDDECLS
358 
359 #endif /* SDLZ_H */
360