sdlz.c revision 1.1.1.7 1 1.1 christos /* $NetBSD: sdlz.c,v 1.1.1.7 2021/02/19 16:37:13 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 1.1 christos *
6 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public
7 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this
8 1.1.1.7 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 1.1 christos *
10 1.1 christos * See the COPYRIGHT file distributed with this work for additional
11 1.1 christos * information regarding copyright ownership.
12 1.1 christos */
13 1.1 christos
14 1.1 christos /*
15 1.1 christos * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting (at) nlnet.nl.
16 1.1 christos *
17 1.1 christos * Permission to use, copy, modify, and distribute this software for any
18 1.1 christos * purpose with or without fee is hereby granted, provided that the
19 1.1 christos * above copyright notice and this permission notice appear in all
20 1.1 christos * copies.
21 1.1 christos *
22 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
23 1.1 christos * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
24 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
25 1.1 christos * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
26 1.1 christos * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
27 1.1 christos * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
28 1.1 christos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
29 1.1 christos * USE OR PERFORMANCE OF THIS SOFTWARE.
30 1.1 christos *
31 1.1 christos * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
32 1.1 christos * conceived and contributed by Rob Butler.
33 1.1 christos *
34 1.1 christos * Permission to use, copy, modify, and distribute this software for any
35 1.1 christos * purpose with or without fee is hereby granted, provided that the
36 1.1 christos * above copyright notice and this permission notice appear in all
37 1.1 christos * copies.
38 1.1 christos *
39 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
40 1.1 christos * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
41 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
42 1.1 christos * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
43 1.1 christos * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
44 1.1 christos * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
45 1.1 christos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
46 1.1 christos * USE OR PERFORMANCE OF THIS SOFTWARE.
47 1.1 christos */
48 1.1 christos
49 1.1 christos /*! \file */
50 1.1 christos
51 1.1.1.2 christos #include <inttypes.h>
52 1.1.1.2 christos #include <stdbool.h>
53 1.1 christos #include <string.h>
54 1.1 christos
55 1.1 christos #include <isc/buffer.h>
56 1.1 christos #include <isc/lex.h>
57 1.1 christos #include <isc/log.h>
58 1.1 christos #include <isc/magic.h>
59 1.1 christos #include <isc/mem.h>
60 1.1 christos #include <isc/once.h>
61 1.1 christos #include <isc/print.h>
62 1.1 christos #include <isc/region.h>
63 1.1.1.5 christos #include <isc/rwlock.h>
64 1.1.1.5 christos #include <isc/string.h>
65 1.1.1.5 christos #include <isc/util.h>
66 1.1 christos
67 1.1 christos #include <dns/callbacks.h>
68 1.1 christos #include <dns/db.h>
69 1.1 christos #include <dns/dbiterator.h>
70 1.1 christos #include <dns/dlz.h>
71 1.1 christos #include <dns/fixedname.h>
72 1.1 christos #include <dns/log.h>
73 1.1.1.5 christos #include <dns/master.h>
74 1.1 christos #include <dns/rdata.h>
75 1.1 christos #include <dns/rdatalist.h>
76 1.1 christos #include <dns/rdataset.h>
77 1.1 christos #include <dns/rdatasetiter.h>
78 1.1 christos #include <dns/rdatatype.h>
79 1.1 christos #include <dns/result.h>
80 1.1 christos #include <dns/sdlz.h>
81 1.1 christos #include <dns/types.h>
82 1.1 christos
83 1.1 christos #include "rdatalist_p.h"
84 1.1 christos
85 1.1 christos /*
86 1.1 christos * Private Types
87 1.1 christos */
88 1.1 christos
89 1.1 christos struct dns_sdlzimplementation {
90 1.1.1.5 christos const dns_sdlzmethods_t *methods;
91 1.1.1.5 christos isc_mem_t *mctx;
92 1.1.1.5 christos void *driverarg;
93 1.1.1.5 christos unsigned int flags;
94 1.1.1.5 christos isc_mutex_t driverlock;
95 1.1.1.5 christos dns_dlzimplementation_t *dlz_imp;
96 1.1 christos };
97 1.1 christos
98 1.1 christos struct dns_sdlz_db {
99 1.1 christos /* Unlocked */
100 1.1.1.5 christos dns_db_t common;
101 1.1.1.5 christos void *dbdata;
102 1.1.1.5 christos dns_sdlzimplementation_t *dlzimp;
103 1.1.1.5 christos
104 1.1.1.5 christos /* Atomic */
105 1.1.1.5 christos isc_refcount_t references;
106 1.1.1.5 christos
107 1.1 christos /* Locked */
108 1.1.1.5 christos dns_dbversion_t *future_version;
109 1.1.1.5 christos int dummy_version;
110 1.1 christos };
111 1.1 christos
112 1.1 christos struct dns_sdlzlookup {
113 1.1 christos /* Unlocked */
114 1.1.1.5 christos unsigned int magic;
115 1.1.1.5 christos dns_sdlz_db_t *sdlz;
116 1.1.1.5 christos ISC_LIST(dns_rdatalist_t) lists;
117 1.1.1.5 christos ISC_LIST(isc_buffer_t) buffers;
118 1.1.1.5 christos dns_name_t *name;
119 1.1.1.5 christos ISC_LINK(dns_sdlzlookup_t) link;
120 1.1.1.5 christos dns_rdatacallbacks_t callbacks;
121 1.1.1.5 christos
122 1.1.1.5 christos /* Atomic */
123 1.1.1.5 christos isc_refcount_t references;
124 1.1 christos };
125 1.1 christos
126 1.1 christos typedef struct dns_sdlzlookup dns_sdlznode_t;
127 1.1 christos
128 1.1 christos struct dns_sdlzallnodes {
129 1.1.1.5 christos dns_dbiterator_t common;
130 1.1.1.5 christos ISC_LIST(dns_sdlznode_t) nodelist;
131 1.1.1.5 christos dns_sdlznode_t *current;
132 1.1.1.5 christos dns_sdlznode_t *origin;
133 1.1 christos };
134 1.1 christos
135 1.1 christos typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
136 1.1 christos
137 1.1 christos typedef struct sdlz_rdatasetiter {
138 1.1.1.5 christos dns_rdatasetiter_t common;
139 1.1.1.5 christos dns_rdatalist_t *current;
140 1.1 christos } sdlz_rdatasetiter_t;
141 1.1 christos
142 1.1.1.5 christos #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
143 1.1 christos
144 1.1 christos /*
145 1.1 christos * Note that "impmagic" is not the first four bytes of the struct, so
146 1.1 christos * ISC_MAGIC_VALID cannot be used.
147 1.1 christos */
148 1.1 christos
149 1.1.1.5 christos #define VALID_SDLZDB(sdlzdb) \
150 1.1.1.5 christos ((sdlzdb) != NULL && (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
151 1.1 christos
152 1.1.1.5 christos #define SDLZLOOKUP_MAGIC ISC_MAGIC('D', 'L', 'Z', 'L')
153 1.1.1.5 christos #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
154 1.1 christos #define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn)
155 1.1 christos
156 1.1 christos /* These values are taken from RFC 1537 */
157 1.1.1.5 christos #define SDLZ_DEFAULT_REFRESH 28800U /* 8 hours */
158 1.1.1.5 christos #define SDLZ_DEFAULT_RETRY 7200U /* 2 hours */
159 1.1.1.5 christos #define SDLZ_DEFAULT_EXPIRE 604800U /* 7 days */
160 1.1.1.5 christos #define SDLZ_DEFAULT_MINIMUM 86400U /* 1 day */
161 1.1 christos
162 1.1 christos /* This is a reasonable value */
163 1.1.1.5 christos #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
164 1.1 christos
165 1.1 christos #ifdef __COVERITY__
166 1.1.1.5 christos #define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
167 1.1 christos #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
168 1.1.1.5 christos #else /* ifdef __COVERITY__ */
169 1.1.1.5 christos #define MAYBE_LOCK(imp) \
170 1.1.1.5 christos do { \
171 1.1.1.5 christos unsigned int flags = imp->flags; \
172 1.1 christos if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
173 1.1.1.5 christos LOCK(&imp->driverlock); \
174 1.1 christos } while (0)
175 1.1 christos
176 1.1.1.5 christos #define MAYBE_UNLOCK(imp) \
177 1.1.1.5 christos do { \
178 1.1.1.5 christos unsigned int flags = imp->flags; \
179 1.1 christos if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
180 1.1.1.5 christos UNLOCK(&imp->driverlock); \
181 1.1 christos } while (0)
182 1.1.1.5 christos #endif /* ifdef __COVERITY__ */
183 1.1 christos
184 1.1 christos /*
185 1.1 christos * Forward references.
186 1.1 christos */
187 1.1.1.5 christos static isc_result_t
188 1.1.1.5 christos getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
189 1.1.1.5 christos unsigned int options, dns_clientinfomethods_t *methods,
190 1.1.1.5 christos dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep);
191 1.1.1.5 christos
192 1.1.1.5 christos static void
193 1.1.1.5 christos list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
194 1.1.1.5 christos dns_rdataset_t *rdataset);
195 1.1.1.5 christos
196 1.1.1.5 christos static void
197 1.1.1.5 christos detachnode(dns_db_t *db, dns_dbnode_t **targetp);
198 1.1.1.5 christos
199 1.1.1.5 christos static void
200 1.1.1.5 christos dbiterator_destroy(dns_dbiterator_t **iteratorp);
201 1.1.1.5 christos static isc_result_t
202 1.1.1.5 christos dbiterator_first(dns_dbiterator_t *iterator);
203 1.1.1.5 christos static isc_result_t
204 1.1.1.5 christos dbiterator_last(dns_dbiterator_t *iterator);
205 1.1.1.5 christos static isc_result_t
206 1.1.1.5 christos dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name);
207 1.1.1.5 christos static isc_result_t
208 1.1.1.5 christos dbiterator_prev(dns_dbiterator_t *iterator);
209 1.1.1.5 christos static isc_result_t
210 1.1.1.5 christos dbiterator_next(dns_dbiterator_t *iterator);
211 1.1.1.5 christos static isc_result_t
212 1.1.1.5 christos dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
213 1.1.1.5 christos dns_name_t *name);
214 1.1.1.5 christos static isc_result_t
215 1.1.1.5 christos dbiterator_pause(dns_dbiterator_t *iterator);
216 1.1.1.5 christos static isc_result_t
217 1.1.1.5 christos dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
218 1.1 christos
219 1.1 christos static dns_dbiteratormethods_t dbiterator_methods = {
220 1.1.1.5 christos dbiterator_destroy, dbiterator_first, dbiterator_last,
221 1.1.1.5 christos dbiterator_seek, dbiterator_prev, dbiterator_next,
222 1.1.1.5 christos dbiterator_current, dbiterator_pause, dbiterator_origin
223 1.1 christos };
224 1.1 christos
225 1.1 christos /*
226 1.1 christos * Utility functions
227 1.1 christos */
228 1.1 christos
229 1.1 christos /*
230 1.1 christos * Log a message at the given level
231 1.1 christos */
232 1.1 christos static void
233 1.1 christos sdlz_log(int level, const char *fmt, ...) {
234 1.1 christos va_list ap;
235 1.1 christos va_start(ap, fmt);
236 1.1.1.5 christos isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ,
237 1.1.1.5 christos ISC_LOG_DEBUG(level), fmt, ap);
238 1.1 christos va_end(ap);
239 1.1 christos }
240 1.1 christos
241 1.1 christos /*% Converts the input string to lowercase, in place. */
242 1.1 christos static void
243 1.1 christos dns_sdlz_tolower(char *str) {
244 1.1 christos unsigned int len = strlen(str);
245 1.1 christos unsigned int i;
246 1.1 christos
247 1.1 christos for (i = 0; i < len; i++) {
248 1.1.1.5 christos if (str[i] >= 'A' && str[i] <= 'Z') {
249 1.1 christos str[i] += 32;
250 1.1.1.5 christos }
251 1.1 christos }
252 1.1 christos }
253 1.1 christos
254 1.1 christos static inline unsigned int
255 1.1 christos initial_size(const char *data) {
256 1.1 christos unsigned int len = (strlen(data) / 64) + 1;
257 1.1 christos return (len * 64 + 64);
258 1.1 christos }
259 1.1 christos
260 1.1 christos /*
261 1.1 christos * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
262 1.1 christos * driver interface. See the SDB driver interface documentation for more info.
263 1.1 christos */
264 1.1 christos
265 1.1 christos static void
266 1.1 christos rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
267 1.1.1.5 christos sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)(*iteratorp);
268 1.1 christos
269 1.1 christos detachnode(sdlziterator->common.db, &sdlziterator->common.node);
270 1.1 christos isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
271 1.1 christos sizeof(sdlz_rdatasetiter_t));
272 1.1 christos *iteratorp = NULL;
273 1.1 christos }
274 1.1 christos
275 1.1 christos static isc_result_t
276 1.1 christos rdatasetiter_first(dns_rdatasetiter_t *iterator) {
277 1.1 christos sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
278 1.1 christos dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
279 1.1 christos
280 1.1.1.5 christos if (ISC_LIST_EMPTY(sdlznode->lists)) {
281 1.1 christos return (ISC_R_NOMORE);
282 1.1.1.5 christos }
283 1.1 christos sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
284 1.1 christos return (ISC_R_SUCCESS);
285 1.1 christos }
286 1.1 christos
287 1.1 christos static isc_result_t
288 1.1 christos rdatasetiter_next(dns_rdatasetiter_t *iterator) {
289 1.1 christos sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
290 1.1 christos
291 1.1 christos sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
292 1.1.1.5 christos if (sdlziterator->current == NULL) {
293 1.1 christos return (ISC_R_NOMORE);
294 1.1.1.5 christos } else {
295 1.1 christos return (ISC_R_SUCCESS);
296 1.1.1.5 christos }
297 1.1 christos }
298 1.1 christos
299 1.1 christos static void
300 1.1 christos rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
301 1.1 christos sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
302 1.1 christos
303 1.1 christos list_tordataset(sdlziterator->current, iterator->db, iterator->node,
304 1.1 christos rdataset);
305 1.1 christos }
306 1.1 christos
307 1.1 christos static dns_rdatasetitermethods_t rdatasetiter_methods = {
308 1.1.1.5 christos rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next,
309 1.1 christos rdatasetiter_current
310 1.1 christos };
311 1.1 christos
312 1.1 christos /*
313 1.1 christos * DB routines. These methods were "borrowed" from the SDB driver interface.
314 1.1 christos * See the SDB driver interface documentation for more info.
315 1.1 christos */
316 1.1 christos
317 1.1 christos static void
318 1.1 christos attach(dns_db_t *source, dns_db_t **targetp) {
319 1.1.1.5 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)source;
320 1.1 christos
321 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
322 1.1 christos
323 1.1.1.5 christos isc_refcount_increment(&sdlz->references);
324 1.1 christos
325 1.1 christos *targetp = source;
326 1.1 christos }
327 1.1 christos
328 1.1 christos static void
329 1.1 christos destroy(dns_sdlz_db_t *sdlz) {
330 1.1 christos sdlz->common.magic = 0;
331 1.1 christos sdlz->common.impmagic = 0;
332 1.1 christos
333 1.1.1.5 christos dns_name_free(&sdlz->common.origin, sdlz->common.mctx);
334 1.1 christos
335 1.1.1.5 christos isc_refcount_destroy(&sdlz->references);
336 1.1.1.5 christos isc_mem_putanddetach(&sdlz->common.mctx, sdlz, sizeof(dns_sdlz_db_t));
337 1.1 christos }
338 1.1 christos
339 1.1 christos static void
340 1.1 christos detach(dns_db_t **dbp) {
341 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
342 1.1 christos
343 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
344 1.1 christos
345 1.1 christos *dbp = NULL;
346 1.1.1.5 christos
347 1.1.1.5 christos if (isc_refcount_decrement(&sdlz->references) == 1) {
348 1.1.1.5 christos destroy(sdlz);
349 1.1.1.5 christos }
350 1.1 christos }
351 1.1 christos
352 1.1 christos static isc_result_t
353 1.1 christos beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
354 1.1 christos UNUSED(db);
355 1.1 christos UNUSED(callbacks);
356 1.1 christos return (ISC_R_NOTIMPLEMENTED);
357 1.1 christos }
358 1.1 christos
359 1.1 christos static isc_result_t
360 1.1 christos endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
361 1.1 christos UNUSED(db);
362 1.1 christos UNUSED(callbacks);
363 1.1 christos return (ISC_R_NOTIMPLEMENTED);
364 1.1 christos }
365 1.1 christos
366 1.1 christos static isc_result_t
367 1.1 christos dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
368 1.1.1.5 christos dns_masterformat_t masterformat) {
369 1.1 christos UNUSED(db);
370 1.1 christos UNUSED(version);
371 1.1 christos UNUSED(filename);
372 1.1 christos UNUSED(masterformat);
373 1.1 christos return (ISC_R_NOTIMPLEMENTED);
374 1.1 christos }
375 1.1 christos
376 1.1 christos static void
377 1.1 christos currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
378 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
379 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
380 1.1 christos REQUIRE(versionp != NULL && *versionp == NULL);
381 1.1 christos
382 1.1.1.5 christos *versionp = (void *)&sdlz->dummy_version;
383 1.1 christos return;
384 1.1 christos }
385 1.1 christos
386 1.1 christos static isc_result_t
387 1.1 christos newversion(dns_db_t *db, dns_dbversion_t **versionp) {
388 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
389 1.1 christos char origin[DNS_NAME_MAXTEXT + 1];
390 1.1 christos isc_result_t result;
391 1.1 christos
392 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
393 1.1 christos
394 1.1.1.5 christos if (sdlz->dlzimp->methods->newversion == NULL) {
395 1.1 christos return (ISC_R_NOTIMPLEMENTED);
396 1.1.1.5 christos }
397 1.1 christos
398 1.1 christos dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
399 1.1 christos
400 1.1.1.5 christos result = sdlz->dlzimp->methods->newversion(
401 1.1.1.5 christos origin, sdlz->dlzimp->driverarg, sdlz->dbdata, versionp);
402 1.1 christos if (result != ISC_R_SUCCESS) {
403 1.1 christos sdlz_log(ISC_LOG_ERROR,
404 1.1.1.5 christos "sdlz newversion on origin %s failed : %s", origin,
405 1.1.1.5 christos isc_result_totext(result));
406 1.1 christos return (result);
407 1.1 christos }
408 1.1 christos
409 1.1 christos sdlz->future_version = *versionp;
410 1.1 christos return (ISC_R_SUCCESS);
411 1.1 christos }
412 1.1 christos
413 1.1 christos static void
414 1.1.1.5 christos attachversion(dns_db_t *db, dns_dbversion_t *source,
415 1.1.1.5 christos dns_dbversion_t **targetp) {
416 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
417 1.1 christos
418 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
419 1.1 christos REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
420 1.1 christos
421 1.1 christos *targetp = source;
422 1.1 christos }
423 1.1 christos
424 1.1 christos static void
425 1.1.1.2 christos closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
426 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
427 1.1 christos char origin[DNS_NAME_MAXTEXT + 1];
428 1.1 christos
429 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
430 1.1 christos REQUIRE(versionp != NULL);
431 1.1 christos
432 1.1 christos if (*versionp == (void *)&sdlz->dummy_version) {
433 1.1 christos *versionp = NULL;
434 1.1 christos return;
435 1.1 christos }
436 1.1 christos
437 1.1 christos REQUIRE(*versionp == sdlz->future_version);
438 1.1 christos REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
439 1.1 christos
440 1.1 christos dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
441 1.1 christos
442 1.1 christos sdlz->dlzimp->methods->closeversion(origin, commit,
443 1.1 christos sdlz->dlzimp->driverarg,
444 1.1 christos sdlz->dbdata, versionp);
445 1.1.1.5 christos if (*versionp != NULL) {
446 1.1.1.5 christos sdlz_log(ISC_LOG_ERROR, "sdlz closeversion on origin %s failed",
447 1.1.1.5 christos origin);
448 1.1.1.5 christos }
449 1.1 christos
450 1.1 christos sdlz->future_version = NULL;
451 1.1 christos }
452 1.1 christos
453 1.1 christos static isc_result_t
454 1.1 christos createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
455 1.1 christos dns_sdlznode_t *node;
456 1.1 christos
457 1.1 christos node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
458 1.1 christos
459 1.1 christos node->sdlz = NULL;
460 1.1 christos attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
461 1.1 christos ISC_LIST_INIT(node->lists);
462 1.1 christos ISC_LIST_INIT(node->buffers);
463 1.1 christos ISC_LINK_INIT(node, link);
464 1.1 christos node->name = NULL;
465 1.1 christos dns_rdatacallbacks_init(&node->callbacks);
466 1.1.1.5 christos
467 1.1.1.5 christos isc_refcount_init(&node->references, 1);
468 1.1 christos node->magic = SDLZLOOKUP_MAGIC;
469 1.1 christos
470 1.1 christos *nodep = node;
471 1.1 christos return (ISC_R_SUCCESS);
472 1.1 christos }
473 1.1 christos
474 1.1 christos static void
475 1.1 christos destroynode(dns_sdlznode_t *node) {
476 1.1 christos dns_rdatalist_t *list;
477 1.1 christos dns_rdata_t *rdata;
478 1.1 christos isc_buffer_t *b;
479 1.1 christos dns_sdlz_db_t *sdlz;
480 1.1 christos dns_db_t *db;
481 1.1 christos isc_mem_t *mctx;
482 1.1 christos
483 1.1.1.5 christos isc_refcount_destroy(&node->references);
484 1.1.1.5 christos
485 1.1 christos sdlz = node->sdlz;
486 1.1 christos mctx = sdlz->common.mctx;
487 1.1 christos
488 1.1 christos while (!ISC_LIST_EMPTY(node->lists)) {
489 1.1 christos list = ISC_LIST_HEAD(node->lists);
490 1.1 christos while (!ISC_LIST_EMPTY(list->rdata)) {
491 1.1 christos rdata = ISC_LIST_HEAD(list->rdata);
492 1.1 christos ISC_LIST_UNLINK(list->rdata, rdata, link);
493 1.1 christos isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
494 1.1 christos }
495 1.1 christos ISC_LIST_UNLINK(node->lists, list, link);
496 1.1 christos isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
497 1.1 christos }
498 1.1 christos
499 1.1 christos while (!ISC_LIST_EMPTY(node->buffers)) {
500 1.1 christos b = ISC_LIST_HEAD(node->buffers);
501 1.1 christos ISC_LIST_UNLINK(node->buffers, b, link);
502 1.1 christos isc_buffer_free(&b);
503 1.1 christos }
504 1.1 christos
505 1.1 christos if (node->name != NULL) {
506 1.1 christos dns_name_free(node->name, mctx);
507 1.1 christos isc_mem_put(mctx, node->name, sizeof(dns_name_t));
508 1.1 christos }
509 1.1.1.5 christos
510 1.1 christos node->magic = 0;
511 1.1 christos isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
512 1.1 christos db = &sdlz->common;
513 1.1 christos detach(&db);
514 1.1 christos }
515 1.1 christos
516 1.1 christos static isc_result_t
517 1.1.1.2 christos getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
518 1.1 christos unsigned int options, dns_clientinfomethods_t *methods,
519 1.1.1.5 christos dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) {
520 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
521 1.1 christos dns_sdlznode_t *node = NULL;
522 1.1 christos isc_result_t result;
523 1.1 christos isc_buffer_t b;
524 1.1 christos char namestr[DNS_NAME_MAXTEXT + 1];
525 1.1 christos isc_buffer_t b2;
526 1.1 christos char zonestr[DNS_NAME_MAXTEXT + 1];
527 1.1.1.2 christos bool isorigin;
528 1.1 christos dns_sdlzauthorityfunc_t authority;
529 1.1 christos
530 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
531 1.1 christos REQUIRE(nodep != NULL && *nodep == NULL);
532 1.1 christos
533 1.1 christos if (sdlz->dlzimp->methods->newversion == NULL) {
534 1.1.1.6 christos REQUIRE(!create);
535 1.1 christos }
536 1.1 christos
537 1.1 christos isc_buffer_init(&b, namestr, sizeof(namestr));
538 1.1 christos if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
539 1.1 christos dns_name_t relname;
540 1.1 christos unsigned int labels;
541 1.1 christos
542 1.1 christos labels = dns_name_countlabels(name) -
543 1.1 christos dns_name_countlabels(&sdlz->common.origin);
544 1.1 christos dns_name_init(&relname, NULL);
545 1.1 christos dns_name_getlabelsequence(name, 0, labels, &relname);
546 1.1.1.2 christos result = dns_name_totext(&relname, true, &b);
547 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
548 1.1 christos return (result);
549 1.1.1.5 christos }
550 1.1 christos } else {
551 1.1.1.2 christos result = dns_name_totext(name, true, &b);
552 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
553 1.1 christos return (result);
554 1.1.1.5 christos }
555 1.1 christos }
556 1.1 christos isc_buffer_putuint8(&b, 0);
557 1.1 christos
558 1.1 christos isc_buffer_init(&b2, zonestr, sizeof(zonestr));
559 1.1.1.2 christos result = dns_name_totext(&sdlz->common.origin, true, &b2);
560 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
561 1.1 christos return (result);
562 1.1.1.5 christos }
563 1.1 christos isc_buffer_putuint8(&b2, 0);
564 1.1 christos
565 1.1 christos result = createnode(sdlz, &node);
566 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
567 1.1 christos return (result);
568 1.1.1.5 christos }
569 1.1 christos
570 1.1 christos isorigin = dns_name_equal(name, &sdlz->common.origin);
571 1.1 christos
572 1.1 christos /* make sure strings are always lowercase */
573 1.1 christos dns_sdlz_tolower(zonestr);
574 1.1 christos dns_sdlz_tolower(namestr);
575 1.1 christos
576 1.1 christos MAYBE_LOCK(sdlz->dlzimp);
577 1.1 christos
578 1.1 christos /* try to lookup the host (namestr) */
579 1.1.1.5 christos result = sdlz->dlzimp->methods->lookup(
580 1.1.1.5 christos zonestr, namestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node,
581 1.1.1.5 christos methods, clientinfo);
582 1.1 christos
583 1.1 christos /*
584 1.1 christos * If the name was not found and DNS_DBFIND_NOWILD is not
585 1.1 christos * set, then we try to find a wildcard entry.
586 1.1 christos *
587 1.1 christos * If DNS_DBFIND_NOZONECUT is set and there are multiple
588 1.1 christos * levels between the host and the zone origin, we also look
589 1.1 christos * for wildcards at each level.
590 1.1 christos */
591 1.1 christos if (result == ISC_R_NOTFOUND && !create &&
592 1.1.1.5 christos (options & DNS_DBFIND_NOWILD) == 0) {
593 1.1 christos unsigned int i, dlabels, nlabels;
594 1.1 christos
595 1.1 christos nlabels = dns_name_countlabels(name);
596 1.1 christos dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin);
597 1.1 christos for (i = 0; i < dlabels; i++) {
598 1.1 christos char wildstr[DNS_NAME_MAXTEXT + 1];
599 1.1 christos dns_fixedname_t fixed;
600 1.1 christos const dns_name_t *wild;
601 1.1 christos
602 1.1 christos dns_fixedname_init(&fixed);
603 1.1.1.3 christos if (i == dlabels - 1) {
604 1.1 christos wild = dns_wildcardname;
605 1.1.1.3 christos } else {
606 1.1 christos dns_name_t *fname;
607 1.1 christos fname = dns_fixedname_name(&fixed);
608 1.1.1.5 christos dns_name_getlabelsequence(
609 1.1.1.5 christos name, i + 1, dlabels - i - 1, fname);
610 1.1.1.5 christos result = dns_name_concatenate(
611 1.1.1.5 christos dns_wildcardname, fname, fname, NULL);
612 1.1.1.3 christos if (result != ISC_R_SUCCESS) {
613 1.1.1.3 christos MAYBE_UNLOCK(sdlz->dlzimp);
614 1.1 christos return (result);
615 1.1.1.3 christos }
616 1.1 christos wild = fname;
617 1.1 christos }
618 1.1 christos
619 1.1 christos isc_buffer_init(&b, wildstr, sizeof(wildstr));
620 1.1.1.2 christos result = dns_name_totext(wild, true, &b);
621 1.1.1.3 christos if (result != ISC_R_SUCCESS) {
622 1.1.1.3 christos MAYBE_UNLOCK(sdlz->dlzimp);
623 1.1 christos return (result);
624 1.1.1.3 christos }
625 1.1 christos isc_buffer_putuint8(&b, 0);
626 1.1 christos
627 1.1.1.5 christos result = sdlz->dlzimp->methods->lookup(
628 1.1.1.5 christos zonestr, wildstr, sdlz->dlzimp->driverarg,
629 1.1.1.5 christos sdlz->dbdata, node, methods, clientinfo);
630 1.1.1.5 christos if (result == ISC_R_SUCCESS) {
631 1.1 christos break;
632 1.1.1.5 christos }
633 1.1 christos }
634 1.1 christos }
635 1.1 christos
636 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp);
637 1.1 christos
638 1.1.1.5 christos if (result == ISC_R_NOTFOUND && (isorigin || create)) {
639 1.1 christos result = ISC_R_SUCCESS;
640 1.1.1.5 christos }
641 1.1 christos
642 1.1 christos if (result != ISC_R_SUCCESS) {
643 1.1.1.7 christos isc_refcount_decrementz(&node->references);
644 1.1 christos destroynode(node);
645 1.1 christos return (result);
646 1.1 christos }
647 1.1 christos
648 1.1 christos if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
649 1.1 christos MAYBE_LOCK(sdlz->dlzimp);
650 1.1 christos authority = sdlz->dlzimp->methods->authority;
651 1.1 christos result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
652 1.1 christos sdlz->dbdata, node);
653 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp);
654 1.1.1.5 christos if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
655 1.1.1.7 christos isc_refcount_decrementz(&node->references);
656 1.1 christos destroynode(node);
657 1.1 christos return (result);
658 1.1 christos }
659 1.1 christos }
660 1.1 christos
661 1.1 christos if (node->name == NULL) {
662 1.1.1.5 christos node->name = isc_mem_get(sdlz->common.mctx, sizeof(dns_name_t));
663 1.1 christos dns_name_init(node->name, NULL);
664 1.1.1.5 christos dns_name_dup(name, sdlz->common.mctx, node->name);
665 1.1 christos }
666 1.1 christos
667 1.1 christos *nodep = node;
668 1.1 christos return (ISC_R_SUCCESS);
669 1.1 christos }
670 1.1 christos
671 1.1 christos static isc_result_t
672 1.1.1.2 christos findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
673 1.1 christos dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
674 1.1.1.5 christos dns_dbnode_t **nodep) {
675 1.1 christos return (getnodedata(db, name, create, 0, methods, clientinfo, nodep));
676 1.1 christos }
677 1.1 christos
678 1.1 christos static isc_result_t
679 1.1.1.2 christos findnode(dns_db_t *db, const dns_name_t *name, bool create,
680 1.1.1.5 christos dns_dbnode_t **nodep) {
681 1.1 christos return (getnodedata(db, name, create, 0, NULL, NULL, nodep));
682 1.1 christos }
683 1.1 christos
684 1.1 christos static isc_result_t
685 1.1 christos findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
686 1.1 christos isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
687 1.1.1.2 christos dns_name_t *dcname, dns_rdataset_t *rdataset,
688 1.1.1.5 christos dns_rdataset_t *sigrdataset) {
689 1.1 christos UNUSED(db);
690 1.1 christos UNUSED(name);
691 1.1 christos UNUSED(options);
692 1.1 christos UNUSED(now);
693 1.1 christos UNUSED(nodep);
694 1.1 christos UNUSED(foundname);
695 1.1.1.2 christos UNUSED(dcname);
696 1.1 christos UNUSED(rdataset);
697 1.1 christos UNUSED(sigrdataset);
698 1.1 christos
699 1.1 christos return (ISC_R_NOTIMPLEMENTED);
700 1.1 christos }
701 1.1 christos
702 1.1 christos static void
703 1.1 christos attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
704 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
705 1.1 christos dns_sdlznode_t *node = (dns_sdlznode_t *)source;
706 1.1 christos
707 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
708 1.1 christos
709 1.1 christos UNUSED(sdlz);
710 1.1 christos
711 1.1.1.5 christos isc_refcount_increment(&node->references);
712 1.1 christos
713 1.1 christos *targetp = source;
714 1.1 christos }
715 1.1 christos
716 1.1 christos static void
717 1.1 christos detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
718 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
719 1.1 christos dns_sdlznode_t *node;
720 1.1 christos
721 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
722 1.1 christos REQUIRE(targetp != NULL && *targetp != NULL);
723 1.1 christos
724 1.1 christos UNUSED(sdlz);
725 1.1 christos
726 1.1 christos node = (dns_sdlznode_t *)(*targetp);
727 1.1.1.5 christos *targetp = NULL;
728 1.1 christos
729 1.1.1.5 christos if (isc_refcount_decrement(&node->references) == 1) {
730 1.1 christos destroynode(node);
731 1.1.1.5 christos }
732 1.1 christos }
733 1.1 christos
734 1.1 christos static isc_result_t
735 1.1 christos expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
736 1.1 christos UNUSED(db);
737 1.1 christos UNUSED(node);
738 1.1 christos UNUSED(now);
739 1.1 christos INSIST(0);
740 1.1.1.2 christos ISC_UNREACHABLE();
741 1.1 christos }
742 1.1 christos
743 1.1 christos static void
744 1.1 christos printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
745 1.1 christos UNUSED(db);
746 1.1 christos UNUSED(node);
747 1.1 christos UNUSED(out);
748 1.1 christos return;
749 1.1 christos }
750 1.1 christos
751 1.1 christos static isc_result_t
752 1.1.1.5 christos createiterator(dns_db_t *db, unsigned int options,
753 1.1.1.5 christos dns_dbiterator_t **iteratorp) {
754 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
755 1.1 christos sdlz_dbiterator_t *sdlziter;
756 1.1 christos isc_result_t result;
757 1.1 christos isc_buffer_t b;
758 1.1 christos char zonestr[DNS_NAME_MAXTEXT + 1];
759 1.1 christos
760 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
761 1.1 christos
762 1.1.1.5 christos if (sdlz->dlzimp->methods->allnodes == NULL) {
763 1.1 christos return (ISC_R_NOTIMPLEMENTED);
764 1.1.1.5 christos }
765 1.1 christos
766 1.1 christos if ((options & DNS_DB_NSEC3ONLY) != 0 ||
767 1.1.1.5 christos (options & DNS_DB_NONSEC3) != 0) {
768 1.1.1.5 christos return (ISC_R_NOTIMPLEMENTED);
769 1.1.1.5 christos }
770 1.1 christos
771 1.1 christos isc_buffer_init(&b, zonestr, sizeof(zonestr));
772 1.1.1.2 christos result = dns_name_totext(&sdlz->common.origin, true, &b);
773 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
774 1.1 christos return (result);
775 1.1.1.5 christos }
776 1.1 christos isc_buffer_putuint8(&b, 0);
777 1.1 christos
778 1.1 christos sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
779 1.1 christos
780 1.1 christos sdlziter->common.methods = &dbiterator_methods;
781 1.1 christos sdlziter->common.db = NULL;
782 1.1 christos dns_db_attach(db, &sdlziter->common.db);
783 1.1.1.5 christos sdlziter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
784 1.1.1.5 christos 0);
785 1.1 christos sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
786 1.1 christos ISC_LIST_INIT(sdlziter->nodelist);
787 1.1 christos sdlziter->current = NULL;
788 1.1 christos sdlziter->origin = NULL;
789 1.1 christos
790 1.1 christos /* make sure strings are always lowercase */
791 1.1 christos dns_sdlz_tolower(zonestr);
792 1.1 christos
793 1.1 christos MAYBE_LOCK(sdlz->dlzimp);
794 1.1.1.5 christos result = sdlz->dlzimp->methods->allnodes(
795 1.1.1.5 christos zonestr, sdlz->dlzimp->driverarg, sdlz->dbdata, sdlziter);
796 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp);
797 1.1 christos if (result != ISC_R_SUCCESS) {
798 1.1 christos dns_dbiterator_t *iter = &sdlziter->common;
799 1.1 christos dbiterator_destroy(&iter);
800 1.1 christos return (result);
801 1.1 christos }
802 1.1 christos
803 1.1 christos if (sdlziter->origin != NULL) {
804 1.1 christos ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
805 1.1 christos ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
806 1.1 christos }
807 1.1 christos
808 1.1 christos *iteratorp = (dns_dbiterator_t *)sdlziter;
809 1.1 christos
810 1.1 christos return (ISC_R_SUCCESS);
811 1.1 christos }
812 1.1 christos
813 1.1 christos static isc_result_t
814 1.1 christos findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
815 1.1.1.5 christos dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
816 1.1.1.5 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
817 1.1.1.5 christos REQUIRE(VALID_SDLZNODE(node));
818 1.1 christos dns_rdatalist_t *list;
819 1.1 christos dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
820 1.1 christos
821 1.1 christos UNUSED(db);
822 1.1 christos UNUSED(version);
823 1.1 christos UNUSED(covers);
824 1.1 christos UNUSED(now);
825 1.1 christos UNUSED(sigrdataset);
826 1.1 christos
827 1.1.1.5 christos if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) {
828 1.1 christos return (ISC_R_NOTIMPLEMENTED);
829 1.1.1.5 christos }
830 1.1 christos
831 1.1 christos list = ISC_LIST_HEAD(sdlznode->lists);
832 1.1 christos while (list != NULL) {
833 1.1.1.5 christos if (list->type == type) {
834 1.1 christos break;
835 1.1.1.5 christos }
836 1.1 christos list = ISC_LIST_NEXT(list, link);
837 1.1 christos }
838 1.1.1.5 christos if (list == NULL) {
839 1.1 christos return (ISC_R_NOTFOUND);
840 1.1.1.5 christos }
841 1.1 christos
842 1.1 christos list_tordataset(list, db, node, rdataset);
843 1.1 christos
844 1.1 christos return (ISC_R_SUCCESS);
845 1.1 christos }
846 1.1 christos
847 1.1 christos static isc_result_t
848 1.1 christos findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
849 1.1 christos dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
850 1.1 christos dns_dbnode_t **nodep, dns_name_t *foundname,
851 1.1 christos dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
852 1.1.1.5 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
853 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
854 1.1 christos dns_dbnode_t *node = NULL;
855 1.1 christos dns_fixedname_t fname;
856 1.1 christos dns_rdataset_t xrdataset;
857 1.1 christos dns_name_t *xname;
858 1.1 christos unsigned int nlabels, olabels;
859 1.1 christos isc_result_t result;
860 1.1 christos unsigned int i;
861 1.1 christos
862 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
863 1.1 christos REQUIRE(nodep == NULL || *nodep == NULL);
864 1.1.1.5 christos REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
865 1.1 christos version == sdlz->future_version);
866 1.1 christos
867 1.1 christos UNUSED(sdlz);
868 1.1 christos
869 1.1.1.5 christos if (!dns_name_issubdomain(name, &db->origin)) {
870 1.1 christos return (DNS_R_NXDOMAIN);
871 1.1.1.5 christos }
872 1.1 christos
873 1.1 christos olabels = dns_name_countlabels(&db->origin);
874 1.1 christos nlabels = dns_name_countlabels(name);
875 1.1 christos
876 1.1 christos xname = dns_fixedname_initname(&fname);
877 1.1 christos
878 1.1 christos if (rdataset == NULL) {
879 1.1 christos dns_rdataset_init(&xrdataset);
880 1.1 christos rdataset = &xrdataset;
881 1.1 christos }
882 1.1 christos
883 1.1 christos result = DNS_R_NXDOMAIN;
884 1.1 christos
885 1.1 christos /*
886 1.1 christos * If we're not walking down searching for zone
887 1.1 christos * cuts, we can cut straight to the chase
888 1.1 christos */
889 1.1 christos if ((options & DNS_DBFIND_NOZONECUT) != 0) {
890 1.1 christos i = nlabels;
891 1.1 christos goto search;
892 1.1 christos }
893 1.1 christos
894 1.1 christos for (i = olabels; i <= nlabels; i++) {
895 1.1.1.5 christos search:
896 1.1 christos /*
897 1.1 christos * Look up the next label.
898 1.1 christos */
899 1.1 christos dns_name_getlabelsequence(name, nlabels - i, i, xname);
900 1.1.1.5 christos result = getnodedata(db, xname, false, options, methods,
901 1.1.1.5 christos clientinfo, &node);
902 1.1 christos if (result == ISC_R_NOTFOUND) {
903 1.1 christos result = DNS_R_NXDOMAIN;
904 1.1 christos continue;
905 1.1.1.5 christos } else if (result != ISC_R_SUCCESS) {
906 1.1 christos break;
907 1.1.1.5 christos }
908 1.1 christos
909 1.1 christos /*
910 1.1 christos * Look for a DNAME at the current label, unless this is
911 1.1 christos * the qname.
912 1.1 christos */
913 1.1 christos if (i < nlabels) {
914 1.1 christos result = findrdataset(db, node, version,
915 1.1 christos dns_rdatatype_dname, 0, now,
916 1.1 christos rdataset, sigrdataset);
917 1.1 christos if (result == ISC_R_SUCCESS) {
918 1.1 christos result = DNS_R_DNAME;
919 1.1 christos break;
920 1.1 christos }
921 1.1 christos }
922 1.1 christos
923 1.1 christos /*
924 1.1 christos * Look for an NS at the current label, unless this is the
925 1.1 christos * origin, glue is ok, or there are known to be no zone cuts.
926 1.1 christos */
927 1.1 christos if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 &&
928 1.1 christos (options & DNS_DBFIND_NOZONECUT) == 0)
929 1.1 christos {
930 1.1 christos result = findrdataset(db, node, version,
931 1.1 christos dns_rdatatype_ns, 0, now,
932 1.1 christos rdataset, sigrdataset);
933 1.1 christos
934 1.1.1.5 christos if (result == ISC_R_SUCCESS && i == nlabels &&
935 1.1.1.5 christos type == dns_rdatatype_any) {
936 1.1 christos result = DNS_R_ZONECUT;
937 1.1 christos dns_rdataset_disassociate(rdataset);
938 1.1 christos if (sigrdataset != NULL &&
939 1.1.1.5 christos dns_rdataset_isassociated(sigrdataset)) {
940 1.1 christos dns_rdataset_disassociate(sigrdataset);
941 1.1.1.5 christos }
942 1.1 christos break;
943 1.1 christos } else if (result == ISC_R_SUCCESS) {
944 1.1 christos result = DNS_R_DELEGATION;
945 1.1 christos break;
946 1.1 christos }
947 1.1 christos }
948 1.1 christos
949 1.1 christos /*
950 1.1 christos * If the current name is not the qname, add another label
951 1.1 christos * and try again.
952 1.1 christos */
953 1.1 christos if (i < nlabels) {
954 1.1.1.5 christos detachnode(db, &node);
955 1.1 christos node = NULL;
956 1.1 christos continue;
957 1.1 christos }
958 1.1 christos
959 1.1 christos /*
960 1.1 christos * If we're looking for ANY, we're done.
961 1.1 christos */
962 1.1 christos if (type == dns_rdatatype_any) {
963 1.1 christos result = ISC_R_SUCCESS;
964 1.1 christos break;
965 1.1 christos }
966 1.1 christos
967 1.1 christos /*
968 1.1 christos * Look for the qtype.
969 1.1 christos */
970 1.1.1.5 christos result = findrdataset(db, node, version, type, 0, now, rdataset,
971 1.1.1.5 christos sigrdataset);
972 1.1.1.5 christos if (result == ISC_R_SUCCESS) {
973 1.1 christos break;
974 1.1.1.5 christos }
975 1.1 christos
976 1.1 christos /*
977 1.1 christos * Look for a CNAME
978 1.1 christos */
979 1.1 christos if (type != dns_rdatatype_cname) {
980 1.1 christos result = findrdataset(db, node, version,
981 1.1 christos dns_rdatatype_cname, 0, now,
982 1.1 christos rdataset, sigrdataset);
983 1.1 christos if (result == ISC_R_SUCCESS) {
984 1.1 christos result = DNS_R_CNAME;
985 1.1 christos break;
986 1.1 christos }
987 1.1 christos }
988 1.1 christos
989 1.1 christos result = DNS_R_NXRRSET;
990 1.1 christos break;
991 1.1 christos }
992 1.1 christos
993 1.1.1.5 christos if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
994 1.1 christos dns_rdataset_disassociate(rdataset);
995 1.1.1.5 christos }
996 1.1 christos
997 1.1 christos if (foundname != NULL) {
998 1.1.1.4 christos dns_name_copynf(xname, foundname);
999 1.1 christos }
1000 1.1 christos
1001 1.1.1.5 christos if (nodep != NULL) {
1002 1.1 christos *nodep = node;
1003 1.1.1.5 christos } else if (node != NULL) {
1004 1.1 christos detachnode(db, &node);
1005 1.1.1.5 christos }
1006 1.1 christos
1007 1.1 christos return (result);
1008 1.1 christos }
1009 1.1 christos
1010 1.1 christos static isc_result_t
1011 1.1 christos find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
1012 1.1 christos dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
1013 1.1.1.5 christos dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
1014 1.1.1.5 christos dns_rdataset_t *sigrdataset) {
1015 1.1.1.5 christos return (findext(db, name, version, type, options, now, nodep, foundname,
1016 1.1.1.5 christos NULL, NULL, rdataset, sigrdataset));
1017 1.1 christos }
1018 1.1 christos
1019 1.1 christos static isc_result_t
1020 1.1 christos allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1021 1.1.1.5 christos isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) {
1022 1.1.1.5 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1023 1.1 christos sdlz_rdatasetiter_t *iterator;
1024 1.1 christos
1025 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
1026 1.1 christos
1027 1.1.1.5 christos REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
1028 1.1 christos version == sdlz->future_version);
1029 1.1 christos
1030 1.1 christos UNUSED(version);
1031 1.1 christos UNUSED(now);
1032 1.1 christos
1033 1.1 christos iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
1034 1.1 christos
1035 1.1 christos iterator->common.magic = DNS_RDATASETITER_MAGIC;
1036 1.1 christos iterator->common.methods = &rdatasetiter_methods;
1037 1.1 christos iterator->common.db = db;
1038 1.1 christos iterator->common.node = NULL;
1039 1.1 christos attachnode(db, node, &iterator->common.node);
1040 1.1 christos iterator->common.version = version;
1041 1.1 christos iterator->common.now = now;
1042 1.1 christos
1043 1.1 christos *iteratorp = (dns_rdatasetiter_t *)iterator;
1044 1.1 christos
1045 1.1 christos return (ISC_R_SUCCESS);
1046 1.1 christos }
1047 1.1 christos
1048 1.1 christos static isc_result_t
1049 1.1 christos modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1050 1.1 christos dns_rdataset_t *rdataset, unsigned int options,
1051 1.1.1.5 christos dns_sdlzmodrdataset_t mod_function) {
1052 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1053 1.1 christos dns_master_style_t *style = NULL;
1054 1.1 christos isc_result_t result;
1055 1.1 christos isc_buffer_t *buffer = NULL;
1056 1.1 christos isc_mem_t *mctx;
1057 1.1 christos dns_sdlznode_t *sdlznode;
1058 1.1 christos char *rdatastr = NULL;
1059 1.1 christos char name[DNS_NAME_MAXTEXT + 1];
1060 1.1 christos
1061 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
1062 1.1 christos
1063 1.1.1.5 christos if (mod_function == NULL) {
1064 1.1 christos return (ISC_R_NOTIMPLEMENTED);
1065 1.1.1.5 christos }
1066 1.1 christos
1067 1.1 christos sdlznode = (dns_sdlznode_t *)node;
1068 1.1 christos
1069 1.1 christos UNUSED(options);
1070 1.1 christos
1071 1.1 christos dns_name_format(sdlznode->name, name, sizeof(name));
1072 1.1 christos
1073 1.1 christos mctx = sdlz->common.mctx;
1074 1.1 christos
1075 1.1.1.5 christos isc_buffer_allocate(mctx, &buffer, 1024);
1076 1.1 christos
1077 1.1.1.5 christos result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, 0xffffffff,
1078 1.1.1.5 christos mctx);
1079 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1080 1.1 christos goto cleanup;
1081 1.1.1.5 christos }
1082 1.1 christos
1083 1.1.1.5 christos result = dns_master_rdatasettotext(sdlznode->name, rdataset, style,
1084 1.1.1.5 christos NULL, buffer);
1085 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1086 1.1 christos goto cleanup;
1087 1.1.1.5 christos }
1088 1.1 christos
1089 1.1 christos if (isc_buffer_usedlength(buffer) < 1) {
1090 1.1 christos result = ISC_R_BADADDRESSFORM;
1091 1.1 christos goto cleanup;
1092 1.1 christos }
1093 1.1 christos
1094 1.1 christos rdatastr = isc_buffer_base(buffer);
1095 1.1 christos if (rdatastr == NULL) {
1096 1.1 christos result = ISC_R_NOMEMORY;
1097 1.1 christos goto cleanup;
1098 1.1 christos }
1099 1.1 christos rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
1100 1.1 christos
1101 1.1 christos MAYBE_LOCK(sdlz->dlzimp);
1102 1.1 christos result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
1103 1.1 christos sdlz->dbdata, version);
1104 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp);
1105 1.1 christos
1106 1.1 christos cleanup:
1107 1.1 christos isc_buffer_free(&buffer);
1108 1.1.1.5 christos if (style != NULL) {
1109 1.1 christos dns_master_styledestroy(&style, mctx);
1110 1.1.1.5 christos }
1111 1.1 christos
1112 1.1 christos return (result);
1113 1.1 christos }
1114 1.1 christos
1115 1.1 christos static isc_result_t
1116 1.1 christos addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1117 1.1 christos isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1118 1.1.1.5 christos dns_rdataset_t *addedrdataset) {
1119 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1120 1.1 christos isc_result_t result;
1121 1.1 christos
1122 1.1 christos UNUSED(now);
1123 1.1 christos UNUSED(addedrdataset);
1124 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
1125 1.1 christos
1126 1.1.1.5 christos if (sdlz->dlzimp->methods->addrdataset == NULL) {
1127 1.1 christos return (ISC_R_NOTIMPLEMENTED);
1128 1.1.1.5 christos }
1129 1.1 christos
1130 1.1 christos result = modrdataset(db, node, version, rdataset, options,
1131 1.1 christos sdlz->dlzimp->methods->addrdataset);
1132 1.1 christos return (result);
1133 1.1 christos }
1134 1.1 christos
1135 1.1 christos static isc_result_t
1136 1.1 christos subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1137 1.1 christos dns_rdataset_t *rdataset, unsigned int options,
1138 1.1.1.5 christos dns_rdataset_t *newrdataset) {
1139 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1140 1.1 christos isc_result_t result;
1141 1.1 christos
1142 1.1 christos UNUSED(newrdataset);
1143 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
1144 1.1 christos
1145 1.1 christos if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
1146 1.1 christos return (ISC_R_NOTIMPLEMENTED);
1147 1.1 christos }
1148 1.1 christos
1149 1.1 christos result = modrdataset(db, node, version, rdataset, options,
1150 1.1 christos sdlz->dlzimp->methods->subtractrdataset);
1151 1.1 christos return (result);
1152 1.1 christos }
1153 1.1 christos
1154 1.1 christos static isc_result_t
1155 1.1 christos deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1156 1.1.1.5 christos dns_rdatatype_t type, dns_rdatatype_t covers) {
1157 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1158 1.1 christos char name[DNS_NAME_MAXTEXT + 1];
1159 1.1 christos char b_type[DNS_RDATATYPE_FORMATSIZE];
1160 1.1 christos dns_sdlznode_t *sdlznode;
1161 1.1 christos isc_result_t result;
1162 1.1 christos
1163 1.1 christos UNUSED(covers);
1164 1.1 christos
1165 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
1166 1.1 christos
1167 1.1.1.5 christos if (sdlz->dlzimp->methods->delrdataset == NULL) {
1168 1.1 christos return (ISC_R_NOTIMPLEMENTED);
1169 1.1.1.5 christos }
1170 1.1 christos
1171 1.1 christos sdlznode = (dns_sdlznode_t *)node;
1172 1.1 christos dns_name_format(sdlznode->name, name, sizeof(name));
1173 1.1 christos dns_rdatatype_format(type, b_type, sizeof(b_type));
1174 1.1 christos
1175 1.1 christos MAYBE_LOCK(sdlz->dlzimp);
1176 1.1.1.5 christos result = sdlz->dlzimp->methods->delrdataset(
1177 1.1.1.5 christos name, b_type, sdlz->dlzimp->driverarg, sdlz->dbdata, version);
1178 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp);
1179 1.1 christos
1180 1.1 christos return (result);
1181 1.1 christos }
1182 1.1 christos
1183 1.1.1.2 christos static bool
1184 1.1 christos issecure(dns_db_t *db) {
1185 1.1 christos UNUSED(db);
1186 1.1 christos
1187 1.1.1.2 christos return (false);
1188 1.1 christos }
1189 1.1 christos
1190 1.1 christos static unsigned int
1191 1.1 christos nodecount(dns_db_t *db) {
1192 1.1 christos UNUSED(db);
1193 1.1 christos
1194 1.1 christos return (0);
1195 1.1 christos }
1196 1.1 christos
1197 1.1.1.2 christos static bool
1198 1.1 christos ispersistent(dns_db_t *db) {
1199 1.1 christos UNUSED(db);
1200 1.1.1.2 christos return (true);
1201 1.1 christos }
1202 1.1 christos
1203 1.1 christos static void
1204 1.1.1.2 christos overmem(dns_db_t *db, bool over) {
1205 1.1 christos UNUSED(db);
1206 1.1 christos UNUSED(over);
1207 1.1 christos }
1208 1.1 christos
1209 1.1 christos static void
1210 1.1 christos settask(dns_db_t *db, isc_task_t *task) {
1211 1.1 christos UNUSED(db);
1212 1.1 christos UNUSED(task);
1213 1.1 christos }
1214 1.1 christos
1215 1.1 christos /*
1216 1.1 christos * getoriginnode() is used by the update code to find the
1217 1.1 christos * dns_rdatatype_dnskey record for a zone
1218 1.1 christos */
1219 1.1 christos static isc_result_t
1220 1.1 christos getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
1221 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1222 1.1 christos isc_result_t result;
1223 1.1 christos
1224 1.1 christos REQUIRE(VALID_SDLZDB(sdlz));
1225 1.1.1.5 christos if (sdlz->dlzimp->methods->newversion == NULL) {
1226 1.1 christos return (ISC_R_NOTIMPLEMENTED);
1227 1.1.1.5 christos }
1228 1.1 christos
1229 1.1.1.5 christos result = getnodedata(db, &sdlz->common.origin, false, 0, NULL, NULL,
1230 1.1.1.5 christos nodep);
1231 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1232 1.1 christos sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
1233 1.1 christos isc_result_totext(result));
1234 1.1.1.5 christos }
1235 1.1 christos return (result);
1236 1.1 christos }
1237 1.1 christos
1238 1.1 christos static dns_dbmethods_t sdlzdb_methods = {
1239 1.1 christos attach,
1240 1.1 christos detach,
1241 1.1 christos beginload,
1242 1.1 christos endload,
1243 1.1.1.5 christos NULL, /* serialize */
1244 1.1 christos dump,
1245 1.1 christos currentversion,
1246 1.1 christos newversion,
1247 1.1 christos attachversion,
1248 1.1 christos closeversion,
1249 1.1 christos findnode,
1250 1.1 christos find,
1251 1.1 christos findzonecut,
1252 1.1 christos attachnode,
1253 1.1 christos detachnode,
1254 1.1 christos expirenode,
1255 1.1 christos printnode,
1256 1.1 christos createiterator,
1257 1.1 christos findrdataset,
1258 1.1 christos allrdatasets,
1259 1.1 christos addrdataset,
1260 1.1 christos subtractrdataset,
1261 1.1 christos deleterdataset,
1262 1.1 christos issecure,
1263 1.1 christos nodecount,
1264 1.1 christos ispersistent,
1265 1.1 christos overmem,
1266 1.1 christos settask,
1267 1.1 christos getoriginnode,
1268 1.1.1.5 christos NULL, /* transfernode */
1269 1.1.1.5 christos NULL, /* getnsec3parameters */
1270 1.1.1.5 christos NULL, /* findnsec3node */
1271 1.1.1.5 christos NULL, /* setsigningtime */
1272 1.1.1.5 christos NULL, /* getsigningtime */
1273 1.1.1.5 christos NULL, /* resigned */
1274 1.1.1.5 christos NULL, /* isdnssec */
1275 1.1.1.5 christos NULL, /* getrrsetstats */
1276 1.1.1.5 christos NULL, /* rpz_attach */
1277 1.1.1.5 christos NULL, /* rpz_ready */
1278 1.1 christos findnodeext,
1279 1.1 christos findext,
1280 1.1.1.5 christos NULL, /* setcachestats */
1281 1.1.1.5 christos NULL, /* hashsize */
1282 1.1.1.5 christos NULL, /* nodefullname */
1283 1.1.1.5 christos NULL, /* getsize */
1284 1.1.1.5 christos NULL, /* setservestalettl */
1285 1.1.1.5 christos NULL, /* getservestalettl */
1286 1.1.1.7 christos NULL, /* setservestalerefresh */
1287 1.1.1.7 christos NULL, /* getservestalerefresh */
1288 1.1.1.7 christos NULL, /* setgluecachestats */
1289 1.1.1.7 christos NULL /* adjusthashsize */
1290 1.1 christos };
1291 1.1 christos
1292 1.1 christos /*
1293 1.1 christos * Database Iterator Methods. These methods were "borrowed" from the SDB
1294 1.1 christos * driver interface. See the SDB driver interface documentation for more info.
1295 1.1 christos */
1296 1.1 christos
1297 1.1 christos static void
1298 1.1 christos dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1299 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1300 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1301 1.1 christos
1302 1.1 christos while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1303 1.1 christos dns_sdlznode_t *node;
1304 1.1 christos node = ISC_LIST_HEAD(sdlziter->nodelist);
1305 1.1 christos ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
1306 1.1.1.7 christos isc_refcount_decrementz(&node->references);
1307 1.1 christos destroynode(node);
1308 1.1 christos }
1309 1.1 christos
1310 1.1 christos dns_db_detach(&sdlziter->common.db);
1311 1.1 christos isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1312 1.1 christos
1313 1.1 christos *iteratorp = NULL;
1314 1.1 christos }
1315 1.1 christos
1316 1.1 christos static isc_result_t
1317 1.1 christos dbiterator_first(dns_dbiterator_t *iterator) {
1318 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1319 1.1 christos
1320 1.1 christos sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1321 1.1.1.5 christos if (sdlziter->current == NULL) {
1322 1.1 christos return (ISC_R_NOMORE);
1323 1.1.1.5 christos } else {
1324 1.1 christos return (ISC_R_SUCCESS);
1325 1.1.1.5 christos }
1326 1.1 christos }
1327 1.1 christos
1328 1.1 christos static isc_result_t
1329 1.1 christos dbiterator_last(dns_dbiterator_t *iterator) {
1330 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1331 1.1 christos
1332 1.1 christos sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
1333 1.1.1.5 christos if (sdlziter->current == NULL) {
1334 1.1 christos return (ISC_R_NOMORE);
1335 1.1.1.5 christos } else {
1336 1.1 christos return (ISC_R_SUCCESS);
1337 1.1.1.5 christos }
1338 1.1 christos }
1339 1.1 christos
1340 1.1 christos static isc_result_t
1341 1.1 christos dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
1342 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1343 1.1 christos
1344 1.1 christos sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1345 1.1 christos while (sdlziter->current != NULL) {
1346 1.1.1.5 christos if (dns_name_equal(sdlziter->current->name, name)) {
1347 1.1 christos return (ISC_R_SUCCESS);
1348 1.1.1.5 christos }
1349 1.1 christos sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1350 1.1 christos }
1351 1.1 christos return (ISC_R_NOTFOUND);
1352 1.1 christos }
1353 1.1 christos
1354 1.1 christos static isc_result_t
1355 1.1 christos dbiterator_prev(dns_dbiterator_t *iterator) {
1356 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1357 1.1 christos
1358 1.1 christos sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
1359 1.1.1.5 christos if (sdlziter->current == NULL) {
1360 1.1 christos return (ISC_R_NOMORE);
1361 1.1.1.5 christos } else {
1362 1.1 christos return (ISC_R_SUCCESS);
1363 1.1.1.5 christos }
1364 1.1 christos }
1365 1.1 christos
1366 1.1 christos static isc_result_t
1367 1.1 christos dbiterator_next(dns_dbiterator_t *iterator) {
1368 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1369 1.1 christos
1370 1.1 christos sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1371 1.1.1.5 christos if (sdlziter->current == NULL) {
1372 1.1 christos return (ISC_R_NOMORE);
1373 1.1.1.5 christos } else {
1374 1.1 christos return (ISC_R_SUCCESS);
1375 1.1.1.5 christos }
1376 1.1 christos }
1377 1.1 christos
1378 1.1 christos static isc_result_t
1379 1.1 christos dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1380 1.1.1.5 christos dns_name_t *name) {
1381 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1382 1.1 christos
1383 1.1 christos attachnode(iterator->db, sdlziter->current, nodep);
1384 1.1.1.4 christos if (name != NULL) {
1385 1.1.1.4 christos dns_name_copynf(sdlziter->current->name, name);
1386 1.1.1.4 christos return (ISC_R_SUCCESS);
1387 1.1.1.4 christos }
1388 1.1 christos return (ISC_R_SUCCESS);
1389 1.1 christos }
1390 1.1 christos
1391 1.1 christos static isc_result_t
1392 1.1 christos dbiterator_pause(dns_dbiterator_t *iterator) {
1393 1.1 christos UNUSED(iterator);
1394 1.1 christos return (ISC_R_SUCCESS);
1395 1.1 christos }
1396 1.1 christos
1397 1.1 christos static isc_result_t
1398 1.1 christos dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1399 1.1 christos UNUSED(iterator);
1400 1.1.1.4 christos dns_name_copynf(dns_rootname, name);
1401 1.1.1.4 christos return (ISC_R_SUCCESS);
1402 1.1 christos }
1403 1.1 christos
1404 1.1 christos /*
1405 1.1 christos * Rdataset Methods. These methods were "borrowed" from the SDB driver
1406 1.1 christos * interface. See the SDB driver interface documentation for more info.
1407 1.1 christos */
1408 1.1 christos
1409 1.1 christos static void
1410 1.1 christos disassociate(dns_rdataset_t *rdataset) {
1411 1.1 christos dns_dbnode_t *node = rdataset->private5;
1412 1.1.1.5 christos dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1413 1.1.1.5 christos dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1414 1.1 christos
1415 1.1 christos detachnode(db, &node);
1416 1.1 christos isc__rdatalist_disassociate(rdataset);
1417 1.1 christos }
1418 1.1 christos
1419 1.1 christos static void
1420 1.1 christos rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1421 1.1 christos dns_dbnode_t *node = source->private5;
1422 1.1.1.5 christos dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1423 1.1.1.5 christos dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1424 1.1 christos dns_dbnode_t *tempdb = NULL;
1425 1.1 christos
1426 1.1 christos isc__rdatalist_clone(source, target);
1427 1.1 christos attachnode(db, node, &tempdb);
1428 1.1 christos source->private5 = tempdb;
1429 1.1 christos }
1430 1.1 christos
1431 1.1 christos static dns_rdatasetmethods_t rdataset_methods = {
1432 1.1 christos disassociate,
1433 1.1 christos isc__rdatalist_first,
1434 1.1 christos isc__rdatalist_next,
1435 1.1 christos isc__rdatalist_current,
1436 1.1 christos rdataset_clone,
1437 1.1 christos isc__rdatalist_count,
1438 1.1 christos isc__rdatalist_addnoqname,
1439 1.1 christos isc__rdatalist_getnoqname,
1440 1.1 christos NULL, /* addclosest */
1441 1.1 christos NULL, /* getclosest */
1442 1.1 christos NULL, /* settrust */
1443 1.1 christos NULL, /* expire */
1444 1.1 christos NULL, /* clearprefetch */
1445 1.1 christos NULL, /* setownercase */
1446 1.1 christos NULL, /* getownercase */
1447 1.1 christos NULL /* addglue */
1448 1.1 christos };
1449 1.1 christos
1450 1.1 christos static void
1451 1.1.1.5 christos list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
1452 1.1.1.5 christos dns_rdataset_t *rdataset) {
1453 1.1 christos /*
1454 1.1 christos * The sdlz rdataset is an rdatalist with some additions.
1455 1.1 christos * - private1 & private2 are used by the rdatalist.
1456 1.1 christos * - private3 & private 4 are unused.
1457 1.1 christos * - private5 is the node.
1458 1.1 christos */
1459 1.1 christos
1460 1.1 christos /* This should never fail. */
1461 1.1 christos RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1462 1.1 christos ISC_R_SUCCESS);
1463 1.1 christos
1464 1.1 christos rdataset->methods = &rdataset_methods;
1465 1.1 christos dns_db_attachnode(db, node, &rdataset->private5);
1466 1.1 christos }
1467 1.1 christos
1468 1.1 christos /*
1469 1.1 christos * SDLZ core methods. This is the core of the new DLZ functionality.
1470 1.1 christos */
1471 1.1 christos
1472 1.1 christos /*%
1473 1.1 christos * Build a 'bind' database driver structure to be returned by
1474 1.1 christos * either the find zone or the allow zone transfer method.
1475 1.1 christos * This method is only available in this source file, it is
1476 1.1 christos * not made available anywhere else.
1477 1.1 christos */
1478 1.1 christos
1479 1.1 christos static isc_result_t
1480 1.1 christos dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1481 1.1 christos const dns_name_t *name, dns_rdataclass_t rdclass,
1482 1.1.1.5 christos dns_db_t **dbp) {
1483 1.1 christos isc_result_t result;
1484 1.1 christos dns_sdlz_db_t *sdlzdb;
1485 1.1 christos dns_sdlzimplementation_t *imp;
1486 1.1 christos
1487 1.1 christos /* check that things are as we expect */
1488 1.1 christos REQUIRE(dbp != NULL && *dbp == NULL);
1489 1.1 christos REQUIRE(name != NULL);
1490 1.1 christos
1491 1.1.1.5 christos imp = (dns_sdlzimplementation_t *)driverarg;
1492 1.1 christos
1493 1.1 christos /* allocate and zero memory for driver structure */
1494 1.1 christos sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1495 1.1 christos memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1496 1.1 christos
1497 1.1 christos /* initialize and set origin */
1498 1.1 christos dns_name_init(&sdlzdb->common.origin, NULL);
1499 1.1 christos result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1500 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1501 1.1 christos goto mem_cleanup;
1502 1.1.1.5 christos }
1503 1.1 christos
1504 1.1 christos /* set the rest of the database structure attributes */
1505 1.1 christos sdlzdb->dlzimp = imp;
1506 1.1 christos sdlzdb->common.methods = &sdlzdb_methods;
1507 1.1 christos sdlzdb->common.attributes = 0;
1508 1.1 christos sdlzdb->common.rdclass = rdclass;
1509 1.1 christos sdlzdb->common.mctx = NULL;
1510 1.1 christos sdlzdb->dbdata = dbdata;
1511 1.1.1.5 christos isc_refcount_init(&sdlzdb->references, 1);
1512 1.1 christos
1513 1.1 christos /* attach to the memory context */
1514 1.1 christos isc_mem_attach(mctx, &sdlzdb->common.mctx);
1515 1.1 christos
1516 1.1 christos /* mark structure as valid */
1517 1.1 christos sdlzdb->common.magic = DNS_DB_MAGIC;
1518 1.1 christos sdlzdb->common.impmagic = SDLZDB_MAGIC;
1519 1.1.1.5 christos *dbp = (dns_db_t *)sdlzdb;
1520 1.1 christos
1521 1.1 christos return (result);
1522 1.1.1.5 christos mem_cleanup:
1523 1.1 christos isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1524 1.1 christos return (result);
1525 1.1 christos }
1526 1.1 christos
1527 1.1 christos static isc_result_t
1528 1.1 christos dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1529 1.1 christos dns_rdataclass_t rdclass, const dns_name_t *name,
1530 1.1.1.5 christos const isc_sockaddr_t *clientaddr, dns_db_t **dbp) {
1531 1.1 christos isc_buffer_t b;
1532 1.1 christos isc_buffer_t b2;
1533 1.1 christos char namestr[DNS_NAME_MAXTEXT + 1];
1534 1.1.1.5 christos char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255."
1535 1.1.1.5 christos "255") +
1536 1.1.1.5 christos 1];
1537 1.1 christos isc_netaddr_t netaddr;
1538 1.1 christos isc_result_t result;
1539 1.1 christos dns_sdlzimplementation_t *imp;
1540 1.1 christos
1541 1.1 christos /*
1542 1.1 christos * Perform checks to make sure data is as we expect it to be.
1543 1.1 christos */
1544 1.1 christos REQUIRE(driverarg != NULL);
1545 1.1 christos REQUIRE(name != NULL);
1546 1.1 christos REQUIRE(clientaddr != NULL);
1547 1.1 christos REQUIRE(dbp != NULL && *dbp == NULL);
1548 1.1 christos
1549 1.1.1.5 christos imp = (dns_sdlzimplementation_t *)driverarg;
1550 1.1 christos
1551 1.1 christos /* Convert DNS name to ascii text */
1552 1.1 christos isc_buffer_init(&b, namestr, sizeof(namestr));
1553 1.1.1.2 christos result = dns_name_totext(name, true, &b);
1554 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1555 1.1 christos return (result);
1556 1.1.1.5 christos }
1557 1.1 christos isc_buffer_putuint8(&b, 0);
1558 1.1 christos
1559 1.1 christos /* convert client address to ascii text */
1560 1.1 christos isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1561 1.1 christos isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1562 1.1 christos result = isc_netaddr_totext(&netaddr, &b2);
1563 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1564 1.1 christos return (result);
1565 1.1.1.5 christos }
1566 1.1 christos isc_buffer_putuint8(&b2, 0);
1567 1.1 christos
1568 1.1 christos /* make sure strings are always lowercase */
1569 1.1 christos dns_sdlz_tolower(namestr);
1570 1.1 christos dns_sdlz_tolower(clientstr);
1571 1.1 christos
1572 1.1 christos /* Call SDLZ driver's find zone method */
1573 1.1 christos if (imp->methods->allowzonexfr != NULL) {
1574 1.1.1.5 christos isc_result_t rresult = ISC_R_SUCCESS;
1575 1.1.1.5 christos
1576 1.1 christos MAYBE_LOCK(imp);
1577 1.1 christos result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1578 1.1 christos namestr, clientstr);
1579 1.1 christos MAYBE_UNLOCK(imp);
1580 1.1 christos /*
1581 1.1.1.5 christos * if zone is supported and transfers are (or might be)
1582 1.1.1.5 christos * allowed, build a 'bind' database driver
1583 1.1 christos */
1584 1.1.1.5 christos if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) {
1585 1.1.1.5 christos rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1586 1.1.1.5 christos name, rdclass, dbp);
1587 1.1.1.5 christos }
1588 1.1.1.5 christos if (rresult != ISC_R_SUCCESS) {
1589 1.1.1.5 christos result = rresult;
1590 1.1.1.5 christos }
1591 1.1 christos return (result);
1592 1.1 christos }
1593 1.1 christos
1594 1.1 christos return (ISC_R_NOTIMPLEMENTED);
1595 1.1 christos }
1596 1.1 christos
1597 1.1 christos static isc_result_t
1598 1.1 christos dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1599 1.1.1.5 christos char *argv[], void *driverarg, void **dbdata) {
1600 1.1 christos dns_sdlzimplementation_t *imp;
1601 1.1 christos isc_result_t result = ISC_R_NOTFOUND;
1602 1.1 christos
1603 1.1 christos /* Write debugging message to log */
1604 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
1605 1.1 christos
1606 1.1 christos /*
1607 1.1 christos * Performs checks to make sure data is as we expect it to be.
1608 1.1 christos */
1609 1.1 christos REQUIRE(driverarg != NULL);
1610 1.1 christos REQUIRE(dlzname != NULL);
1611 1.1 christos REQUIRE(dbdata != NULL);
1612 1.1 christos UNUSED(mctx);
1613 1.1 christos
1614 1.1 christos imp = driverarg;
1615 1.1 christos
1616 1.1 christos /* If the create method exists, call it. */
1617 1.1 christos if (imp->methods->create != NULL) {
1618 1.1 christos MAYBE_LOCK(imp);
1619 1.1 christos result = imp->methods->create(dlzname, argc, argv,
1620 1.1 christos imp->driverarg, dbdata);
1621 1.1 christos MAYBE_UNLOCK(imp);
1622 1.1 christos }
1623 1.1 christos
1624 1.1 christos /* Write debugging message to log */
1625 1.1 christos if (result == ISC_R_SUCCESS) {
1626 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
1627 1.1 christos } else {
1628 1.1 christos sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
1629 1.1 christos }
1630 1.1 christos
1631 1.1 christos return (result);
1632 1.1 christos }
1633 1.1 christos
1634 1.1 christos static void
1635 1.1 christos dns_sdlzdestroy(void *driverdata, void **dbdata) {
1636 1.1 christos dns_sdlzimplementation_t *imp;
1637 1.1 christos
1638 1.1 christos /* Write debugging message to log */
1639 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
1640 1.1 christos
1641 1.1 christos imp = driverdata;
1642 1.1 christos
1643 1.1 christos /* If the destroy method exists, call it. */
1644 1.1 christos if (imp->methods->destroy != NULL) {
1645 1.1 christos MAYBE_LOCK(imp);
1646 1.1 christos imp->methods->destroy(imp->driverarg, dbdata);
1647 1.1 christos MAYBE_UNLOCK(imp);
1648 1.1 christos }
1649 1.1 christos }
1650 1.1 christos
1651 1.1 christos static isc_result_t
1652 1.1 christos dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1653 1.1 christos dns_rdataclass_t rdclass, const dns_name_t *name,
1654 1.1.1.5 christos dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
1655 1.1.1.5 christos dns_db_t **dbp) {
1656 1.1 christos isc_buffer_t b;
1657 1.1 christos char namestr[DNS_NAME_MAXTEXT + 1];
1658 1.1 christos isc_result_t result;
1659 1.1 christos dns_sdlzimplementation_t *imp;
1660 1.1 christos
1661 1.1 christos /*
1662 1.1 christos * Perform checks to make sure data is as we expect it to be.
1663 1.1 christos */
1664 1.1 christos REQUIRE(driverarg != NULL);
1665 1.1 christos REQUIRE(name != NULL);
1666 1.1 christos REQUIRE(dbp != NULL && *dbp == NULL);
1667 1.1 christos
1668 1.1.1.5 christos imp = (dns_sdlzimplementation_t *)driverarg;
1669 1.1 christos
1670 1.1 christos /* Convert DNS name to ascii text */
1671 1.1 christos isc_buffer_init(&b, namestr, sizeof(namestr));
1672 1.1.1.2 christos result = dns_name_totext(name, true, &b);
1673 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1674 1.1 christos return (result);
1675 1.1.1.5 christos }
1676 1.1 christos isc_buffer_putuint8(&b, 0);
1677 1.1 christos
1678 1.1 christos /* make sure strings are always lowercase */
1679 1.1 christos dns_sdlz_tolower(namestr);
1680 1.1 christos
1681 1.1 christos /* Call SDLZ driver's find zone method */
1682 1.1 christos MAYBE_LOCK(imp);
1683 1.1 christos result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
1684 1.1 christos methods, clientinfo);
1685 1.1 christos MAYBE_UNLOCK(imp);
1686 1.1 christos
1687 1.1 christos /*
1688 1.1 christos * if zone is supported build a 'bind' database driver
1689 1.1 christos * structure to return
1690 1.1 christos */
1691 1.1.1.5 christos if (result == ISC_R_SUCCESS) {
1692 1.1 christos result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1693 1.1 christos rdclass, dbp);
1694 1.1.1.5 christos }
1695 1.1 christos
1696 1.1 christos return (result);
1697 1.1 christos }
1698 1.1 christos
1699 1.1 christos static isc_result_t
1700 1.1.1.5 christos dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view,
1701 1.1.1.5 christos dns_dlzdb_t *dlzdb) {
1702 1.1 christos isc_result_t result;
1703 1.1 christos dns_sdlzimplementation_t *imp;
1704 1.1 christos
1705 1.1 christos REQUIRE(driverarg != NULL);
1706 1.1 christos
1707 1.1.1.5 christos imp = (dns_sdlzimplementation_t *)driverarg;
1708 1.1 christos
1709 1.1 christos /* Call SDLZ driver's configure method */
1710 1.1 christos if (imp->methods->configure != NULL) {
1711 1.1 christos MAYBE_LOCK(imp);
1712 1.1.1.5 christos result = imp->methods->configure(view, dlzdb, imp->driverarg,
1713 1.1.1.5 christos dbdata);
1714 1.1 christos MAYBE_UNLOCK(imp);
1715 1.1 christos } else {
1716 1.1 christos result = ISC_R_SUCCESS;
1717 1.1 christos }
1718 1.1 christos
1719 1.1 christos return (result);
1720 1.1 christos }
1721 1.1 christos
1722 1.1.1.2 christos static bool
1723 1.1 christos dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
1724 1.1 christos const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
1725 1.1.1.5 christos const dst_key_t *key, void *driverarg, void *dbdata) {
1726 1.1 christos dns_sdlzimplementation_t *imp;
1727 1.1 christos char b_signer[DNS_NAME_FORMATSIZE];
1728 1.1 christos char b_name[DNS_NAME_FORMATSIZE];
1729 1.1 christos char b_addr[ISC_NETADDR_FORMATSIZE];
1730 1.1 christos char b_type[DNS_RDATATYPE_FORMATSIZE];
1731 1.1 christos char b_key[DST_KEY_FORMATSIZE];
1732 1.1 christos isc_buffer_t *tkey_token = NULL;
1733 1.1 christos isc_region_t token_region = { NULL, 0 };
1734 1.1.1.2 christos uint32_t token_len = 0;
1735 1.1.1.2 christos bool ret;
1736 1.1 christos
1737 1.1 christos REQUIRE(driverarg != NULL);
1738 1.1 christos
1739 1.1.1.5 christos imp = (dns_sdlzimplementation_t *)driverarg;
1740 1.1.1.5 christos if (imp->methods->ssumatch == NULL) {
1741 1.1.1.2 christos return (false);
1742 1.1.1.5 christos }
1743 1.1 christos
1744 1.1 christos /*
1745 1.1 christos * Format the request elements. sdlz operates on strings, not
1746 1.1 christos * structures
1747 1.1 christos */
1748 1.1.1.5 christos if (signer != NULL) {
1749 1.1 christos dns_name_format(signer, b_signer, sizeof(b_signer));
1750 1.1.1.5 christos } else {
1751 1.1 christos b_signer[0] = 0;
1752 1.1.1.5 christos }
1753 1.1 christos
1754 1.1 christos dns_name_format(name, b_name, sizeof(b_name));
1755 1.1 christos
1756 1.1.1.5 christos if (tcpaddr != NULL) {
1757 1.1 christos isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
1758 1.1.1.5 christos } else {
1759 1.1 christos b_addr[0] = 0;
1760 1.1.1.5 christos }
1761 1.1 christos
1762 1.1 christos dns_rdatatype_format(type, b_type, sizeof(b_type));
1763 1.1 christos
1764 1.1 christos if (key != NULL) {
1765 1.1 christos dst_key_format(key, b_key, sizeof(b_key));
1766 1.1 christos tkey_token = dst_key_tkeytoken(key);
1767 1.1.1.5 christos } else {
1768 1.1 christos b_key[0] = 0;
1769 1.1.1.5 christos }
1770 1.1 christos
1771 1.1 christos if (tkey_token != NULL) {
1772 1.1 christos isc_buffer_region(tkey_token, &token_region);
1773 1.1 christos token_len = token_region.length;
1774 1.1 christos }
1775 1.1 christos
1776 1.1 christos MAYBE_LOCK(imp);
1777 1.1 christos ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
1778 1.1 christos token_len,
1779 1.1 christos token_len != 0 ? token_region.base : NULL,
1780 1.1 christos imp->driverarg, dbdata);
1781 1.1 christos MAYBE_UNLOCK(imp);
1782 1.1 christos return (ret);
1783 1.1 christos }
1784 1.1 christos
1785 1.1.1.5 christos static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate, dns_sdlzdestroy,
1786 1.1.1.5 christos dns_sdlzfindzone, dns_sdlzallowzonexfr,
1787 1.1.1.5 christos dns_sdlzconfigure, dns_sdlzssumatch };
1788 1.1 christos
1789 1.1 christos /*
1790 1.1 christos * Public functions.
1791 1.1 christos */
1792 1.1 christos
1793 1.1 christos isc_result_t
1794 1.1 christos dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1795 1.1.1.5 christos const char *data) {
1796 1.1 christos dns_rdatalist_t *rdatalist;
1797 1.1 christos dns_rdata_t *rdata;
1798 1.1 christos dns_rdatatype_t typeval;
1799 1.1 christos isc_consttextregion_t r;
1800 1.1 christos isc_buffer_t b;
1801 1.1 christos isc_buffer_t *rdatabuf = NULL;
1802 1.1 christos isc_lex_t *lex;
1803 1.1 christos isc_result_t result;
1804 1.1 christos unsigned int size;
1805 1.1 christos isc_mem_t *mctx;
1806 1.1 christos const dns_name_t *origin;
1807 1.1 christos
1808 1.1 christos REQUIRE(VALID_SDLZLOOKUP(lookup));
1809 1.1 christos REQUIRE(type != NULL);
1810 1.1 christos REQUIRE(data != NULL);
1811 1.1 christos
1812 1.1 christos mctx = lookup->sdlz->common.mctx;
1813 1.1 christos
1814 1.1 christos r.base = type;
1815 1.1 christos r.length = strlen(type);
1816 1.1.1.5 christos result = dns_rdatatype_fromtext(&typeval, (void *)&r);
1817 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1818 1.1 christos return (result);
1819 1.1.1.5 christos }
1820 1.1 christos
1821 1.1 christos rdatalist = ISC_LIST_HEAD(lookup->lists);
1822 1.1 christos while (rdatalist != NULL) {
1823 1.1.1.5 christos if (rdatalist->type == typeval) {
1824 1.1 christos break;
1825 1.1.1.5 christos }
1826 1.1 christos rdatalist = ISC_LIST_NEXT(rdatalist, link);
1827 1.1 christos }
1828 1.1 christos
1829 1.1 christos if (rdatalist == NULL) {
1830 1.1 christos rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1831 1.1 christos dns_rdatalist_init(rdatalist);
1832 1.1 christos rdatalist->rdclass = lookup->sdlz->common.rdclass;
1833 1.1 christos rdatalist->type = typeval;
1834 1.1 christos rdatalist->ttl = ttl;
1835 1.1 christos ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1836 1.1.1.5 christos } else if (rdatalist->ttl > ttl) {
1837 1.1.1.5 christos /*
1838 1.1.1.5 christos * BIND9 doesn't enforce all RRs in an RRset
1839 1.1.1.5 christos * having the same TTL, as per RFC 2136,
1840 1.1.1.5 christos * section 7.12. If a DLZ backend has
1841 1.1.1.5 christos * different TTLs, then the best
1842 1.1.1.5 christos * we can do is return the lowest.
1843 1.1.1.5 christos */
1844 1.1.1.5 christos rdatalist->ttl = ttl;
1845 1.1.1.5 christos }
1846 1.1 christos
1847 1.1 christos rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1848 1.1 christos dns_rdata_init(rdata);
1849 1.1 christos
1850 1.1.1.5 christos if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1851 1.1 christos origin = &lookup->sdlz->common.origin;
1852 1.1.1.5 christos } else {
1853 1.1 christos origin = dns_rootname;
1854 1.1.1.5 christos }
1855 1.1 christos
1856 1.1 christos lex = NULL;
1857 1.1 christos result = isc_lex_create(mctx, 64, &lex);
1858 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1859 1.1 christos goto failure;
1860 1.1.1.5 christos }
1861 1.1 christos
1862 1.1 christos size = initial_size(data);
1863 1.1 christos do {
1864 1.1 christos isc_buffer_constinit(&b, data, strlen(data));
1865 1.1 christos isc_buffer_add(&b, strlen(data));
1866 1.1 christos
1867 1.1 christos result = isc_lex_openbuffer(lex, &b);
1868 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1869 1.1 christos goto failure;
1870 1.1.1.5 christos }
1871 1.1 christos
1872 1.1 christos rdatabuf = NULL;
1873 1.1.1.5 christos isc_buffer_allocate(mctx, &rdatabuf, size);
1874 1.1 christos
1875 1.1 christos result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1876 1.1.1.5 christos rdatalist->type, lex, origin, false,
1877 1.1.1.5 christos mctx, rdatabuf, &lookup->callbacks);
1878 1.1.1.2 christos if (result != ISC_R_SUCCESS) {
1879 1.1 christos isc_buffer_free(&rdatabuf);
1880 1.1.1.2 christos result = DNS_R_SERVFAIL;
1881 1.1.1.2 christos }
1882 1.1.1.5 christos if (size >= 65535) {
1883 1.1 christos break;
1884 1.1.1.5 christos }
1885 1.1 christos size *= 2;
1886 1.1.1.5 christos if (size >= 65535) {
1887 1.1 christos size = 65535;
1888 1.1.1.5 christos }
1889 1.1 christos } while (result == ISC_R_NOSPACE);
1890 1.1 christos
1891 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1892 1.1 christos goto failure;
1893 1.1.1.5 christos }
1894 1.1 christos
1895 1.1 christos ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1896 1.1 christos ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1897 1.1 christos
1898 1.1.1.5 christos if (lex != NULL) {
1899 1.1 christos isc_lex_destroy(&lex);
1900 1.1.1.5 christos }
1901 1.1 christos
1902 1.1 christos return (ISC_R_SUCCESS);
1903 1.1 christos
1904 1.1.1.5 christos failure:
1905 1.1.1.5 christos if (rdatabuf != NULL) {
1906 1.1 christos isc_buffer_free(&rdatabuf);
1907 1.1.1.5 christos }
1908 1.1.1.5 christos if (lex != NULL) {
1909 1.1 christos isc_lex_destroy(&lex);
1910 1.1.1.5 christos }
1911 1.1 christos isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1912 1.1 christos
1913 1.1 christos return (result);
1914 1.1 christos }
1915 1.1 christos
1916 1.1 christos isc_result_t
1917 1.1 christos dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1918 1.1.1.5 christos const char *type, dns_ttl_t ttl, const char *data) {
1919 1.1 christos dns_name_t *newname;
1920 1.1 christos const dns_name_t *origin;
1921 1.1 christos dns_fixedname_t fnewname;
1922 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1923 1.1 christos dns_sdlznode_t *sdlznode;
1924 1.1 christos isc_mem_t *mctx = sdlz->common.mctx;
1925 1.1 christos isc_buffer_t b;
1926 1.1 christos isc_result_t result;
1927 1.1 christos
1928 1.1 christos newname = dns_fixedname_initname(&fnewname);
1929 1.1 christos
1930 1.1.1.5 christos if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1931 1.1 christos origin = &sdlz->common.origin;
1932 1.1.1.5 christos } else {
1933 1.1 christos origin = dns_rootname;
1934 1.1.1.5 christos }
1935 1.1 christos isc_buffer_constinit(&b, name, strlen(name));
1936 1.1 christos isc_buffer_add(&b, strlen(name));
1937 1.1 christos
1938 1.1 christos result = dns_name_fromtext(newname, &b, origin, 0, NULL);
1939 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
1940 1.1 christos return (result);
1941 1.1.1.5 christos }
1942 1.1 christos
1943 1.1 christos if (allnodes->common.relative_names) {
1944 1.1 christos /* All names are relative to the root */
1945 1.1 christos unsigned int nlabels = dns_name_countlabels(newname);
1946 1.1 christos dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1947 1.1 christos }
1948 1.1 christos
1949 1.1 christos sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1950 1.1 christos if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1951 1.1 christos sdlznode = NULL;
1952 1.1 christos result = createnode(sdlz, &sdlznode);
1953 1.1 christos if (result != ISC_R_SUCCESS) {
1954 1.1 christos return (result);
1955 1.1 christos }
1956 1.1.1.5 christos sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1957 1.1.1.5 christos dns_name_init(sdlznode->name, NULL);
1958 1.1.1.5 christos dns_name_dup(newname, mctx, sdlznode->name);
1959 1.1 christos ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1960 1.1 christos if (allnodes->origin == NULL &&
1961 1.1.1.5 christos dns_name_equal(newname, &sdlz->common.origin)) {
1962 1.1 christos allnodes->origin = sdlznode;
1963 1.1.1.5 christos }
1964 1.1 christos }
1965 1.1 christos return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1966 1.1 christos }
1967 1.1 christos
1968 1.1 christos isc_result_t
1969 1.1 christos dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
1970 1.1.1.5 christos uint32_t serial) {
1971 1.1 christos char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1972 1.1 christos int n;
1973 1.1 christos
1974 1.1 christos REQUIRE(mname != NULL);
1975 1.1 christos REQUIRE(rname != NULL);
1976 1.1 christos
1977 1.1.1.5 christos n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname,
1978 1.1.1.5 christos serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1979 1.1 christos SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
1980 1.1.1.5 christos if (n >= (int)sizeof(str) || n < 0) {
1981 1.1 christos return (ISC_R_NOSPACE);
1982 1.1.1.5 christos }
1983 1.1 christos return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1984 1.1 christos }
1985 1.1 christos
1986 1.1 christos isc_result_t
1987 1.1 christos dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1988 1.1 christos void *driverarg, unsigned int flags, isc_mem_t *mctx,
1989 1.1.1.5 christos dns_sdlzimplementation_t **sdlzimp) {
1990 1.1 christos dns_sdlzimplementation_t *imp;
1991 1.1 christos isc_result_t result;
1992 1.1 christos
1993 1.1 christos /*
1994 1.1 christos * Performs checks to make sure data is as we expect it to be.
1995 1.1 christos */
1996 1.1 christos REQUIRE(drivername != NULL);
1997 1.1 christos REQUIRE(methods != NULL);
1998 1.1 christos REQUIRE(methods->findzone != NULL);
1999 1.1 christos REQUIRE(methods->lookup != NULL);
2000 1.1 christos REQUIRE(mctx != NULL);
2001 1.1 christos REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
2002 1.1.1.5 christos REQUIRE((flags &
2003 1.1.1.5 christos ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA |
2004 1.1.1.5 christos DNS_SDLZFLAG_THREADSAFE)) == 0);
2005 1.1 christos
2006 1.1 christos /* Write debugging message to log */
2007 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
2008 1.1 christos
2009 1.1 christos /*
2010 1.1 christos * Allocate memory for a sdlz_implementation object. Error if
2011 1.1 christos * we cannot.
2012 1.1 christos */
2013 1.1 christos imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
2014 1.1 christos
2015 1.1 christos /* Make sure memory region is set to all 0's */
2016 1.1 christos memset(imp, 0, sizeof(dns_sdlzimplementation_t));
2017 1.1 christos
2018 1.1 christos /* Store the data passed into this method */
2019 1.1 christos imp->methods = methods;
2020 1.1 christos imp->driverarg = driverarg;
2021 1.1 christos imp->flags = flags;
2022 1.1 christos imp->mctx = NULL;
2023 1.1 christos
2024 1.1 christos /* attach the new sdlz_implementation object to a memory context */
2025 1.1 christos isc_mem_attach(mctx, &imp->mctx);
2026 1.1 christos
2027 1.1 christos /*
2028 1.1 christos * initialize the driver lock, error if we cannot
2029 1.1 christos * (used if a driver does not support multiple threads)
2030 1.1 christos */
2031 1.1.1.2 christos isc_mutex_init(&imp->driverlock);
2032 1.1 christos
2033 1.1 christos imp->dlz_imp = NULL;
2034 1.1 christos
2035 1.1 christos /*
2036 1.1 christos * register the DLZ driver. Pass in our "extra" sdlz information as
2037 1.1 christos * a driverarg. (that's why we stored the passed in driver arg in our
2038 1.1 christos * sdlz_implementation structure) Also, store the dlz_implementation
2039 1.1 christos * structure in our sdlz_implementation.
2040 1.1 christos */
2041 1.1 christos result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
2042 1.1 christos &imp->dlz_imp);
2043 1.1 christos
2044 1.1 christos /* if registration fails, cleanup and get outta here. */
2045 1.1.1.5 christos if (result != ISC_R_SUCCESS) {
2046 1.1 christos goto cleanup_mutex;
2047 1.1.1.5 christos }
2048 1.1 christos
2049 1.1 christos *sdlzimp = imp;
2050 1.1 christos
2051 1.1 christos return (ISC_R_SUCCESS);
2052 1.1 christos
2053 1.1.1.5 christos cleanup_mutex:
2054 1.1 christos /* destroy the driver lock, we don't need it anymore */
2055 1.1.1.2 christos isc_mutex_destroy(&imp->driverlock);
2056 1.1 christos
2057 1.1 christos /*
2058 1.1 christos * return the memory back to the available memory pool and
2059 1.1 christos * remove it from the memory context.
2060 1.1 christos */
2061 1.1.1.5 christos isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2062 1.1 christos return (result);
2063 1.1 christos }
2064 1.1 christos
2065 1.1 christos void
2066 1.1 christos dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
2067 1.1 christos dns_sdlzimplementation_t *imp;
2068 1.1 christos
2069 1.1 christos /* Write debugging message to log */
2070 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
2071 1.1 christos
2072 1.1 christos /*
2073 1.1 christos * Performs checks to make sure data is as we expect it to be.
2074 1.1 christos */
2075 1.1 christos REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
2076 1.1 christos
2077 1.1 christos imp = *sdlzimp;
2078 1.1.1.5 christos *sdlzimp = NULL;
2079 1.1 christos
2080 1.1 christos /* Unregister the DLZ driver implementation */
2081 1.1 christos dns_dlzunregister(&imp->dlz_imp);
2082 1.1 christos
2083 1.1 christos /* destroy the driver lock, we don't need it anymore */
2084 1.1.1.2 christos isc_mutex_destroy(&imp->driverlock);
2085 1.1 christos
2086 1.1 christos /*
2087 1.1 christos * return the memory back to the available memory pool and
2088 1.1 christos * remove it from the memory context.
2089 1.1 christos */
2090 1.1.1.5 christos isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2091 1.1 christos }
2092 1.1 christos
2093 1.1 christos isc_result_t
2094 1.1 christos dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
2095 1.1.1.5 christos const dns_name_t *name, dns_db_t **dbp) {
2096 1.1 christos isc_result_t result;
2097 1.1 christos
2098 1.1 christos result = dns_sdlzcreateDBP(dlzdatabase->mctx,
2099 1.1 christos dlzdatabase->implementation->driverarg,
2100 1.1 christos dlzdatabase->dbdata, name, rdclass, dbp);
2101 1.1 christos return (result);
2102 1.1 christos }
2103