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