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