dnsrps.c revision 1.13 1 1.13 christos /* $NetBSD: dnsrps.c,v 1.13 2025/01/26 16:25:22 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 1.1 christos *
6 1.8 christos * SPDX-License-Identifier: MPL-2.0
7 1.8 christos *
8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public
9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this
10 1.6 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 1.1 christos *
12 1.1 christos * See the COPYRIGHT file distributed with this work for additional
13 1.1 christos * information regarding copyright ownership.
14 1.1 christos */
15 1.1 christos
16 1.1 christos /*! \file */
17 1.1 christos
18 1.3 christos #include <inttypes.h>
19 1.3 christos #include <stdbool.h>
20 1.3 christos
21 1.1 christos #ifdef USE_DNSRPS
22 1.1 christos
23 1.5 christos #include <stdlib.h>
24 1.5 christos
25 1.1 christos #include <isc/mem.h>
26 1.1 christos #include <isc/string.h>
27 1.1 christos #include <isc/util.h>
28 1.1 christos
29 1.1 christos #include <dns/db.h>
30 1.1 christos #define LIBRPZ_LIB_OPEN DNSRPS_LIB_OPEN
31 1.11 christos #include <isc/result.h>
32 1.11 christos
33 1.1 christos #include <dns/dnsrps.h>
34 1.1 christos #include <dns/rdataset.h>
35 1.1 christos #include <dns/rdatasetiter.h>
36 1.1 christos #include <dns/rpz.h>
37 1.1 christos
38 1.13 christos librpz_t *librpz = NULL;
39 1.1 christos librpz_emsg_t librpz_lib_open_emsg;
40 1.13 christos static void *librpz_handle = NULL;
41 1.1 christos
42 1.5 christos #define RPSDB_MAGIC ISC_MAGIC('R', 'P', 'Z', 'F')
43 1.1 christos #define VALID_RPSDB(rpsdb) ((rpsdb)->common.impmagic == RPSDB_MAGIC)
44 1.1 christos
45 1.13 christos #define RD_DB(r) ((r)->rps.db)
46 1.13 christos #define RD_CUR_RR(r) ((r)->rps.iter_pos)
47 1.5 christos #define RD_NEXT_RR(r) ((r)->resign)
48 1.13 christos #define RD_COUNT(r) ((r)->rps.iter_count)
49 1.1 christos
50 1.1 christos typedef struct {
51 1.5 christos dns_rdatasetiter_t common;
52 1.5 christos dns_rdatatype_t type;
53 1.5 christos dns_rdataclass_t class;
54 1.5 christos uint32_t ttl;
55 1.5 christos uint count;
56 1.5 christos librpz_idx_t next_rr;
57 1.1 christos } rpsdb_rdatasetiter_t;
58 1.1 christos
59 1.1 christos static dns_dbmethods_t rpsdb_db_methods;
60 1.1 christos static dns_rdatasetmethods_t rpsdb_rdataset_methods;
61 1.1 christos static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods;
62 1.1 christos
63 1.1 christos static librpz_clist_t *clist;
64 1.1 christos
65 1.1 christos static isc_mutex_t dnsrps_mutex;
66 1.1 christos
67 1.1 christos static void
68 1.1 christos dnsrps_lock(void *mutex0) {
69 1.1 christos isc_mutex_t *mutex = mutex0;
70 1.1 christos
71 1.1 christos LOCK(mutex);
72 1.1 christos }
73 1.1 christos
74 1.1 christos static void
75 1.1 christos dnsrps_unlock(void *mutex0) {
76 1.1 christos isc_mutex_t *mutex = mutex0;
77 1.1 christos
78 1.1 christos UNLOCK(mutex);
79 1.1 christos }
80 1.1 christos
81 1.1 christos static void
82 1.1 christos dnsrps_mutex_destroy(void *mutex0) {
83 1.1 christos isc_mutex_t *mutex = mutex0;
84 1.1 christos
85 1.3 christos isc_mutex_destroy(mutex);
86 1.1 christos }
87 1.1 christos
88 1.1 christos static void
89 1.1 christos dnsrps_log_fnc(librpz_log_level_t level, void *ctxt, const char *buf) {
90 1.1 christos int isc_level;
91 1.1 christos
92 1.1 christos UNUSED(ctxt);
93 1.1 christos
94 1.1 christos /* Setting librpz_log_level in the configuration overrides the
95 1.1 christos * BIND9 logging levels. */
96 1.1 christos if (level > LIBRPZ_LOG_TRACE1 &&
97 1.1 christos level <= librpz->log_level_val(LIBRPZ_LOG_INVALID))
98 1.5 christos {
99 1.1 christos level = LIBRPZ_LOG_TRACE1;
100 1.5 christos }
101 1.1 christos
102 1.5 christos switch (level) {
103 1.5 christos case LIBRPZ_LOG_TRACE1: /* big events such as dnsrpzd starts */
104 1.1 christos isc_level = DNS_RPZ_INFO_LEVEL;
105 1.1 christos break;
106 1.1 christos
107 1.5 christos case LIBRPZ_LOG_TRACE2: /* smaller dnsrpzd zone transfers */
108 1.1 christos isc_level = DNS_RPZ_DEBUG_LEVEL1;
109 1.1 christos break;
110 1.1 christos
111 1.5 christos case LIBRPZ_LOG_TRACE3: /* librpz hits */
112 1.1 christos isc_level = DNS_RPZ_DEBUG_LEVEL2;
113 1.1 christos break;
114 1.1 christos
115 1.5 christos case LIBRPZ_LOG_TRACE4: /* librpz lookups */
116 1.1 christos isc_level = DNS_RPZ_DEBUG_LEVEL3;
117 1.1 christos break;
118 1.13 christos
119 1.13 christos case LIBRPZ_LOG_FATAL:
120 1.13 christos case LIBRPZ_LOG_ERROR: /* errors */
121 1.13 christos default:
122 1.13 christos isc_level = DNS_RPZ_ERROR_LEVEL;
123 1.13 christos break;
124 1.1 christos }
125 1.1 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
126 1.1 christos isc_level, "dnsrps: %s", buf);
127 1.1 christos }
128 1.1 christos
129 1.1 christos /*
130 1.1 christos * Start dnsrps for the entire server.
131 1.1 christos * This is not thread safe, but it is called by a single thread.
132 1.1 christos */
133 1.1 christos isc_result_t
134 1.13 christos dns_dnsrps_server_create(const char *librpz_path) {
135 1.1 christos librpz_emsg_t emsg;
136 1.1 christos
137 1.1 christos INSIST(clist == NULL);
138 1.1 christos INSIST(librpz == NULL);
139 1.1 christos INSIST(librpz_handle == NULL);
140 1.1 christos
141 1.1 christos /*
142 1.1 christos * Notice if librpz is available.
143 1.1 christos */
144 1.5 christos librpz = librpz_lib_open(&librpz_lib_open_emsg, &librpz_handle,
145 1.13 christos librpz_path);
146 1.5 christos if (librpz == NULL) {
147 1.13 christos return ISC_R_FILENOTFOUND;
148 1.5 christos }
149 1.1 christos
150 1.3 christos isc_mutex_init(&dnsrps_mutex);
151 1.1 christos
152 1.5 christos librpz->set_log(dnsrps_log_fnc, NULL);
153 1.1 christos
154 1.1 christos clist = librpz->clist_create(&emsg, dnsrps_lock, dnsrps_unlock,
155 1.1 christos dnsrps_mutex_destroy, &dnsrps_mutex,
156 1.1 christos dns_lctx);
157 1.1 christos if (clist == NULL) {
158 1.1 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
159 1.1 christos DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
160 1.1 christos "dnsrps: %s", emsg.c);
161 1.13 christos return ISC_R_NOMEMORY;
162 1.1 christos }
163 1.13 christos return ISC_R_SUCCESS;
164 1.1 christos }
165 1.1 christos
166 1.1 christos /*
167 1.1 christos * Stop dnsrps for the entire server.
168 1.1 christos * This is not thread safe.
169 1.1 christos */
170 1.1 christos void
171 1.1 christos dns_dnsrps_server_destroy(void) {
172 1.5 christos if (clist != NULL) {
173 1.1 christos librpz->clist_detach(&clist);
174 1.5 christos }
175 1.1 christos
176 1.13 christos #if DNSRPS_LIB_OPEN == 2
177 1.1 christos if (librpz != NULL) {
178 1.1 christos INSIST(librpz_handle != NULL);
179 1.5 christos if (dlclose(librpz_handle) != 0) {
180 1.1 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
181 1.1 christos DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
182 1.1 christos "dnsrps: dlclose(): %s", dlerror());
183 1.5 christos }
184 1.1 christos librpz_handle = NULL;
185 1.13 christos librpz = NULL;
186 1.1 christos }
187 1.13 christos #endif
188 1.1 christos }
189 1.1 christos
190 1.1 christos /*
191 1.1 christos * Ready dnsrps for a view.
192 1.1 christos */
193 1.1 christos isc_result_t
194 1.1 christos dns_dnsrps_view_init(dns_rpz_zones_t *new, char *rps_cstr) {
195 1.1 christos librpz_emsg_t emsg;
196 1.1 christos
197 1.5 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
198 1.5 christos DNS_RPZ_DEBUG_LEVEL3, "dnsrps configuration \"%s\"",
199 1.5 christos rps_cstr);
200 1.1 christos
201 1.5 christos new->rps_client = librpz->client_create(&emsg, clist, rps_cstr, false);
202 1.1 christos if (new->rps_client == NULL) {
203 1.1 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
204 1.1 christos DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
205 1.1 christos "librpz->client_create(): %s", emsg.c);
206 1.3 christos new->p.dnsrps_enabled = false;
207 1.13 christos return ISC_R_FAILURE;
208 1.1 christos }
209 1.1 christos
210 1.3 christos new->p.dnsrps_enabled = true;
211 1.13 christos return ISC_R_SUCCESS;
212 1.1 christos }
213 1.1 christos
214 1.1 christos /*
215 1.1 christos * Connect to and start the dnsrps daemon, dnsrpzd.
216 1.1 christos */
217 1.1 christos isc_result_t
218 1.1 christos dns_dnsrps_connect(dns_rpz_zones_t *rpzs) {
219 1.1 christos librpz_emsg_t emsg;
220 1.1 christos
221 1.5 christos if (rpzs == NULL || !rpzs->p.dnsrps_enabled) {
222 1.13 christos return ISC_R_SUCCESS;
223 1.5 christos }
224 1.1 christos
225 1.1 christos /*
226 1.1 christos * Fail only if we failed to link to librpz.
227 1.1 christos */
228 1.1 christos if (librpz == NULL) {
229 1.1 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
230 1.1 christos DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
231 1.1 christos "librpz->connect(): %s", librpz_lib_open_emsg.c);
232 1.13 christos return ISC_R_FAILURE;
233 1.1 christos }
234 1.1 christos
235 1.1 christos if (!librpz->connect(&emsg, rpzs->rps_client, true)) {
236 1.1 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
237 1.1 christos DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
238 1.1 christos "librpz->connect(): %s", emsg.c);
239 1.13 christos return ISC_R_SUCCESS;
240 1.1 christos }
241 1.1 christos
242 1.1 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
243 1.1 christos DNS_RPZ_INFO_LEVEL, "dnsrps: librpz version %s",
244 1.1 christos librpz->version);
245 1.1 christos
246 1.13 christos return ISC_R_SUCCESS;
247 1.1 christos }
248 1.1 christos
249 1.1 christos /*
250 1.1 christos * Get ready to try RPZ rewriting.
251 1.1 christos */
252 1.1 christos isc_result_t
253 1.1 christos dns_dnsrps_rewrite_init(librpz_emsg_t *emsg, dns_rpz_st_t *st,
254 1.1 christos dns_rpz_zones_t *rpzs, const dns_name_t *qname,
255 1.5 christos isc_mem_t *mctx, bool have_rd) {
256 1.13 christos dns_rpsdb_t *rpsdb = NULL;
257 1.1 christos
258 1.1 christos rpsdb = isc_mem_get(mctx, sizeof(*rpsdb));
259 1.13 christos *rpsdb = (dns_rpsdb_t){
260 1.13 christos .common = {
261 1.13 christos .methods = &rpsdb_db_methods,
262 1.13 christos .rdclass = dns_rdataclass_in,
263 1.13 christos },
264 1.13 christos .qname = qname,
265 1.13 christos };
266 1.13 christos isc_refcount_init(&rpsdb->common.references, 1);
267 1.1 christos
268 1.5 christos if (!librpz->rsp_create(emsg, &rpsdb->rsp, NULL, rpzs->rps_client,
269 1.5 christos have_rd, false))
270 1.5 christos {
271 1.1 christos isc_mem_put(mctx, rpsdb, sizeof(*rpsdb));
272 1.13 christos return DNS_R_SERVFAIL;
273 1.1 christos }
274 1.1 christos if (rpsdb->rsp == NULL) {
275 1.1 christos isc_mem_put(mctx, rpsdb, sizeof(*rpsdb));
276 1.13 christos return DNS_R_DISALLOWED;
277 1.1 christos }
278 1.1 christos
279 1.1 christos rpsdb->common.magic = DNS_DB_MAGIC;
280 1.1 christos rpsdb->common.impmagic = RPSDB_MAGIC;
281 1.1 christos dns_name_init(&rpsdb->common.origin, NULL);
282 1.1 christos isc_mem_attach(mctx, &rpsdb->common.mctx);
283 1.1 christos
284 1.1 christos st->rpsdb = &rpsdb->common;
285 1.13 christos return ISC_R_SUCCESS;
286 1.1 christos }
287 1.1 christos
288 1.1 christos /*
289 1.1 christos * Convert a dnsrps policy to a classic BIND9 RPZ policy.
290 1.1 christos */
291 1.1 christos dns_rpz_policy_t
292 1.1 christos dns_dnsrps_2policy(librpz_policy_t rps_policy) {
293 1.1 christos switch (rps_policy) {
294 1.1 christos case LIBRPZ_POLICY_UNDEFINED:
295 1.13 christos return DNS_RPZ_POLICY_MISS;
296 1.1 christos case LIBRPZ_POLICY_PASSTHRU:
297 1.13 christos return DNS_RPZ_POLICY_PASSTHRU;
298 1.1 christos case LIBRPZ_POLICY_DROP:
299 1.13 christos return DNS_RPZ_POLICY_DROP;
300 1.1 christos case LIBRPZ_POLICY_TCP_ONLY:
301 1.13 christos return DNS_RPZ_POLICY_TCP_ONLY;
302 1.1 christos case LIBRPZ_POLICY_NXDOMAIN:
303 1.13 christos return DNS_RPZ_POLICY_NXDOMAIN;
304 1.1 christos case LIBRPZ_POLICY_NODATA:
305 1.13 christos return DNS_RPZ_POLICY_NODATA;
306 1.1 christos case LIBRPZ_POLICY_RECORD:
307 1.1 christos case LIBRPZ_POLICY_CNAME:
308 1.13 christos return DNS_RPZ_POLICY_RECORD;
309 1.1 christos
310 1.1 christos case LIBRPZ_POLICY_DELETED:
311 1.1 christos case LIBRPZ_POLICY_GIVEN:
312 1.1 christos case LIBRPZ_POLICY_DISABLED:
313 1.1 christos default:
314 1.8 christos UNREACHABLE();
315 1.1 christos }
316 1.1 christos }
317 1.1 christos
318 1.1 christos /*
319 1.1 christos * Convert a dnsrps trigger to a classic BIND9 RPZ rewrite or trigger type.
320 1.1 christos */
321 1.1 christos dns_rpz_type_t
322 1.1 christos dns_dnsrps_trig2type(librpz_trig_t trig) {
323 1.1 christos switch (trig) {
324 1.1 christos case LIBRPZ_TRIG_CLIENT_IP:
325 1.13 christos return DNS_RPZ_TYPE_CLIENT_IP;
326 1.1 christos case LIBRPZ_TRIG_QNAME:
327 1.13 christos return DNS_RPZ_TYPE_QNAME;
328 1.1 christos case LIBRPZ_TRIG_IP:
329 1.13 christos return DNS_RPZ_TYPE_IP;
330 1.1 christos case LIBRPZ_TRIG_NSDNAME:
331 1.13 christos return DNS_RPZ_TYPE_NSDNAME;
332 1.1 christos case LIBRPZ_TRIG_NSIP:
333 1.13 christos return DNS_RPZ_TYPE_NSIP;
334 1.13 christos case LIBRPZ_TRIG_BAD:
335 1.13 christos default:
336 1.13 christos return DNS_RPZ_TYPE_BAD;
337 1.1 christos }
338 1.1 christos }
339 1.1 christos
340 1.1 christos /*
341 1.1 christos * Convert a classic BIND9 RPZ rewrite or trigger type to a librpz trigger type.
342 1.1 christos */
343 1.1 christos librpz_trig_t
344 1.1 christos dns_dnsrps_type2trig(dns_rpz_type_t type) {
345 1.1 christos switch (type) {
346 1.1 christos case DNS_RPZ_TYPE_CLIENT_IP:
347 1.13 christos return LIBRPZ_TRIG_CLIENT_IP;
348 1.1 christos case DNS_RPZ_TYPE_QNAME:
349 1.13 christos return LIBRPZ_TRIG_QNAME;
350 1.1 christos case DNS_RPZ_TYPE_IP:
351 1.13 christos return LIBRPZ_TRIG_IP;
352 1.1 christos case DNS_RPZ_TYPE_NSDNAME:
353 1.13 christos return LIBRPZ_TRIG_NSDNAME;
354 1.1 christos case DNS_RPZ_TYPE_NSIP:
355 1.13 christos return LIBRPZ_TRIG_NSIP;
356 1.13 christos case DNS_RPZ_TYPE_BAD:
357 1.13 christos default:
358 1.13 christos return LIBRPZ_TRIG_BAD;
359 1.1 christos }
360 1.1 christos }
361 1.1 christos
362 1.1 christos static void
363 1.13 christos rpsdb_destroy(dns_db_t *db) {
364 1.13 christos dns_rpsdb_t *rpsdb = (dns_rpsdb_t *)db;
365 1.1 christos
366 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
367 1.1 christos
368 1.1 christos librpz->rsp_detach(&rpsdb->rsp);
369 1.13 christos isc_refcount_destroy(&rpsdb->common.references);
370 1.1 christos rpsdb->common.impmagic = 0;
371 1.1 christos isc_mem_putanddetach(&rpsdb->common.mctx, rpsdb, sizeof(*rpsdb));
372 1.1 christos }
373 1.1 christos
374 1.1 christos static void
375 1.13 christos rpsdb_attachnode(dns_db_t *db, dns_dbnode_t *source,
376 1.13 christos dns_dbnode_t **targetp DNS__DB_FLARG) {
377 1.13 christos dns_rpsdb_t *rpsdb = (dns_rpsdb_t *)db;
378 1.1 christos
379 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
380 1.1 christos REQUIRE(targetp != NULL && *targetp == NULL);
381 1.5 christos REQUIRE(source == &rpsdb->origin_node || source == &rpsdb->data_node);
382 1.1 christos
383 1.13 christos isc_refcount_increment(&rpsdb->common.references);
384 1.1 christos *targetp = source;
385 1.1 christos }
386 1.1 christos
387 1.1 christos static void
388 1.13 christos rpsdb_detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) {
389 1.13 christos dns_rpsdb_t *rpsdb = (dns_rpsdb_t *)db;
390 1.1 christos
391 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
392 1.1 christos REQUIRE(*targetp == &rpsdb->origin_node ||
393 1.1 christos *targetp == &rpsdb->data_node);
394 1.1 christos
395 1.1 christos *targetp = NULL;
396 1.13 christos dns_db_detach(&db);
397 1.1 christos }
398 1.1 christos
399 1.1 christos static isc_result_t
400 1.3 christos rpsdb_findnode(dns_db_t *db, const dns_name_t *name, bool create,
401 1.13 christos dns_dbnode_t **nodep DNS__DB_FLARG) {
402 1.13 christos dns_rpsdb_t *rpsdb = (dns_rpsdb_t *)db;
403 1.13 christos dns_db_t *dbp = NULL;
404 1.1 christos
405 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
406 1.1 christos REQUIRE(nodep != NULL && *nodep == NULL);
407 1.1 christos REQUIRE(!create);
408 1.1 christos
409 1.1 christos /*
410 1.1 christos * A fake/shim rpsdb has two nodes.
411 1.1 christos * One is the origin to support query_addsoa() in bin/named/query.c.
412 1.1 christos * The other contains rewritten RRs.
413 1.1 christos */
414 1.5 christos if (dns_name_equal(name, &db->origin)) {
415 1.1 christos *nodep = &rpsdb->origin_node;
416 1.5 christos } else {
417 1.1 christos *nodep = &rpsdb->data_node;
418 1.5 christos }
419 1.1 christos
420 1.13 christos dns_db_attach(db, &dbp);
421 1.13 christos
422 1.13 christos return ISC_R_SUCCESS;
423 1.1 christos }
424 1.1 christos
425 1.1 christos static void
426 1.1 christos rpsdb_bind_rdataset(dns_rdataset_t *rdataset, uint count, librpz_idx_t next_rr,
427 1.1 christos dns_rdatatype_t type, uint16_t class, uint32_t ttl,
428 1.13 christos dns_rpsdb_t *rpsdb) {
429 1.13 christos dns_db_t *dbp = NULL;
430 1.1 christos
431 1.5 christos INSIST(rdataset->methods == NULL); /* We must be disassociated. */
432 1.1 christos REQUIRE(type != dns_rdatatype_none);
433 1.1 christos
434 1.1 christos rdataset->methods = &rpsdb_rdataset_methods;
435 1.1 christos rdataset->rdclass = class;
436 1.1 christos rdataset->type = type;
437 1.1 christos rdataset->ttl = ttl;
438 1.1 christos dbp = NULL;
439 1.1 christos dns_db_attach(&rpsdb->common, &dbp);
440 1.13 christos RD_DB(rdataset) = (dns_rpsdb_t *)dbp;
441 1.1 christos RD_COUNT(rdataset) = count;
442 1.1 christos RD_NEXT_RR(rdataset) = next_rr;
443 1.1 christos RD_CUR_RR(rdataset) = NULL;
444 1.1 christos }
445 1.1 christos
446 1.1 christos static isc_result_t
447 1.13 christos rpsdb_bind_soa(dns_rdataset_t *rdataset, dns_rpsdb_t *rpsdb) {
448 1.1 christos uint32_t ttl;
449 1.1 christos librpz_emsg_t emsg;
450 1.1 christos
451 1.5 christos if (!librpz->rsp_soa(&emsg, &ttl, NULL, NULL, &rpsdb->result,
452 1.9 christos rpsdb->rsp))
453 1.9 christos {
454 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
455 1.13 christos return DNS_R_SERVFAIL;
456 1.1 christos }
457 1.1 christos rpsdb_bind_rdataset(rdataset, 1, LIBRPZ_IDX_BAD, dns_rdatatype_soa,
458 1.5 christos dns_rdataclass_in, ttl, rpsdb);
459 1.13 christos return ISC_R_SUCCESS;
460 1.1 christos }
461 1.1 christos
462 1.1 christos /*
463 1.1 christos * Forge an rdataset of the desired type from a librpz result.
464 1.1 christos * This is written for simplicity instead of speed, because RPZ rewriting
465 1.1 christos * should be rare compared to normal BIND operations.
466 1.1 christos */
467 1.1 christos static isc_result_t
468 1.1 christos rpsdb_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
469 1.1 christos dns_rdatatype_t type, dns_rdatatype_t covers,
470 1.1 christos isc_stdtime_t now, dns_rdataset_t *rdataset,
471 1.13 christos dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
472 1.13 christos dns_rpsdb_t *rpsdb = (dns_rpsdb_t *)db;
473 1.1 christos dns_rdatatype_t foundtype;
474 1.1 christos dns_rdataclass_t class;
475 1.1 christos uint32_t ttl;
476 1.1 christos uint count;
477 1.1 christos librpz_emsg_t emsg;
478 1.1 christos
479 1.1 christos UNUSED(version);
480 1.1 christos UNUSED(covers);
481 1.1 christos UNUSED(now);
482 1.1 christos UNUSED(sigrdataset);
483 1.1 christos
484 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
485 1.1 christos
486 1.1 christos if (node == &rpsdb->origin_node) {
487 1.5 christos if (type == dns_rdatatype_any) {
488 1.13 christos return ISC_R_SUCCESS;
489 1.5 christos }
490 1.5 christos if (type == dns_rdatatype_soa) {
491 1.13 christos return rpsdb_bind_soa(rdataset, rpsdb);
492 1.5 christos }
493 1.13 christos return DNS_R_NXRRSET;
494 1.1 christos }
495 1.1 christos
496 1.1 christos REQUIRE(node == &rpsdb->data_node);
497 1.1 christos
498 1.1 christos switch (rpsdb->result.policy) {
499 1.13 christos case LIBRPZ_POLICY_NXDOMAIN:
500 1.13 christos return DNS_R_NXDOMAIN;
501 1.13 christos
502 1.13 christos case LIBRPZ_POLICY_NODATA:
503 1.13 christos return DNS_R_NXRRSET;
504 1.13 christos
505 1.13 christos case LIBRPZ_POLICY_RECORD:
506 1.13 christos case LIBRPZ_POLICY_CNAME:
507 1.13 christos break;
508 1.13 christos
509 1.1 christos case LIBRPZ_POLICY_UNDEFINED:
510 1.1 christos case LIBRPZ_POLICY_DELETED:
511 1.1 christos case LIBRPZ_POLICY_PASSTHRU:
512 1.1 christos case LIBRPZ_POLICY_DROP:
513 1.1 christos case LIBRPZ_POLICY_TCP_ONLY:
514 1.1 christos case LIBRPZ_POLICY_GIVEN:
515 1.1 christos case LIBRPZ_POLICY_DISABLED:
516 1.1 christos default:
517 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL,
518 1.1 christos "impossible dnsrps policy %d at %s:%d",
519 1.1 christos rpsdb->result.policy, __FILE__, __LINE__);
520 1.13 christos return DNS_R_SERVFAIL;
521 1.1 christos }
522 1.1 christos
523 1.5 christos if (type == dns_rdatatype_soa) {
524 1.13 christos return rpsdb_bind_soa(rdataset, rpsdb);
525 1.5 christos }
526 1.1 christos
527 1.1 christos /*
528 1.1 christos * There is little to do for an ANY query.
529 1.1 christos */
530 1.5 christos if (type == dns_rdatatype_any) {
531 1.13 christos return ISC_R_SUCCESS;
532 1.5 christos }
533 1.1 christos
534 1.1 christos /*
535 1.1 christos * Reset to the start of the RRs.
536 1.1 christos * This function is only used after a policy has been chosen,
537 1.1 christos * and so without caring whether it is after recursion.
538 1.1 christos */
539 1.1 christos if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
540 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
541 1.13 christos return DNS_R_SERVFAIL;
542 1.1 christos }
543 1.1 christos if (!librpz->rsp_rr(&emsg, &foundtype, &class, &ttl, NULL,
544 1.1 christos &rpsdb->result, rpsdb->qname->ndata,
545 1.5 christos rpsdb->qname->length, rpsdb->rsp))
546 1.5 christos {
547 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
548 1.13 christos return DNS_R_SERVFAIL;
549 1.1 christos }
550 1.1 christos REQUIRE(foundtype != dns_rdatatype_none);
551 1.1 christos
552 1.1 christos /*
553 1.1 christos * Ho many of the target RR type are available?
554 1.1 christos */
555 1.1 christos count = 0;
556 1.1 christos do {
557 1.5 christos if (type == foundtype || type == dns_rdatatype_any) {
558 1.1 christos ++count;
559 1.5 christos }
560 1.1 christos
561 1.1 christos if (!librpz->rsp_rr(&emsg, &foundtype, NULL, NULL, NULL,
562 1.1 christos &rpsdb->result, rpsdb->qname->ndata,
563 1.5 christos rpsdb->qname->length, rpsdb->rsp))
564 1.5 christos {
565 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
566 1.13 christos return DNS_R_SERVFAIL;
567 1.1 christos }
568 1.1 christos } while (foundtype != dns_rdatatype_none);
569 1.5 christos if (count == 0) {
570 1.13 christos return DNS_R_NXRRSET;
571 1.5 christos }
572 1.5 christos rpsdb_bind_rdataset(rdataset, count, rpsdb->result.next_rr, type, class,
573 1.5 christos ttl, rpsdb);
574 1.13 christos return ISC_R_SUCCESS;
575 1.1 christos }
576 1.1 christos
577 1.1 christos static isc_result_t
578 1.1 christos rpsdb_finddb(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
579 1.1 christos dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
580 1.1 christos dns_dbnode_t **nodep, dns_name_t *foundname,
581 1.13 christos dns_rdataset_t *rdataset,
582 1.13 christos dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
583 1.13 christos dns_dbnode_t *node = NULL;
584 1.1 christos
585 1.1 christos UNUSED(version);
586 1.1 christos UNUSED(options);
587 1.1 christos UNUSED(now);
588 1.1 christos UNUSED(sigrdataset);
589 1.1 christos
590 1.1 christos if (nodep == NULL) {
591 1.1 christos node = NULL;
592 1.1 christos nodep = &node;
593 1.1 christos }
594 1.13 christos rpsdb_findnode(db, name, false, nodep DNS__DB_FLARG_PASS);
595 1.11 christos dns_name_copy(name, foundname);
596 1.13 christos return rpsdb_findrdataset(db, *nodep, NULL, type, 0, 0, rdataset,
597 1.13 christos sigrdataset DNS__DB_FLARG_PASS);
598 1.1 christos }
599 1.1 christos
600 1.1 christos static isc_result_t
601 1.1 christos rpsdb_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
602 1.9 christos unsigned int options, isc_stdtime_t now,
603 1.13 christos dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) {
604 1.13 christos dns_rpsdb_t *rpsdb = (dns_rpsdb_t *)db;
605 1.13 christos rpsdb_rdatasetiter_t *rpsdb_iter = NULL;
606 1.1 christos
607 1.1 christos UNUSED(version);
608 1.1 christos UNUSED(now);
609 1.1 christos
610 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
611 1.1 christos REQUIRE(node == &rpsdb->origin_node || node == &rpsdb->data_node);
612 1.1 christos
613 1.1 christos rpsdb_iter = isc_mem_get(rpsdb->common.mctx, sizeof(*rpsdb_iter));
614 1.13 christos *rpsdb_iter = ( rpsdb_rdatasetiter_t){
615 1.13 christos
616 1.13 christos .common= {.magic = DNS_RDATASETITER_MAGIC,
617 1.13 christos .methods = &rpsdb_rdatasetiter_methods,
618 1.13 christos .db = db,
619 1.13 christos .options = options,
620 1.13 christos },
621 1.13 christos };
622 1.1 christos
623 1.13 christos rpsdb_attachnode(db, node, &rpsdb_iter->common.node DNS__DB_FLARG_PASS);
624 1.1 christos
625 1.1 christos *iteratorp = &rpsdb_iter->common;
626 1.1 christos
627 1.13 christos return ISC_R_SUCCESS;
628 1.1 christos }
629 1.1 christos
630 1.3 christos static bool
631 1.1 christos rpsdb_issecure(dns_db_t *db) {
632 1.1 christos UNUSED(db);
633 1.1 christos
634 1.13 christos return false;
635 1.1 christos }
636 1.1 christos
637 1.1 christos static isc_result_t
638 1.13 christos rpsdb_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) {
639 1.13 christos dns_rpsdb_t *rpsdb = (dns_rpsdb_t *)db;
640 1.1 christos
641 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
642 1.1 christos REQUIRE(nodep != NULL && *nodep == NULL);
643 1.1 christos
644 1.13 christos rpsdb_attachnode(db, &rpsdb->origin_node, nodep DNS__DB_FLARG_PASS);
645 1.13 christos return ISC_R_SUCCESS;
646 1.1 christos }
647 1.1 christos
648 1.1 christos static void
649 1.13 christos rpsdb_rdataset_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) {
650 1.13 christos dns_db_t *db = NULL;
651 1.1 christos
652 1.1 christos /*
653 1.1 christos * Detach the last RR delivered.
654 1.1 christos */
655 1.1 christos if (RD_CUR_RR(rdataset) != NULL) {
656 1.1 christos free(RD_CUR_RR(rdataset));
657 1.1 christos RD_CUR_RR(rdataset) = NULL;
658 1.1 christos }
659 1.1 christos
660 1.13 christos db = (dns_db_t *)RD_DB(rdataset);
661 1.1 christos RD_DB(rdataset) = NULL;
662 1.1 christos dns_db_detach(&db);
663 1.1 christos }
664 1.1 christos
665 1.1 christos static isc_result_t
666 1.1 christos rpsdb_rdataset_next(dns_rdataset_t *rdataset) {
667 1.13 christos dns_rpsdb_t *rpsdb = NULL;
668 1.1 christos uint16_t type;
669 1.1 christos dns_rdataclass_t class;
670 1.13 christos librpz_rr_t *rr = NULL;
671 1.1 christos librpz_emsg_t emsg;
672 1.1 christos
673 1.1 christos rpsdb = RD_DB(rdataset);
674 1.1 christos
675 1.1 christos /*
676 1.1 christos * Detach the previous RR.
677 1.1 christos */
678 1.1 christos if (RD_CUR_RR(rdataset) != NULL) {
679 1.1 christos free(RD_CUR_RR(rdataset));
680 1.1 christos RD_CUR_RR(rdataset) = NULL;
681 1.1 christos }
682 1.1 christos
683 1.1 christos /*
684 1.1 christos * Get the next RR of the specified type.
685 1.1 christos * SOAs differ.
686 1.1 christos */
687 1.1 christos if (rdataset->type == dns_rdatatype_soa) {
688 1.5 christos if (RD_NEXT_RR(rdataset) == LIBRPZ_IDX_NULL) {
689 1.13 christos return ISC_R_NOMORE;
690 1.5 christos }
691 1.1 christos RD_NEXT_RR(rdataset) = LIBRPZ_IDX_NULL;
692 1.5 christos if (!librpz->rsp_soa(&emsg, NULL, &rr, NULL, &rpsdb->result,
693 1.9 christos rpsdb->rsp))
694 1.9 christos {
695 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
696 1.13 christos return DNS_R_SERVFAIL;
697 1.1 christos }
698 1.1 christos RD_CUR_RR(rdataset) = rr;
699 1.13 christos return ISC_R_SUCCESS;
700 1.1 christos }
701 1.1 christos
702 1.1 christos rpsdb->result.next_rr = RD_NEXT_RR(rdataset);
703 1.1 christos for (;;) {
704 1.1 christos if (!librpz->rsp_rr(&emsg, &type, &class, NULL, &rr,
705 1.1 christos &rpsdb->result, rpsdb->qname->ndata,
706 1.5 christos rpsdb->qname->length, rpsdb->rsp))
707 1.5 christos {
708 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
709 1.13 christos return DNS_R_SERVFAIL;
710 1.1 christos }
711 1.5 christos if (rdataset->type == type && rdataset->rdclass == class) {
712 1.1 christos RD_CUR_RR(rdataset) = rr;
713 1.1 christos RD_NEXT_RR(rdataset) = rpsdb->result.next_rr;
714 1.13 christos return ISC_R_SUCCESS;
715 1.1 christos }
716 1.5 christos if (type == dns_rdatatype_none) {
717 1.13 christos return ISC_R_NOMORE;
718 1.5 christos }
719 1.1 christos free(rr);
720 1.1 christos }
721 1.1 christos }
722 1.1 christos
723 1.1 christos static isc_result_t
724 1.1 christos rpsdb_rdataset_first(dns_rdataset_t *rdataset) {
725 1.13 christos dns_rpsdb_t *rpsdb = NULL;
726 1.1 christos librpz_emsg_t emsg;
727 1.1 christos
728 1.1 christos rpsdb = RD_DB(rdataset);
729 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
730 1.1 christos
731 1.1 christos if (RD_CUR_RR(rdataset) != NULL) {
732 1.1 christos free(RD_CUR_RR(rdataset));
733 1.1 christos RD_CUR_RR(rdataset) = NULL;
734 1.1 christos }
735 1.1 christos
736 1.1 christos if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
737 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
738 1.13 christos return DNS_R_SERVFAIL;
739 1.1 christos }
740 1.5 christos if (rdataset->type == dns_rdatatype_soa) {
741 1.1 christos RD_NEXT_RR(rdataset) = LIBRPZ_IDX_BAD;
742 1.5 christos } else {
743 1.1 christos RD_NEXT_RR(rdataset) = rpsdb->result.next_rr;
744 1.5 christos }
745 1.1 christos
746 1.13 christos return rpsdb_rdataset_next(rdataset);
747 1.1 christos }
748 1.1 christos
749 1.1 christos static void
750 1.1 christos rpsdb_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
751 1.13 christos dns_rpsdb_t *rpsdb = NULL;
752 1.13 christos librpz_rr_t *rr = NULL;
753 1.1 christos isc_region_t r;
754 1.1 christos
755 1.1 christos rpsdb = RD_DB(rdataset);
756 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
757 1.1 christos rr = RD_CUR_RR(rdataset);
758 1.1 christos REQUIRE(rr != NULL);
759 1.1 christos
760 1.1 christos r.length = ntohs(rr->rdlength);
761 1.1 christos r.base = rr->rdata;
762 1.1 christos dns_rdata_fromregion(rdata, ntohs(rr->class), ntohs(rr->type), &r);
763 1.1 christos }
764 1.1 christos
765 1.1 christos static void
766 1.13 christos rpsdb_rdataset_clone(dns_rdataset_t *source,
767 1.13 christos dns_rdataset_t *target DNS__DB_FLARG) {
768 1.13 christos dns_rpsdb_t *rpsdb = NULL;
769 1.13 christos dns_db_t *dbp = NULL;
770 1.1 christos
771 1.1 christos INSIST(!ISC_LINK_LINKED(target, link));
772 1.1 christos *target = *source;
773 1.1 christos ISC_LINK_INIT(target, link);
774 1.1 christos rpsdb = RD_DB(source);
775 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
776 1.1 christos dbp = NULL;
777 1.1 christos dns_db_attach(&rpsdb->common, &dbp);
778 1.13 christos RD_DB(target) = (dns_rpsdb_t *)dbp;
779 1.1 christos RD_CUR_RR(target) = NULL;
780 1.1 christos RD_NEXT_RR(target) = LIBRPZ_IDX_NULL;
781 1.1 christos }
782 1.1 christos
783 1.1 christos static unsigned int
784 1.1 christos rpsdb_rdataset_count(dns_rdataset_t *rdataset) {
785 1.13 christos dns_rpsdb_t *rpsdb = NULL;
786 1.1 christos
787 1.1 christos rpsdb = RD_DB(rdataset);
788 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
789 1.1 christos
790 1.13 christos return RD_COUNT(rdataset);
791 1.1 christos }
792 1.1 christos
793 1.1 christos static void
794 1.13 christos rpsdb_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) {
795 1.13 christos dns_rpsdb_t *rpsdb = NULL;
796 1.13 christos dns_rdatasetiter_t *iterator = NULL;
797 1.13 christos isc_mem_t *mctx = NULL;
798 1.1 christos
799 1.1 christos iterator = *iteratorp;
800 1.5 christos *iteratorp = NULL;
801 1.13 christos rpsdb = (dns_rpsdb_t *)iterator->db;
802 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
803 1.1 christos
804 1.1 christos mctx = iterator->db->mctx;
805 1.1 christos dns_db_detachnode(iterator->db, &iterator->node);
806 1.1 christos isc_mem_put(mctx, iterator, sizeof(rpsdb_rdatasetiter_t));
807 1.1 christos }
808 1.1 christos
809 1.1 christos static isc_result_t
810 1.13 christos rpsdb_rdatasetiter_next(dns_rdatasetiter_t *iter DNS__DB_FLARG) {
811 1.13 christos dns_rpsdb_t *rpsdb = NULL;
812 1.13 christos rpsdb_rdatasetiter_t *rpsdb_iter = NULL;
813 1.1 christos dns_rdatatype_t next_type, type;
814 1.1 christos dns_rdataclass_t next_class, class;
815 1.1 christos uint32_t ttl;
816 1.1 christos librpz_emsg_t emsg;
817 1.1 christos
818 1.13 christos rpsdb = (dns_rpsdb_t *)iter->db;
819 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
820 1.1 christos rpsdb_iter = (rpsdb_rdatasetiter_t *)iter;
821 1.1 christos
822 1.1 christos /*
823 1.1 christos * This function is only used after a policy has been chosen,
824 1.1 christos * and so without caring whether it is after recursion.
825 1.1 christos */
826 1.1 christos if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
827 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
828 1.13 christos return DNS_R_SERVFAIL;
829 1.1 christos }
830 1.1 christos /*
831 1.1 christos * Find the next class and type after the current class and type
832 1.1 christos * among the RRs in current result.
833 1.1 christos * As a side effect, count the number of those RRs.
834 1.1 christos */
835 1.1 christos rpsdb_iter->count = 0;
836 1.1 christos next_class = dns_rdataclass_reserved0;
837 1.1 christos next_type = dns_rdatatype_none;
838 1.1 christos for (;;) {
839 1.5 christos if (!librpz->rsp_rr(&emsg, &type, &class, &ttl, NULL,
840 1.5 christos &rpsdb->result, rpsdb->qname->ndata,
841 1.5 christos rpsdb->qname->length, rpsdb->rsp))
842 1.5 christos {
843 1.1 christos librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
844 1.13 christos return DNS_R_SERVFAIL;
845 1.1 christos }
846 1.1 christos if (type == dns_rdatatype_none) {
847 1.5 christos if (next_type == dns_rdatatype_none) {
848 1.13 christos return ISC_R_NOMORE;
849 1.5 christos }
850 1.1 christos rpsdb_iter->type = next_type;
851 1.1 christos rpsdb_iter->class = next_class;
852 1.13 christos return ISC_R_SUCCESS;
853 1.1 christos }
854 1.1 christos /*
855 1.1 christos * Skip RRs with the current class and type or before.
856 1.1 christos */
857 1.1 christos if (rpsdb_iter->class > class ||
858 1.1 christos (rpsdb_iter->class = class && rpsdb_iter->type >= type))
859 1.5 christos {
860 1.1 christos continue;
861 1.5 christos }
862 1.5 christos if (next_type == dns_rdatatype_none || next_class > class ||
863 1.5 christos (next_class == class && next_type > type))
864 1.5 christos {
865 1.1 christos /*
866 1.1 christos * This is the first of a subsequent class and type.
867 1.1 christos */
868 1.1 christos next_type = type;
869 1.1 christos next_class = class;
870 1.1 christos rpsdb_iter->ttl = ttl;
871 1.1 christos rpsdb_iter->count = 1;
872 1.1 christos rpsdb_iter->next_rr = rpsdb->result.next_rr;
873 1.1 christos } else if (next_type == type && next_class == class) {
874 1.1 christos ++rpsdb_iter->count;
875 1.1 christos }
876 1.1 christos }
877 1.1 christos }
878 1.1 christos
879 1.1 christos static isc_result_t
880 1.13 christos rpsdb_rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
881 1.13 christos dns_rpsdb_t *rpsdb = NULL;
882 1.13 christos rpsdb_rdatasetiter_t *rpsdb_iter = NULL;
883 1.1 christos
884 1.13 christos rpsdb = (dns_rpsdb_t *)iterator->db;
885 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
886 1.1 christos rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator;
887 1.1 christos
888 1.1 christos rpsdb_iter->type = dns_rdatatype_none;
889 1.1 christos rpsdb_iter->class = dns_rdataclass_reserved0;
890 1.13 christos return rpsdb_rdatasetiter_next(iterator DNS__DB_FLARG_PASS);
891 1.1 christos }
892 1.1 christos
893 1.1 christos static void
894 1.1 christos rpsdb_rdatasetiter_current(dns_rdatasetiter_t *iterator,
895 1.13 christos dns_rdataset_t *rdataset DNS__DB_FLARG) {
896 1.13 christos dns_rpsdb_t *rpsdb = NULL;
897 1.13 christos rpsdb_rdatasetiter_t *rpsdb_iter = NULL;
898 1.1 christos
899 1.13 christos rpsdb = (dns_rpsdb_t *)iterator->db;
900 1.1 christos REQUIRE(VALID_RPSDB(rpsdb));
901 1.1 christos rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator;
902 1.1 christos REQUIRE(rpsdb_iter->type != dns_rdatatype_none);
903 1.1 christos
904 1.5 christos rpsdb_bind_rdataset(rdataset, rpsdb_iter->count, rpsdb_iter->next_rr,
905 1.5 christos rpsdb_iter->type, rpsdb_iter->class,
906 1.5 christos rpsdb_iter->ttl, rpsdb);
907 1.1 christos }
908 1.1 christos
909 1.1 christos static dns_dbmethods_t rpsdb_db_methods = {
910 1.13 christos .destroy = rpsdb_destroy,
911 1.13 christos .findnode = rpsdb_findnode,
912 1.13 christos .find = rpsdb_finddb,
913 1.13 christos .attachnode = rpsdb_attachnode,
914 1.13 christos .detachnode = rpsdb_detachnode,
915 1.13 christos .findrdataset = rpsdb_findrdataset,
916 1.13 christos .allrdatasets = rpsdb_allrdatasets,
917 1.13 christos .issecure = rpsdb_issecure,
918 1.13 christos .getoriginnode = rpsdb_getoriginnode,
919 1.1 christos };
920 1.1 christos
921 1.1 christos static dns_rdatasetmethods_t rpsdb_rdataset_methods = {
922 1.13 christos .disassociate = rpsdb_rdataset_disassociate,
923 1.13 christos .first = rpsdb_rdataset_first,
924 1.13 christos .next = rpsdb_rdataset_next,
925 1.13 christos .current = rpsdb_rdataset_current,
926 1.13 christos .clone = rpsdb_rdataset_clone,
927 1.13 christos .count = rpsdb_rdataset_count,
928 1.1 christos };
929 1.1 christos
930 1.1 christos static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods = {
931 1.5 christos rpsdb_rdatasetiter_destroy, rpsdb_rdatasetiter_first,
932 1.5 christos rpsdb_rdatasetiter_next, rpsdb_rdatasetiter_current
933 1.1 christos };
934 1.1 christos
935 1.1 christos #endif /* USE_DNSRPS */
936