dnsrps.c revision 1.3
1/* $NetBSD: dnsrps.c,v 1.3 2019/01/09 16:55:11 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 isc_result_t result; 602 603 UNUSED(version); 604 UNUSED(options); 605 UNUSED(now); 606 UNUSED(sigrdataset); 607 608 if (nodep == NULL) { 609 node = NULL; 610 nodep = &node; 611 } 612 rpsdb_findnode(db, name, false, nodep); 613 result = dns_name_copy(name, foundname, NULL); 614 if (result != ISC_R_SUCCESS) 615 return (result); 616 return (rpsdb_findrdataset(db, *nodep, NULL, type, 0, 0, 617 rdataset, sigrdataset)); 618} 619 620static isc_result_t 621rpsdb_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 622 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) 623{ 624 rpsdb_t *rpsdb = (rpsdb_t *)db; 625 rpsdb_rdatasetiter_t *rpsdb_iter; 626 627 UNUSED(version); 628 UNUSED(now); 629 630 REQUIRE(VALID_RPSDB(rpsdb)); 631 REQUIRE(node == &rpsdb->origin_node || node == &rpsdb->data_node); 632 633 rpsdb_iter = isc_mem_get(rpsdb->common.mctx, sizeof(*rpsdb_iter)); 634 if (rpsdb_iter == NULL) 635 return (ISC_R_NOMEMORY); 636 637 memset(rpsdb_iter, 0, sizeof(*rpsdb_iter)); 638 rpsdb_iter->common.magic = DNS_RDATASETITER_MAGIC; 639 rpsdb_iter->common.methods = &rpsdb_rdatasetiter_methods; 640 rpsdb_iter->common.db = db; 641 rpsdb_attachnode(db, node, &rpsdb_iter->common.node); 642 643 *iteratorp = &rpsdb_iter->common; 644 645 return (ISC_R_SUCCESS); 646} 647 648static bool 649rpsdb_issecure(dns_db_t *db) { 650 UNUSED(db); 651 652 return (false); 653} 654 655static isc_result_t 656rpsdb_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { 657 rpsdb_t *rpsdb = (rpsdb_t *)db; 658 659 REQUIRE(VALID_RPSDB(rpsdb)); 660 REQUIRE(nodep != NULL && *nodep == NULL); 661 662 rpsdb_attachnode(db, &rpsdb->origin_node, nodep); 663 return (ISC_R_SUCCESS); 664} 665 666static void 667rpsdb_rdataset_disassociate(dns_rdataset_t *rdataset) { 668 dns_db_t *db; 669 670 /* 671 * Detach the last RR delivered. 672 */ 673 if (RD_CUR_RR(rdataset) != NULL) { 674 free(RD_CUR_RR(rdataset)); 675 RD_CUR_RR(rdataset) = NULL; 676 } 677 678 db = RD_DB(rdataset); 679 RD_DB(rdataset) = NULL; 680 dns_db_detach(&db); 681} 682 683static isc_result_t 684rpsdb_rdataset_next(dns_rdataset_t *rdataset) { 685 rpsdb_t *rpsdb; 686 uint16_t type; 687 dns_rdataclass_t class; 688 librpz_rr_t *rr; 689 librpz_emsg_t emsg; 690 691 rpsdb = RD_DB(rdataset); 692 693 /* 694 * Detach the previous RR. 695 */ 696 if (RD_CUR_RR(rdataset) != NULL) { 697 free(RD_CUR_RR(rdataset)); 698 RD_CUR_RR(rdataset) = NULL; 699 } 700 701 /* 702 * Get the next RR of the specified type. 703 * SOAs differ. 704 */ 705 if (rdataset->type == dns_rdatatype_soa) { 706 if (RD_NEXT_RR(rdataset) == LIBRPZ_IDX_NULL) 707 return (ISC_R_NOMORE); 708 RD_NEXT_RR(rdataset) = LIBRPZ_IDX_NULL; 709 if (!librpz->rsp_soa(&emsg, NULL, &rr, NULL, 710 &rpsdb->result, 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 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 724 return (DNS_R_SERVFAIL); 725 } 726 if (rdataset->type == type && 727 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 free(rr); 735 } 736} 737 738static isc_result_t 739rpsdb_rdataset_first(dns_rdataset_t *rdataset) { 740 rpsdb_t *rpsdb; 741 librpz_emsg_t emsg; 742 743 rpsdb = RD_DB(rdataset); 744 REQUIRE(VALID_RPSDB(rpsdb)); 745 746 if (RD_CUR_RR(rdataset) != NULL) { 747 free(RD_CUR_RR(rdataset)); 748 RD_CUR_RR(rdataset) = NULL; 749 } 750 751 if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) { 752 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 753 return (DNS_R_SERVFAIL); 754 } 755 if (rdataset->type == dns_rdatatype_soa) 756 RD_NEXT_RR(rdataset) = LIBRPZ_IDX_BAD; 757 else 758 RD_NEXT_RR(rdataset) = rpsdb->result.next_rr; 759 760 return (rpsdb_rdataset_next(rdataset)); 761} 762 763static void 764rpsdb_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 765 rpsdb_t *rpsdb; 766 librpz_rr_t *rr; 767 isc_region_t r; 768 769 rpsdb = RD_DB(rdataset); 770 REQUIRE(VALID_RPSDB(rpsdb)); 771 rr = RD_CUR_RR(rdataset); 772 REQUIRE(rr != NULL); 773 774 r.length = ntohs(rr->rdlength); 775 r.base = rr->rdata; 776 dns_rdata_fromregion(rdata, ntohs(rr->class), ntohs(rr->type), &r); 777} 778 779static void 780rpsdb_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 781 rpsdb_t *rpsdb; 782 dns_db_t *dbp; 783 784 INSIST(!ISC_LINK_LINKED(target, link)); 785 *target = *source; 786 ISC_LINK_INIT(target, link); 787 rpsdb = RD_DB(source); 788 REQUIRE(VALID_RPSDB(rpsdb)); 789 dbp = NULL; 790 dns_db_attach(&rpsdb->common, &dbp); 791 RD_DB(target) = dbp; 792 RD_CUR_RR(target) = NULL; 793 RD_NEXT_RR(target) = LIBRPZ_IDX_NULL; 794} 795 796static unsigned int 797rpsdb_rdataset_count(dns_rdataset_t *rdataset) { 798 rpsdb_t *rpsdb; 799 800 rpsdb = RD_DB(rdataset); 801 REQUIRE(VALID_RPSDB(rpsdb)); 802 803 return (RD_COUNT(rdataset)); 804} 805 806static void 807rpsdb_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { 808 rpsdb_t *rpsdb; 809 dns_rdatasetiter_t *iterator; 810 isc_mem_t *mctx; 811 812 iterator = *iteratorp; 813 rpsdb = (rpsdb_t *)iterator->db; 814 REQUIRE(VALID_RPSDB(rpsdb)); 815 816 mctx = iterator->db->mctx; 817 dns_db_detachnode(iterator->db, &iterator->node); 818 isc_mem_put(mctx, iterator, sizeof(rpsdb_rdatasetiter_t)); 819 *iteratorp = NULL; 820} 821 822static isc_result_t 823rpsdb_rdatasetiter_next(dns_rdatasetiter_t *iter) { 824 rpsdb_t *rpsdb; 825 rpsdb_rdatasetiter_t *rpsdb_iter; 826 dns_rdatatype_t next_type, type; 827 dns_rdataclass_t next_class, class; 828 uint32_t ttl; 829 librpz_emsg_t emsg; 830 831 rpsdb = (rpsdb_t *)iter->db; 832 REQUIRE(VALID_RPSDB(rpsdb)); 833 rpsdb_iter = (rpsdb_rdatasetiter_t *)iter; 834 835 /* 836 * This function is only used after a policy has been chosen, 837 * and so without caring whether it is after recursion. 838 */ 839 if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) { 840 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 841 return (DNS_R_SERVFAIL); 842 } 843 /* 844 * Find the next class and type after the current class and type 845 * among the RRs in current result. 846 * As a side effect, count the number of those RRs. 847 */ 848 rpsdb_iter->count = 0; 849 next_class = dns_rdataclass_reserved0; 850 next_type = dns_rdatatype_none; 851 for (;;) { 852 if (!librpz->rsp_rr(&emsg, &type, &class, &ttl, 853 NULL, &rpsdb->result, rpsdb->qname->ndata, 854 rpsdb->qname->length, rpsdb->rsp)) { 855 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c); 856 return (DNS_R_SERVFAIL); 857 } 858 if (type == dns_rdatatype_none) { 859 if (next_type == dns_rdatatype_none) 860 return (ISC_R_NOMORE); 861 rpsdb_iter->type = next_type; 862 rpsdb_iter->class = next_class; 863 return (ISC_R_SUCCESS); 864 } 865 /* 866 * Skip RRs with the current class and type or before. 867 */ 868 if (rpsdb_iter->class > class || 869 (rpsdb_iter->class = class && rpsdb_iter->type >= type)) 870 continue; 871 if (next_type == dns_rdatatype_none || 872 next_class > class || 873 (next_class == class && next_type > type)) { 874 /* 875 * This is the first of a subsequent class and type. 876 */ 877 next_type = type; 878 next_class = class; 879 rpsdb_iter->ttl = ttl; 880 rpsdb_iter->count = 1; 881 rpsdb_iter->next_rr = rpsdb->result.next_rr; 882 } else if (next_type == type && next_class == class) { 883 ++rpsdb_iter->count; 884 } 885 } 886} 887 888static isc_result_t 889rpsdb_rdatasetiter_first(dns_rdatasetiter_t *iterator) { 890 rpsdb_t *rpsdb; 891 rpsdb_rdatasetiter_t *rpsdb_iter; 892 893 rpsdb = (rpsdb_t *)iterator->db; 894 REQUIRE(VALID_RPSDB(rpsdb)); 895 rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator; 896 897 rpsdb_iter->type = dns_rdatatype_none; 898 rpsdb_iter->class = dns_rdataclass_reserved0; 899 return (rpsdb_rdatasetiter_next(iterator)); 900} 901 902static void 903rpsdb_rdatasetiter_current(dns_rdatasetiter_t *iterator, 904 dns_rdataset_t *rdataset) 905{ 906 rpsdb_t *rpsdb; 907 rpsdb_rdatasetiter_t *rpsdb_iter; 908 909 rpsdb = (rpsdb_t *)iterator->db; 910 REQUIRE(VALID_RPSDB(rpsdb)); 911 rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator; 912 REQUIRE(rpsdb_iter->type != dns_rdatatype_none); 913 914 rpsdb_bind_rdataset(rdataset, 915 rpsdb_iter->count, rpsdb_iter->next_rr, 916 rpsdb_iter->type, rpsdb_iter->class, 917 rpsdb_iter->ttl, rpsdb); 918} 919 920static dns_dbmethods_t rpsdb_db_methods = { 921 rpsdb_attach, 922 rpsdb_detach, 923 NULL, /* beginload */ 924 NULL, /* endload */ 925 NULL, /* serialize */ 926 NULL, /* dump */ 927 NULL, /* currentversion */ 928 NULL, /* newversion */ 929 NULL, /* attachversion */ 930 NULL, /* closeversion */ 931 rpsdb_findnode, 932 rpsdb_finddb, 933 NULL, /* findzonecut*/ 934 rpsdb_attachnode, 935 rpsdb_detachnode, 936 NULL, /* expirenode */ 937 NULL, /* printnode */ 938 NULL, /* createiterator */ 939 rpsdb_findrdataset, 940 rpsdb_allrdatasets, 941 NULL, /* addrdataset */ 942 NULL, /* subtractrdataset */ 943 NULL, /* deleterdataset */ 944 rpsdb_issecure, 945 NULL, /* nodecount */ 946 NULL, /* ispersistent */ 947 NULL, /* overmem */ 948 NULL, /* settask */ 949 rpsdb_getoriginnode, 950 NULL, /* transfernode */ 951 NULL, /* getnsec3parameters */ 952 NULL, /* findnsec3node */ 953 NULL, /* setsigningtime */ 954 NULL, /* getsigningtime */ 955 NULL, /* resigned */ 956 NULL, /* isdnssec */ 957 NULL, /* getrrsetstats */ 958 NULL, /* rpz_attach */ 959 NULL, /* rpz_ready */ 960 NULL, /* findnodeext */ 961 NULL, /* findext */ 962 NULL, /* setcachestats */ 963 NULL, /* hashsize */ 964 NULL, /* nodefullname */ 965 NULL, /* getsize */ 966 NULL, /* setservestalettl */ 967 NULL, /* getservestalettl */ 968 NULL /* setgluecachestats */ 969}; 970 971static dns_rdatasetmethods_t rpsdb_rdataset_methods = { 972 rpsdb_rdataset_disassociate, 973 rpsdb_rdataset_first, 974 rpsdb_rdataset_next, 975 rpsdb_rdataset_current, 976 rpsdb_rdataset_clone, 977 rpsdb_rdataset_count, 978 NULL, 979 NULL, 980 NULL, 981 NULL, 982 NULL, 983 NULL, 984 NULL, 985 NULL, 986 NULL, 987 NULL 988}; 989 990static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods = { 991 rpsdb_rdatasetiter_destroy, 992 rpsdb_rdatasetiter_first, 993 rpsdb_rdatasetiter_next, 994 rpsdb_rdatasetiter_current 995}; 996 997#endif /* USE_DNSRPS */ 998