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