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