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