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