dnsrps.c revision 1.7
1/* $NetBSD: dnsrps.c,v 1.7 2021/04/05 11:36:55 rillig 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 https://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 <inttypes.h> 17#include <stdbool.h> 18 19#ifdef USE_DNSRPS 20 21#include <stdlib.h> 22 23#include <isc/mem.h> 24#include <isc/string.h> 25#include <isc/util.h> 26 27#include <dns/db.h> 28#define LIBRPZ_LIB_OPEN DNSRPS_LIB_OPEN 29#include <dns/dnsrps.h> 30#include <dns/rdataset.h> 31#include <dns/rdatasetiter.h> 32#include <dns/result.h> 33#include <dns/rpz.h> 34 35librpz_t *librpz; 36librpz_emsg_t librpz_lib_open_emsg; 37static void *librpz_handle; 38 39#define RPSDB_MAGIC ISC_MAGIC('R', 'P', 'Z', 'F') 40#define VALID_RPSDB(rpsdb) ((rpsdb)->common.impmagic == RPSDB_MAGIC) 41 42#define RD_DB(r) ((r)->private1) 43#define RD_CUR_RR(r) ((r)->private2) 44#define RD_NEXT_RR(r) ((r)->resign) 45#define RD_COUNT(r) ((r)->privateuint4) 46 47typedef struct { 48 dns_rdatasetiter_t common; 49 dns_rdatatype_t type; 50 dns_rdataclass_t class; 51 uint32_t ttl; 52 uint count; 53 librpz_idx_t next_rr; 54} rpsdb_rdatasetiter_t; 55 56static dns_dbmethods_t rpsdb_db_methods; 57static dns_rdatasetmethods_t rpsdb_rdataset_methods; 58static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods; 59 60static librpz_clist_t *clist; 61 62static isc_mutex_t dnsrps_mutex; 63 64static void 65dnsrps_lock(void *mutex0) { 66 isc_mutex_t *mutex = mutex0; 67 68 LOCK(mutex); 69} 70 71static void 72dnsrps_unlock(void *mutex0) { 73 isc_mutex_t *mutex = mutex0; 74 75 UNLOCK(mutex); 76} 77 78static void 79dnsrps_mutex_destroy(void *mutex0) { 80 isc_mutex_t *mutex = mutex0; 81 82 isc_mutex_destroy(mutex); 83} 84 85static void 86dnsrps_log_fnc(librpz_log_level_t level, void *ctxt, const char *buf) { 87 int isc_level; 88 89 UNUSED(ctxt); 90 91 /* Setting librpz_log_level in the configuration overrides the 92 * BIND9 logging levels. */ 93 if (level > LIBRPZ_LOG_TRACE1 && 94 level <= librpz->log_level_val(LIBRPZ_LOG_INVALID)) 95 { 96 level = LIBRPZ_LOG_TRACE1; 97 } 98 99 switch (level) { 100 case LIBRPZ_LOG_FATAL: 101 case LIBRPZ_LOG_ERROR: /* errors */ 102 default: 103 isc_level = DNS_RPZ_ERROR_LEVEL; 104 break; 105 106 case LIBRPZ_LOG_TRACE1: /* big events such as dnsrpzd starts */ 107 isc_level = DNS_RPZ_INFO_LEVEL; 108 break; 109 110 case LIBRPZ_LOG_TRACE2: /* smaller dnsrpzd zone transfers */ 111 isc_level = DNS_RPZ_DEBUG_LEVEL1; 112 break; 113 114 case LIBRPZ_LOG_TRACE3: /* librpz hits */ 115 isc_level = DNS_RPZ_DEBUG_LEVEL2; 116 break; 117 118 case LIBRPZ_LOG_TRACE4: /* librpz lookups */ 119 isc_level = DNS_RPZ_DEBUG_LEVEL3; 120 break; 121 } 122 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB, 123 isc_level, "dnsrps: %s", buf); 124} 125 126/* 127 * Start dnsrps for the entire server. 128 * This is not thread safe, but it is called by a single thread. 129 */ 130isc_result_t 131dns_dnsrps_server_create(void) { 132 librpz_emsg_t emsg; 133 134 INSIST(clist == NULL); 135 INSIST(librpz == NULL); 136 INSIST(librpz_handle == NULL); 137 138 /* 139 * Notice if librpz is available. 140 */ 141 librpz = librpz_lib_open(&librpz_lib_open_emsg, &librpz_handle, 142 DNSRPS_LIBRPZ_PATH); 143 /* 144 * Stop now without complaining if librpz is not available. 145 * Complain later if and when librpz is needed for a view with 146 * "dnsrps-enable yes" (including the default view). 147 */ 148 if (librpz == NULL) { 149 return (ISC_R_SUCCESS); 150 } 151 152 isc_mutex_init(&dnsrps_mutex); 153 154 librpz->set_log(dnsrps_log_fnc, NULL); 155 156 clist = librpz->clist_create(&emsg, dnsrps_lock, dnsrps_unlock, 157 dnsrps_mutex_destroy, &dnsrps_mutex, 158 dns_lctx); 159 if (clist == NULL) { 160 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, 161 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, 162 "dnsrps: %s", emsg.c); 163 return (ISC_R_NOMEMORY); 164 } 165 return (ISC_R_SUCCESS); 166} 167 168/* 169 * Stop dnsrps for the entire server. 170 * This is not thread safe. 171 */ 172void 173dns_dnsrps_server_destroy(void) { 174 if (clist != NULL) { 175 librpz->clist_detach(&clist); 176 } 177 178#ifdef LIBRPZ_USE_DLOPEN 179 if (librpz != NULL) { 180 INSIST(librpz_handle != NULL); 181 if (dlclose(librpz_handle) != 0) { 182 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, 183 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, 184 "dnsrps: dlclose(): %s", dlerror()); 185 } 186 librpz_handle = NULL; 187 } 188#endif /* ifdef LIBRPZ_USE_DLOPEN */ 189} 190 191/* 192 * Ready dnsrps for a view. 193 */ 194isc_result_t 195dns_dnsrps_view_init(dns_rpz_zones_t *new, char *rps_cstr) { 196 librpz_emsg_t emsg; 197 198 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB, 199 DNS_RPZ_DEBUG_LEVEL3, "dnsrps configuration \"%s\"", 200 rps_cstr); 201 202 new->rps_client = librpz->client_create(&emsg, clist, rps_cstr, false); 203 if (new->rps_client == NULL) { 204 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, 205 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, 206 "librpz->client_create(): %s", emsg.c); 207 new->p.dnsrps_enabled = false; 208 return (ISC_R_FAILURE); 209 } 210 211 new->p.dnsrps_enabled = true; 212 return (ISC_R_SUCCESS); 213} 214 215/* 216 * Connect to and start the dnsrps daemon, dnsrpzd. 217 */ 218isc_result_t 219dns_dnsrps_connect(dns_rpz_zones_t *rpzs) { 220 librpz_emsg_t emsg; 221 222 if (rpzs == NULL || !rpzs->p.dnsrps_enabled) { 223 return (ISC_R_SUCCESS); 224 } 225 226 /* 227 * Fail only if we failed to link to librpz. 228 */ 229 if (librpz == NULL) { 230 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, 231 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, 232 "librpz->connect(): %s", librpz_lib_open_emsg.c); 233 return (ISC_R_FAILURE); 234 } 235 236 if (!librpz->connect(&emsg, rpzs->rps_client, true)) { 237 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, 238 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, 239 "librpz->connect(): %s", emsg.c); 240 return (ISC_R_SUCCESS); 241 } 242 243 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB, 244 DNS_RPZ_INFO_LEVEL, "dnsrps: librpz version %s", 245 librpz->version); 246 247 return (ISC_R_SUCCESS); 248} 249 250/* 251 * Get ready to try RPZ rewriting. 252 */ 253isc_result_t 254dns_dnsrps_rewrite_init(librpz_emsg_t *emsg, dns_rpz_st_t *st, 255 dns_rpz_zones_t *rpzs, const dns_name_t *qname, 256 isc_mem_t *mctx, bool have_rd) { 257 rpsdb_t *rpsdb; 258 259 rpsdb = isc_mem_get(mctx, sizeof(*rpsdb)); 260 memset(rpsdb, 0, sizeof(*rpsdb)); 261 262 if (!librpz->rsp_create(emsg, &rpsdb->rsp, NULL, rpzs->rps_client, 263 have_rd, false)) 264 { 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 391 librpz->rsp_detach(&rpsdb->rsp); 392 rpsdb->common.impmagic = 0; 393 isc_mem_putanddetach(&rpsdb->common.mctx, rpsdb, sizeof(*rpsdb)); 394} 395 396static void 397rpsdb_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { 398 rpsdb_t *rpsdb = (rpsdb_t *)db; 399 400 REQUIRE(VALID_RPSDB(rpsdb)); 401 REQUIRE(targetp != NULL && *targetp == NULL); 402 REQUIRE(source == &rpsdb->origin_node || 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 rpsdb_t *rpsdb = (rpsdb_t *)db; 427 dns_db_t *dbp; 428 429 REQUIRE(VALID_RPSDB(rpsdb)); 430 REQUIRE(nodep != NULL && *nodep == NULL); 431 REQUIRE(!create); 432 433 /* 434 * A fake/shim rpsdb has two nodes. 435 * One is the origin to support query_addsoa() in bin/named/query.c. 436 * The other contains rewritten RRs. 437 */ 438 if (dns_name_equal(name, &db->origin)) { 439 *nodep = &rpsdb->origin_node; 440 } else { 441 *nodep = &rpsdb->data_node; 442 } 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 dns_db_t *dbp; 454 455 INSIST(rdataset->methods == NULL); /* We must be disassociated. */ 456 REQUIRE(type != dns_rdatatype_none); 457 458 rdataset->methods = &rpsdb_rdataset_methods; 459 rdataset->rdclass = class; 460 rdataset->type = type; 461 rdataset->ttl = ttl; 462 dbp = NULL; 463 dns_db_attach(&rpsdb->common, &dbp); 464 RD_DB(rdataset) = dbp; 465 RD_COUNT(rdataset) = count; 466 RD_NEXT_RR(rdataset) = next_rr; 467 RD_CUR_RR(rdataset) = NULL; 468} 469 470static isc_result_t 471rpsdb_bind_soa(dns_rdataset_t *rdataset, rpsdb_t *rpsdb) { 472 uint32_t ttl; 473 librpz_emsg_t emsg; 474 475 if (!librpz->rsp_soa(&emsg, &ttl, NULL, NULL, &rpsdb->result, 476 rpsdb->rsp)) { 477 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 478 return (DNS_R_SERVFAIL); 479 } 480 rpsdb_bind_rdataset(rdataset, 1, LIBRPZ_IDX_BAD, dns_rdatatype_soa, 481 dns_rdataclass_in, ttl, rpsdb); 482 return (ISC_R_SUCCESS); 483} 484 485/* 486 * Forge an rdataset of the desired type from a librpz result. 487 * This is written for simplicity instead of speed, because RPZ rewriting 488 * should be rare compared to normal BIND operations. 489 */ 490static isc_result_t 491rpsdb_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 492 dns_rdatatype_t type, dns_rdatatype_t covers, 493 isc_stdtime_t now, dns_rdataset_t *rdataset, 494 dns_rdataset_t *sigrdataset) { 495 rpsdb_t *rpsdb = (rpsdb_t *)db; 496 dns_rdatatype_t foundtype; 497 dns_rdataclass_t class; 498 uint32_t ttl; 499 uint count; 500 librpz_emsg_t emsg; 501 502 UNUSED(version); 503 UNUSED(covers); 504 UNUSED(now); 505 UNUSED(sigrdataset); 506 507 REQUIRE(VALID_RPSDB(rpsdb)); 508 509 if (node == &rpsdb->origin_node) { 510 if (type == dns_rdatatype_any) { 511 return (ISC_R_SUCCESS); 512 } 513 if (type == dns_rdatatype_soa) { 514 return (rpsdb_bind_soa(rdataset, rpsdb)); 515 } 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 /* 551 * There is little to do for an ANY query. 552 */ 553 if (type == dns_rdatatype_any) { 554 return (ISC_R_SUCCESS); 555 } 556 557 /* 558 * Reset to the start of the RRs. 559 * This function is only used after a policy has been chosen, 560 * and so without caring whether it is after recursion. 561 */ 562 if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) { 563 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 564 return (DNS_R_SERVFAIL); 565 } 566 if (!librpz->rsp_rr(&emsg, &foundtype, &class, &ttl, NULL, 567 &rpsdb->result, rpsdb->qname->ndata, 568 rpsdb->qname->length, rpsdb->rsp)) 569 { 570 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 571 return (DNS_R_SERVFAIL); 572 } 573 REQUIRE(foundtype != dns_rdatatype_none); 574 575 /* 576 * Ho many of the target RR type are available? 577 */ 578 count = 0; 579 do { 580 if (type == foundtype || type == dns_rdatatype_any) { 581 ++count; 582 } 583 584 if (!librpz->rsp_rr(&emsg, &foundtype, NULL, NULL, NULL, 585 &rpsdb->result, rpsdb->qname->ndata, 586 rpsdb->qname->length, rpsdb->rsp)) 587 { 588 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 589 return (DNS_R_SERVFAIL); 590 } 591 } while (foundtype != dns_rdatatype_none); 592 if (count == 0) { 593 return (DNS_R_NXRRSET); 594 } 595 rpsdb_bind_rdataset(rdataset, count, rpsdb->result.next_rr, type, class, 596 ttl, rpsdb); 597 return (ISC_R_SUCCESS); 598} 599 600static isc_result_t 601rpsdb_finddb(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 602 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 603 dns_dbnode_t **nodep, dns_name_t *foundname, 604 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 605 dns_dbnode_t *node; 606 607 UNUSED(version); 608 UNUSED(options); 609 UNUSED(now); 610 UNUSED(sigrdataset); 611 612 if (nodep == NULL) { 613 node = NULL; 614 nodep = &node; 615 } 616 rpsdb_findnode(db, name, false, nodep); 617 dns_name_copynf(name, foundname); 618 return (rpsdb_findrdataset(db, *nodep, NULL, type, 0, 0, rdataset, 619 sigrdataset)); 620} 621 622static isc_result_t 623rpsdb_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 624 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) { 625 rpsdb_t *rpsdb = (rpsdb_t *)db; 626 rpsdb_rdatasetiter_t *rpsdb_iter; 627 628 UNUSED(version); 629 UNUSED(now); 630 631 REQUIRE(VALID_RPSDB(rpsdb)); 632 REQUIRE(node == &rpsdb->origin_node || node == &rpsdb->data_node); 633 634 rpsdb_iter = isc_mem_get(rpsdb->common.mctx, sizeof(*rpsdb_iter)); 635 636 memset(rpsdb_iter, 0, sizeof(*rpsdb_iter)); 637 rpsdb_iter->common.magic = DNS_RDATASETITER_MAGIC; 638 rpsdb_iter->common.methods = &rpsdb_rdatasetiter_methods; 639 rpsdb_iter->common.db = db; 640 rpsdb_attachnode(db, node, &rpsdb_iter->common.node); 641 642 *iteratorp = &rpsdb_iter->common; 643 644 return (ISC_R_SUCCESS); 645} 646 647static bool 648rpsdb_issecure(dns_db_t *db) { 649 UNUSED(db); 650 651 return (false); 652} 653 654static isc_result_t 655rpsdb_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { 656 rpsdb_t *rpsdb = (rpsdb_t *)db; 657 658 REQUIRE(VALID_RPSDB(rpsdb)); 659 REQUIRE(nodep != NULL && *nodep == NULL); 660 661 rpsdb_attachnode(db, &rpsdb->origin_node, nodep); 662 return (ISC_R_SUCCESS); 663} 664 665static void 666rpsdb_rdataset_disassociate(dns_rdataset_t *rdataset) { 667 dns_db_t *db; 668 669 /* 670 * Detach the last RR delivered. 671 */ 672 if (RD_CUR_RR(rdataset) != NULL) { 673 free(RD_CUR_RR(rdataset)); 674 RD_CUR_RR(rdataset) = NULL; 675 } 676 677 db = RD_DB(rdataset); 678 RD_DB(rdataset) = NULL; 679 dns_db_detach(&db); 680} 681 682static isc_result_t 683rpsdb_rdataset_next(dns_rdataset_t *rdataset) { 684 rpsdb_t *rpsdb; 685 uint16_t type; 686 dns_rdataclass_t class; 687 librpz_rr_t *rr; 688 librpz_emsg_t emsg; 689 690 rpsdb = RD_DB(rdataset); 691 692 /* 693 * Detach the previous RR. 694 */ 695 if (RD_CUR_RR(rdataset) != NULL) { 696 free(RD_CUR_RR(rdataset)); 697 RD_CUR_RR(rdataset) = NULL; 698 } 699 700 /* 701 * Get the next RR of the specified type. 702 * SOAs differ. 703 */ 704 if (rdataset->type == dns_rdatatype_soa) { 705 if (RD_NEXT_RR(rdataset) == LIBRPZ_IDX_NULL) { 706 return (ISC_R_NOMORE); 707 } 708 RD_NEXT_RR(rdataset) = LIBRPZ_IDX_NULL; 709 if (!librpz->rsp_soa(&emsg, NULL, &rr, NULL, &rpsdb->result, 710 rpsdb->rsp)) { 711 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 712 return (DNS_R_SERVFAIL); 713 } 714 RD_CUR_RR(rdataset) = rr; 715 return (ISC_R_SUCCESS); 716 } 717 718 rpsdb->result.next_rr = RD_NEXT_RR(rdataset); 719 for (;;) { 720 if (!librpz->rsp_rr(&emsg, &type, &class, NULL, &rr, 721 &rpsdb->result, rpsdb->qname->ndata, 722 rpsdb->qname->length, rpsdb->rsp)) 723 { 724 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 725 return (DNS_R_SERVFAIL); 726 } 727 if (rdataset->type == type && rdataset->rdclass == class) { 728 RD_CUR_RR(rdataset) = rr; 729 RD_NEXT_RR(rdataset) = rpsdb->result.next_rr; 730 return (ISC_R_SUCCESS); 731 } 732 if (type == dns_rdatatype_none) { 733 return (ISC_R_NOMORE); 734 } 735 free(rr); 736 } 737} 738 739static isc_result_t 740rpsdb_rdataset_first(dns_rdataset_t *rdataset) { 741 rpsdb_t *rpsdb; 742 librpz_emsg_t emsg; 743 744 rpsdb = RD_DB(rdataset); 745 REQUIRE(VALID_RPSDB(rpsdb)); 746 747 if (RD_CUR_RR(rdataset) != NULL) { 748 free(RD_CUR_RR(rdataset)); 749 RD_CUR_RR(rdataset) = NULL; 750 } 751 752 if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) { 753 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 754 return (DNS_R_SERVFAIL); 755 } 756 if (rdataset->type == dns_rdatatype_soa) { 757 RD_NEXT_RR(rdataset) = LIBRPZ_IDX_BAD; 758 } else { 759 RD_NEXT_RR(rdataset) = rpsdb->result.next_rr; 760 } 761 762 return (rpsdb_rdataset_next(rdataset)); 763} 764 765static void 766rpsdb_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 767 rpsdb_t *rpsdb; 768 librpz_rr_t *rr; 769 isc_region_t r; 770 771 rpsdb = RD_DB(rdataset); 772 REQUIRE(VALID_RPSDB(rpsdb)); 773 rr = RD_CUR_RR(rdataset); 774 REQUIRE(rr != NULL); 775 776 r.length = ntohs(rr->rdlength); 777 r.base = rr->rdata; 778 dns_rdata_fromregion(rdata, ntohs(rr->class), ntohs(rr->type), &r); 779} 780 781static void 782rpsdb_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 783 rpsdb_t *rpsdb; 784 dns_db_t *dbp; 785 786 INSIST(!ISC_LINK_LINKED(target, link)); 787 *target = *source; 788 ISC_LINK_INIT(target, link); 789 rpsdb = RD_DB(source); 790 REQUIRE(VALID_RPSDB(rpsdb)); 791 dbp = NULL; 792 dns_db_attach(&rpsdb->common, &dbp); 793 RD_DB(target) = dbp; 794 RD_CUR_RR(target) = NULL; 795 RD_NEXT_RR(target) = LIBRPZ_IDX_NULL; 796} 797 798static unsigned int 799rpsdb_rdataset_count(dns_rdataset_t *rdataset) { 800 rpsdb_t *rpsdb; 801 802 rpsdb = RD_DB(rdataset); 803 REQUIRE(VALID_RPSDB(rpsdb)); 804 805 return (RD_COUNT(rdataset)); 806} 807 808static void 809rpsdb_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { 810 rpsdb_t *rpsdb; 811 dns_rdatasetiter_t *iterator; 812 isc_mem_t *mctx; 813 814 iterator = *iteratorp; 815 *iteratorp = NULL; 816 rpsdb = (rpsdb_t *)iterator->db; 817 REQUIRE(VALID_RPSDB(rpsdb)); 818 819 mctx = iterator->db->mctx; 820 dns_db_detachnode(iterator->db, &iterator->node); 821 isc_mem_put(mctx, iterator, sizeof(rpsdb_rdatasetiter_t)); 822} 823 824static isc_result_t 825rpsdb_rdatasetiter_next(dns_rdatasetiter_t *iter) { 826 rpsdb_t *rpsdb; 827 rpsdb_rdatasetiter_t *rpsdb_iter; 828 dns_rdatatype_t next_type, type; 829 dns_rdataclass_t next_class, class; 830 uint32_t ttl; 831 librpz_emsg_t emsg; 832 833 rpsdb = (rpsdb_t *)iter->db; 834 REQUIRE(VALID_RPSDB(rpsdb)); 835 rpsdb_iter = (rpsdb_rdatasetiter_t *)iter; 836 837 /* 838 * This function is only used after a policy has been chosen, 839 * and so without caring whether it is after recursion. 840 */ 841 if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) { 842 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 843 return (DNS_R_SERVFAIL); 844 } 845 /* 846 * Find the next class and type after the current class and type 847 * among the RRs in current result. 848 * As a side effect, count the number of those RRs. 849 */ 850 rpsdb_iter->count = 0; 851 next_class = dns_rdataclass_reserved0; 852 next_type = dns_rdatatype_none; 853 for (;;) { 854 if (!librpz->rsp_rr(&emsg, &type, &class, &ttl, NULL, 855 &rpsdb->result, rpsdb->qname->ndata, 856 rpsdb->qname->length, rpsdb->rsp)) 857 { 858 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 859 return (DNS_R_SERVFAIL); 860 } 861 if (type == dns_rdatatype_none) { 862 if (next_type == dns_rdatatype_none) { 863 return (ISC_R_NOMORE); 864 } 865 rpsdb_iter->type = next_type; 866 rpsdb_iter->class = next_class; 867 return (ISC_R_SUCCESS); 868 } 869 /* 870 * Skip RRs with the current class and type or before. 871 */ 872 if (rpsdb_iter->class > class || 873 (rpsdb_iter->class = class && rpsdb_iter->type >= type)) 874 { 875 continue; 876 } 877 if (next_type == dns_rdatatype_none || next_class > class || 878 (next_class == class && next_type > type)) 879 { 880 /* 881 * This is the first of a subsequent class and type. 882 */ 883 next_type = type; 884 next_class = class; 885 rpsdb_iter->ttl = ttl; 886 rpsdb_iter->count = 1; 887 rpsdb_iter->next_rr = rpsdb->result.next_rr; 888 } else if (next_type == type && next_class == class) { 889 ++rpsdb_iter->count; 890 } 891 } 892} 893 894static isc_result_t 895rpsdb_rdatasetiter_first(dns_rdatasetiter_t *iterator) { 896 rpsdb_t *rpsdb; 897 rpsdb_rdatasetiter_t *rpsdb_iter; 898 899 rpsdb = (rpsdb_t *)iterator->db; 900 REQUIRE(VALID_RPSDB(rpsdb)); 901 rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator; 902 903 rpsdb_iter->type = dns_rdatatype_none; 904 rpsdb_iter->class = dns_rdataclass_reserved0; 905 return (rpsdb_rdatasetiter_next(iterator)); 906} 907 908static void 909rpsdb_rdatasetiter_current(dns_rdatasetiter_t *iterator, 910 dns_rdataset_t *rdataset) { 911 rpsdb_t *rpsdb; 912 rpsdb_rdatasetiter_t *rpsdb_iter; 913 914 rpsdb = (rpsdb_t *)iterator->db; 915 REQUIRE(VALID_RPSDB(rpsdb)); 916 rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator; 917 REQUIRE(rpsdb_iter->type != dns_rdatatype_none); 918 919 rpsdb_bind_rdataset(rdataset, rpsdb_iter->count, rpsdb_iter->next_rr, 920 rpsdb_iter->type, rpsdb_iter->class, 921 rpsdb_iter->ttl, rpsdb); 922} 923 924static dns_dbmethods_t rpsdb_db_methods = { 925 rpsdb_attach, 926 rpsdb_detach, 927 NULL, /* beginload */ 928 NULL, /* endload */ 929 NULL, /* serialize */ 930 NULL, /* dump */ 931 NULL, /* currentversion */ 932 NULL, /* newversion */ 933 NULL, /* attachversion */ 934 NULL, /* closeversion */ 935 rpsdb_findnode, 936 rpsdb_finddb, 937 NULL, /* findzonecut*/ 938 rpsdb_attachnode, 939 rpsdb_detachnode, 940 NULL, /* expirenode */ 941 NULL, /* printnode */ 942 NULL, /* createiterator */ 943 rpsdb_findrdataset, 944 rpsdb_allrdatasets, 945 NULL, /* addrdataset */ 946 NULL, /* subtractrdataset */ 947 NULL, /* deleterdataset */ 948 rpsdb_issecure, 949 NULL, /* nodecount */ 950 NULL, /* ispersistent */ 951 NULL, /* overmem */ 952 NULL, /* settask */ 953 rpsdb_getoriginnode, 954 NULL, /* transfernode */ 955 NULL, /* getnsec3parameters */ 956 NULL, /* findnsec3node */ 957 NULL, /* setsigningtime */ 958 NULL, /* getsigningtime */ 959 NULL, /* resigned */ 960 NULL, /* isdnssec */ 961 NULL, /* getrrsetstats */ 962 NULL, /* rpz_attach */ 963 NULL, /* rpz_ready */ 964 NULL, /* findnodeext */ 965 NULL, /* findext */ 966 NULL, /* setcachestats */ 967 NULL, /* hashsize */ 968 NULL, /* nodefullname */ 969 NULL, /* getsize */ 970 NULL, /* setservestalettl */ 971 NULL, /* getservestalettl */ 972 NULL, /* setservestalerefresh */ 973 NULL, /* getservestalerefresh */ 974 NULL, /* setgluecachestats */ 975 NULL /* adjusthashsize */ 976}; 977 978static dns_rdatasetmethods_t rpsdb_rdataset_methods = { 979 rpsdb_rdataset_disassociate, 980 rpsdb_rdataset_first, 981 rpsdb_rdataset_next, 982 rpsdb_rdataset_current, 983 rpsdb_rdataset_clone, 984 rpsdb_rdataset_count, 985 NULL, 986 NULL, 987 NULL, 988 NULL, 989 NULL, 990 NULL, 991 NULL, 992 NULL, 993 NULL, 994 NULL 995}; 996 997static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods = { 998 rpsdb_rdatasetiter_destroy, rpsdb_rdatasetiter_first, 999 rpsdb_rdatasetiter_next, rpsdb_rdatasetiter_current 1000}; 1001 1002#endif /* USE_DNSRPS */ 1003