1/* 2 * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: query.c,v 1.353.8.24 2012/02/07 01:14:39 marka Exp $ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <string.h> 25 26#include <isc/hex.h> 27#include <isc/mem.h> 28#include <isc/stats.h> 29#include <isc/util.h> 30 31#include <dns/adb.h> 32#include <dns/byaddr.h> 33#include <dns/db.h> 34#include <dns/dlz.h> 35#include <dns/dns64.h> 36#include <dns/dnssec.h> 37#include <dns/events.h> 38#include <dns/message.h> 39#include <dns/ncache.h> 40#include <dns/nsec3.h> 41#include <dns/order.h> 42#include <dns/rdata.h> 43#include <dns/rdataclass.h> 44#include <dns/rdatalist.h> 45#include <dns/rdataset.h> 46#include <dns/rdatasetiter.h> 47#include <dns/rdatastruct.h> 48#include <dns/rdatatype.h> 49#include <dns/resolver.h> 50#include <dns/result.h> 51#include <dns/stats.h> 52#include <dns/tkey.h> 53#include <dns/view.h> 54#include <dns/zone.h> 55#include <dns/zt.h> 56 57#include <named/client.h> 58#include <named/globals.h> 59#include <named/log.h> 60#include <named/server.h> 61#include <named/sortlist.h> 62#include <named/xfrout.h> 63 64#if 0 65/* 66 * It has been recommended that DNS64 be changed to return excluded 67 * AAAA addresses if DNS64 synthesis does not occur. This minimises 68 * the impact on the lookup results. While most DNS AAAA lookups are 69 * done to send IP packets to a host, not all of them are and filtering 70 * excluded addresses has a negative impact on those uses. 71 */ 72#define dns64_bis_return_excluded_addresses 1 73#endif 74 75/*% Partial answer? */ 76#define PARTIALANSWER(c) (((c)->query.attributes & \ 77 NS_QUERYATTR_PARTIALANSWER) != 0) 78/*% Use Cache? */ 79#define USECACHE(c) (((c)->query.attributes & \ 80 NS_QUERYATTR_CACHEOK) != 0) 81/*% Recursion OK? */ 82#define RECURSIONOK(c) (((c)->query.attributes & \ 83 NS_QUERYATTR_RECURSIONOK) != 0) 84/*% Recursing? */ 85#define RECURSING(c) (((c)->query.attributes & \ 86 NS_QUERYATTR_RECURSING) != 0) 87/*% Cache glue ok? */ 88#define CACHEGLUEOK(c) (((c)->query.attributes & \ 89 NS_QUERYATTR_CACHEGLUEOK) != 0) 90/*% Want Recursion? */ 91#define WANTRECURSION(c) (((c)->query.attributes & \ 92 NS_QUERYATTR_WANTRECURSION) != 0) 93/*% Want DNSSEC? */ 94#define WANTDNSSEC(c) (((c)->attributes & \ 95 NS_CLIENTATTR_WANTDNSSEC) != 0) 96/*% No authority? */ 97#define NOAUTHORITY(c) (((c)->query.attributes & \ 98 NS_QUERYATTR_NOAUTHORITY) != 0) 99/*% No additional? */ 100#define NOADDITIONAL(c) (((c)->query.attributes & \ 101 NS_QUERYATTR_NOADDITIONAL) != 0) 102/*% Secure? */ 103#define SECURE(c) (((c)->query.attributes & \ 104 NS_QUERYATTR_SECURE) != 0) 105/*% DNS64 A lookup? */ 106#define DNS64(c) (((c)->query.attributes & \ 107 NS_QUERYATTR_DNS64) != 0) 108 109#define DNS64EXCLUDE(c) (((c)->query.attributes & \ 110 NS_QUERYATTR_DNS64EXCLUDE) != 0) 111 112/*% No QNAME Proof? */ 113#define NOQNAME(r) (((r)->attributes & \ 114 DNS_RDATASETATTR_NOQNAME) != 0) 115 116#if 0 117#define CTRACE(m) isc_log_write(ns_g_lctx, \ 118 NS_LOGCATEGORY_CLIENT, \ 119 NS_LOGMODULE_QUERY, \ 120 ISC_LOG_DEBUG(3), \ 121 "client %p: %s", client, (m)) 122#define QTRACE(m) isc_log_write(ns_g_lctx, \ 123 NS_LOGCATEGORY_GENERAL, \ 124 NS_LOGMODULE_QUERY, \ 125 ISC_LOG_DEBUG(3), \ 126 "query %p: %s", query, (m)) 127#else 128#define CTRACE(m) ((void)m) 129#define QTRACE(m) ((void)m) 130#endif 131 132#define DNS_GETDB_NOEXACT 0x01U 133#define DNS_GETDB_NOLOG 0x02U 134#define DNS_GETDB_PARTIAL 0x04U 135#define DNS_GETDB_IGNOREACL 0x08U 136 137#define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0) 138 139typedef struct client_additionalctx { 140 ns_client_t *client; 141 dns_rdataset_t *rdataset; 142} client_additionalctx_t; 143 144static isc_result_t 145query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype); 146 147static isc_boolean_t 148validate(ns_client_t *client, dns_db_t *db, dns_name_t *name, 149 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); 150 151static void 152query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, 153 dns_dbversion_t *version, ns_client_t *client, 154 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 155 dns_name_t *fname, isc_boolean_t exact, 156 dns_name_t *found); 157 158static inline void 159log_queryerror(ns_client_t *client, isc_result_t result, int line, int level); 160 161static void 162rpz_st_clear(ns_client_t *client); 163 164/*% 165 * Increment query statistics counters. 166 */ 167static inline void 168inc_stats(ns_client_t *client, isc_statscounter_t counter) { 169 dns_zone_t *zone = client->query.authzone; 170 171 isc_stats_increment(ns_g_server->nsstats, counter); 172 173 if (zone != NULL) { 174 isc_stats_t *zonestats = dns_zone_getrequeststats(zone); 175 if (zonestats != NULL) 176 isc_stats_increment(zonestats, counter); 177 } 178} 179 180static void 181query_send(ns_client_t *client) { 182 isc_statscounter_t counter; 183 if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0) 184 inc_stats(client, dns_nsstatscounter_nonauthans); 185 else 186 inc_stats(client, dns_nsstatscounter_authans); 187 if (client->message->rcode == dns_rcode_noerror) { 188 if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER])) { 189 if (client->query.isreferral) { 190 counter = dns_nsstatscounter_referral; 191 } else { 192 counter = dns_nsstatscounter_nxrrset; 193 } 194 } else { 195 counter = dns_nsstatscounter_success; 196 } 197 } else if (client->message->rcode == dns_rcode_nxdomain) { 198 counter = dns_nsstatscounter_nxdomain; 199 } else { 200 /* We end up here in case of YXDOMAIN, and maybe others */ 201 counter = dns_nsstatscounter_failure; 202 } 203 inc_stats(client, counter); 204 ns_client_send(client); 205} 206 207static void 208query_error(ns_client_t *client, isc_result_t result, int line) { 209 int loglevel = ISC_LOG_DEBUG(3); 210 211 switch (result) { 212 case DNS_R_SERVFAIL: 213 loglevel = ISC_LOG_DEBUG(1); 214 inc_stats(client, dns_nsstatscounter_servfail); 215 break; 216 case DNS_R_FORMERR: 217 inc_stats(client, dns_nsstatscounter_formerr); 218 break; 219 default: 220 inc_stats(client, dns_nsstatscounter_failure); 221 break; 222 } 223 224 log_queryerror(client, result, line, loglevel); 225 226 ns_client_error(client, result); 227} 228 229static void 230query_next(ns_client_t *client, isc_result_t result) { 231 if (result == DNS_R_DUPLICATE) 232 inc_stats(client, dns_nsstatscounter_duplicate); 233 else if (result == DNS_R_DROP) 234 inc_stats(client, dns_nsstatscounter_dropped); 235 else 236 inc_stats(client, dns_nsstatscounter_failure); 237 ns_client_next(client, result); 238} 239 240static inline void 241query_freefreeversions(ns_client_t *client, isc_boolean_t everything) { 242 ns_dbversion_t *dbversion, *dbversion_next; 243 unsigned int i; 244 245 for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0; 246 dbversion != NULL; 247 dbversion = dbversion_next, i++) 248 { 249 dbversion_next = ISC_LIST_NEXT(dbversion, link); 250 /* 251 * If we're not freeing everything, we keep the first three 252 * dbversions structures around. 253 */ 254 if (i > 3 || everything) { 255 ISC_LIST_UNLINK(client->query.freeversions, dbversion, 256 link); 257 isc_mem_put(client->mctx, dbversion, 258 sizeof(*dbversion)); 259 } 260 } 261} 262 263void 264ns_query_cancel(ns_client_t *client) { 265 LOCK(&client->query.fetchlock); 266 if (client->query.fetch != NULL) { 267 dns_resolver_cancelfetch(client->query.fetch); 268 269 client->query.fetch = NULL; 270 } 271 UNLOCK(&client->query.fetchlock); 272} 273 274static inline void 275query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) { 276 dns_rdataset_t *rdataset = *rdatasetp; 277 278 CTRACE("query_putrdataset"); 279 if (rdataset != NULL) { 280 if (dns_rdataset_isassociated(rdataset)) 281 dns_rdataset_disassociate(rdataset); 282 dns_message_puttemprdataset(client->message, rdatasetp); 283 } 284 CTRACE("query_putrdataset: done"); 285} 286 287static inline void 288query_reset(ns_client_t *client, isc_boolean_t everything) { 289 isc_buffer_t *dbuf, *dbuf_next; 290 ns_dbversion_t *dbversion, *dbversion_next; 291 292 /*% 293 * Reset the query state of a client to its default state. 294 */ 295 296 /* 297 * Cancel the fetch if it's running. 298 */ 299 ns_query_cancel(client); 300 301 /* 302 * Cleanup any active versions. 303 */ 304 for (dbversion = ISC_LIST_HEAD(client->query.activeversions); 305 dbversion != NULL; 306 dbversion = dbversion_next) { 307 dbversion_next = ISC_LIST_NEXT(dbversion, link); 308 dns_db_closeversion(dbversion->db, &dbversion->version, 309 ISC_FALSE); 310 dns_db_detach(&dbversion->db); 311 ISC_LIST_INITANDAPPEND(client->query.freeversions, 312 dbversion, link); 313 } 314 ISC_LIST_INIT(client->query.activeversions); 315 316 if (client->query.authdb != NULL) 317 dns_db_detach(&client->query.authdb); 318 if (client->query.authzone != NULL) 319 dns_zone_detach(&client->query.authzone); 320 321 if (client->query.dns64_aaaa != NULL) 322 query_putrdataset(client, &client->query.dns64_aaaa); 323 if (client->query.dns64_sigaaaa != NULL) 324 query_putrdataset(client, &client->query.dns64_sigaaaa); 325 if (client->query.dns64_aaaaok != NULL) { 326 isc_mem_put(client->mctx, client->query.dns64_aaaaok, 327 client->query.dns64_aaaaoklen * 328 sizeof(isc_boolean_t)); 329 client->query.dns64_aaaaok = NULL; 330 client->query.dns64_aaaaoklen = 0; 331 } 332 333 query_freefreeversions(client, everything); 334 335 for (dbuf = ISC_LIST_HEAD(client->query.namebufs); 336 dbuf != NULL; 337 dbuf = dbuf_next) { 338 dbuf_next = ISC_LIST_NEXT(dbuf, link); 339 if (dbuf_next != NULL || everything) { 340 ISC_LIST_UNLINK(client->query.namebufs, dbuf, link); 341 isc_buffer_free(&dbuf); 342 } 343 } 344 345 if (client->query.restarts > 0) { 346 /* 347 * client->query.qname was dynamically allocated. 348 */ 349 dns_message_puttempname(client->message, 350 &client->query.qname); 351 } 352 client->query.qname = NULL; 353 client->query.attributes = (NS_QUERYATTR_RECURSIONOK | 354 NS_QUERYATTR_CACHEOK | 355 NS_QUERYATTR_SECURE); 356 client->query.restarts = 0; 357 client->query.timerset = ISC_FALSE; 358 if (client->query.rpz_st != NULL) { 359 rpz_st_clear(client); 360 if (everything) { 361 isc_mem_put(client->mctx, client->query.rpz_st, 362 sizeof(*client->query.rpz_st)); 363 client->query.rpz_st = NULL; 364 } 365 } 366 client->query.origqname = NULL; 367 client->query.dboptions = 0; 368 client->query.fetchoptions = 0; 369 client->query.gluedb = NULL; 370 client->query.authdbset = ISC_FALSE; 371 client->query.isreferral = ISC_FALSE; 372 client->query.dns64_options = 0; 373 client->query.dns64_ttl = ISC_UINT32_MAX; 374} 375 376static void 377query_next_callback(ns_client_t *client) { 378 query_reset(client, ISC_FALSE); 379} 380 381void 382ns_query_free(ns_client_t *client) { 383 query_reset(client, ISC_TRUE); 384} 385 386static inline isc_result_t 387query_newnamebuf(ns_client_t *client) { 388 isc_buffer_t *dbuf; 389 isc_result_t result; 390 391 CTRACE("query_newnamebuf"); 392 /*% 393 * Allocate a name buffer. 394 */ 395 396 dbuf = NULL; 397 result = isc_buffer_allocate(client->mctx, &dbuf, 1024); 398 if (result != ISC_R_SUCCESS) { 399 CTRACE("query_newnamebuf: isc_buffer_allocate failed: done"); 400 return (result); 401 } 402 ISC_LIST_APPEND(client->query.namebufs, dbuf, link); 403 404 CTRACE("query_newnamebuf: done"); 405 return (ISC_R_SUCCESS); 406} 407 408static inline isc_buffer_t * 409query_getnamebuf(ns_client_t *client) { 410 isc_buffer_t *dbuf; 411 isc_result_t result; 412 isc_region_t r; 413 414 CTRACE("query_getnamebuf"); 415 /*% 416 * Return a name buffer with space for a maximal name, allocating 417 * a new one if necessary. 418 */ 419 420 if (ISC_LIST_EMPTY(client->query.namebufs)) { 421 result = query_newnamebuf(client); 422 if (result != ISC_R_SUCCESS) { 423 CTRACE("query_getnamebuf: query_newnamebuf failed: done"); 424 return (NULL); 425 } 426 } 427 428 dbuf = ISC_LIST_TAIL(client->query.namebufs); 429 INSIST(dbuf != NULL); 430 isc_buffer_availableregion(dbuf, &r); 431 if (r.length < 255) { 432 result = query_newnamebuf(client); 433 if (result != ISC_R_SUCCESS) { 434 CTRACE("query_getnamebuf: query_newnamebuf failed: done"); 435 return (NULL); 436 437 } 438 dbuf = ISC_LIST_TAIL(client->query.namebufs); 439 isc_buffer_availableregion(dbuf, &r); 440 INSIST(r.length >= 255); 441 } 442 CTRACE("query_getnamebuf: done"); 443 return (dbuf); 444} 445 446static inline void 447query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) { 448 isc_region_t r; 449 450 CTRACE("query_keepname"); 451 /*% 452 * 'name' is using space in 'dbuf', but 'dbuf' has not yet been 453 * adjusted to take account of that. We do the adjustment. 454 */ 455 456 REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0); 457 458 dns_name_toregion(name, &r); 459 isc_buffer_add(dbuf, r.length); 460 dns_name_setbuffer(name, NULL); 461 client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED; 462} 463 464static inline void 465query_releasename(ns_client_t *client, dns_name_t **namep) { 466 dns_name_t *name = *namep; 467 468 /*% 469 * 'name' is no longer needed. Return it to our pool of temporary 470 * names. If it is using a name buffer, relinquish its exclusive 471 * rights on the buffer. 472 */ 473 474 CTRACE("query_releasename"); 475 if (dns_name_hasbuffer(name)) { 476 INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) 477 != 0); 478 client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED; 479 } 480 dns_message_puttempname(client->message, namep); 481 CTRACE("query_releasename: done"); 482} 483 484static inline dns_name_t * 485query_newname(ns_client_t *client, isc_buffer_t *dbuf, 486 isc_buffer_t *nbuf) 487{ 488 dns_name_t *name; 489 isc_region_t r; 490 isc_result_t result; 491 492 REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0); 493 494 CTRACE("query_newname"); 495 name = NULL; 496 result = dns_message_gettempname(client->message, &name); 497 if (result != ISC_R_SUCCESS) { 498 CTRACE("query_newname: dns_message_gettempname failed: done"); 499 return (NULL); 500 } 501 isc_buffer_availableregion(dbuf, &r); 502 isc_buffer_init(nbuf, r.base, r.length); 503 dns_name_init(name, NULL); 504 dns_name_setbuffer(name, nbuf); 505 client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED; 506 507 CTRACE("query_newname: done"); 508 return (name); 509} 510 511static inline dns_rdataset_t * 512query_newrdataset(ns_client_t *client) { 513 dns_rdataset_t *rdataset; 514 isc_result_t result; 515 516 CTRACE("query_newrdataset"); 517 rdataset = NULL; 518 result = dns_message_gettemprdataset(client->message, &rdataset); 519 if (result != ISC_R_SUCCESS) { 520 CTRACE("query_newrdataset: " 521 "dns_message_gettemprdataset failed: done"); 522 return (NULL); 523 } 524 dns_rdataset_init(rdataset); 525 526 CTRACE("query_newrdataset: done"); 527 return (rdataset); 528} 529 530static inline isc_result_t 531query_newdbversion(ns_client_t *client, unsigned int n) { 532 unsigned int i; 533 ns_dbversion_t *dbversion; 534 535 for (i = 0; i < n; i++) { 536 dbversion = isc_mem_get(client->mctx, sizeof(*dbversion)); 537 if (dbversion != NULL) { 538 dbversion->db = NULL; 539 dbversion->version = NULL; 540 ISC_LIST_INITANDAPPEND(client->query.freeversions, 541 dbversion, link); 542 } else { 543 /* 544 * We only return ISC_R_NOMEMORY if we couldn't 545 * allocate anything. 546 */ 547 if (i == 0) 548 return (ISC_R_NOMEMORY); 549 else 550 return (ISC_R_SUCCESS); 551 } 552 } 553 554 return (ISC_R_SUCCESS); 555} 556 557static inline ns_dbversion_t * 558query_getdbversion(ns_client_t *client) { 559 isc_result_t result; 560 ns_dbversion_t *dbversion; 561 562 if (ISC_LIST_EMPTY(client->query.freeversions)) { 563 result = query_newdbversion(client, 1); 564 if (result != ISC_R_SUCCESS) 565 return (NULL); 566 } 567 dbversion = ISC_LIST_HEAD(client->query.freeversions); 568 INSIST(dbversion != NULL); 569 ISC_LIST_UNLINK(client->query.freeversions, dbversion, link); 570 571 return (dbversion); 572} 573 574isc_result_t 575ns_query_init(ns_client_t *client) { 576 isc_result_t result; 577 578 ISC_LIST_INIT(client->query.namebufs); 579 ISC_LIST_INIT(client->query.activeversions); 580 ISC_LIST_INIT(client->query.freeversions); 581 client->query.restarts = 0; 582 client->query.timerset = ISC_FALSE; 583 client->query.rpz_st = NULL; 584 client->query.qname = NULL; 585 result = isc_mutex_init(&client->query.fetchlock); 586 if (result != ISC_R_SUCCESS) 587 return (result); 588 client->query.fetch = NULL; 589 client->query.authdb = NULL; 590 client->query.authzone = NULL; 591 client->query.authdbset = ISC_FALSE; 592 client->query.isreferral = ISC_FALSE; 593 client->query.dns64_aaaa = NULL; 594 client->query.dns64_sigaaaa = NULL; 595 client->query.dns64_aaaaok = NULL; 596 client->query.dns64_aaaaoklen = 0; 597 query_reset(client, ISC_FALSE); 598 result = query_newdbversion(client, 3); 599 if (result != ISC_R_SUCCESS) { 600 DESTROYLOCK(&client->query.fetchlock); 601 return (result); 602 } 603 result = query_newnamebuf(client); 604 if (result != ISC_R_SUCCESS) 605 query_freefreeversions(client, ISC_TRUE); 606 607 return (result); 608} 609 610static inline ns_dbversion_t * 611query_findversion(ns_client_t *client, dns_db_t *db) 612{ 613 ns_dbversion_t *dbversion; 614 615 /*% 616 * We may already have done a query related to this 617 * database. If so, we must be sure to make subsequent 618 * queries from the same version. 619 */ 620 for (dbversion = ISC_LIST_HEAD(client->query.activeversions); 621 dbversion != NULL; 622 dbversion = ISC_LIST_NEXT(dbversion, link)) { 623 if (dbversion->db == db) 624 break; 625 } 626 627 if (dbversion == NULL) { 628 /* 629 * This is a new zone for this query. Add it to 630 * the active list. 631 */ 632 dbversion = query_getdbversion(client); 633 if (dbversion == NULL) 634 return (NULL); 635 dns_db_attach(db, &dbversion->db); 636 dns_db_currentversion(db, &dbversion->version); 637 dbversion->acl_checked = ISC_FALSE; 638 dbversion->queryok = ISC_FALSE; 639 ISC_LIST_APPEND(client->query.activeversions, 640 dbversion, link); 641 } 642 643 return (dbversion); 644} 645 646static inline isc_result_t 647query_validatezonedb(ns_client_t *client, dns_name_t *name, 648 dns_rdatatype_t qtype, unsigned int options, 649 dns_zone_t *zone, dns_db_t *db, 650 dns_dbversion_t **versionp) 651{ 652 isc_result_t result; 653 dns_acl_t *queryacl; 654 ns_dbversion_t *dbversion; 655 656 REQUIRE(zone != NULL); 657 REQUIRE(db != NULL); 658 659 /* 660 * This limits our searching to the zone where the first name 661 * (the query target) was looked for. This prevents following 662 * CNAMES or DNAMES into other zones and prevents returning 663 * additional data from other zones. 664 */ 665 if (!client->view->additionalfromauth && 666 client->query.authdbset && 667 db != client->query.authdb) 668 return (DNS_R_REFUSED); 669 670 /* 671 * Non recursive query to a static-stub zone is prohibited; its 672 * zone content is not public data, but a part of local configuration 673 * and should not be disclosed. 674 */ 675 if (dns_zone_gettype(zone) == dns_zone_staticstub && 676 !RECURSIONOK(client)) { 677 return (DNS_R_REFUSED); 678 } 679 680 /* 681 * If the zone has an ACL, we'll check it, otherwise 682 * we use the view's "allow-query" ACL. Each ACL is only checked 683 * once per query. 684 * 685 * Also, get the database version to use. 686 */ 687 688 /* 689 * Get the current version of this database. 690 */ 691 dbversion = query_findversion(client, db); 692 if (dbversion == NULL) 693 return (DNS_R_SERVFAIL); 694 695 if ((options & DNS_GETDB_IGNOREACL) != 0) 696 goto approved; 697 if (dbversion->acl_checked) { 698 if (!dbversion->queryok) 699 return (DNS_R_REFUSED); 700 goto approved; 701 } 702 703 queryacl = dns_zone_getqueryacl(zone); 704 if (queryacl == NULL) { 705 queryacl = client->view->queryacl; 706 if ((client->query.attributes & 707 NS_QUERYATTR_QUERYOKVALID) != 0) { 708 /* 709 * We've evaluated the view's queryacl already. If 710 * NS_QUERYATTR_QUERYOK is set, then the client is 711 * allowed to make queries, otherwise the query should 712 * be refused. 713 */ 714 dbversion->acl_checked = ISC_TRUE; 715 if ((client->query.attributes & 716 NS_QUERYATTR_QUERYOK) == 0) { 717 dbversion->queryok = ISC_FALSE; 718 return (DNS_R_REFUSED); 719 } 720 dbversion->queryok = ISC_TRUE; 721 goto approved; 722 } 723 } 724 725 result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); 726 if ((options & DNS_GETDB_NOLOG) == 0) { 727 char msg[NS_CLIENT_ACLMSGSIZE("query")]; 728 if (result == ISC_R_SUCCESS) { 729 if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) { 730 ns_client_aclmsg("query", name, qtype, 731 client->view->rdclass, 732 msg, sizeof(msg)); 733 ns_client_log(client, 734 DNS_LOGCATEGORY_SECURITY, 735 NS_LOGMODULE_QUERY, 736 ISC_LOG_DEBUG(3), 737 "%s approved", msg); 738 } 739 } else { 740 ns_client_aclmsg("query", name, qtype, 741 client->view->rdclass, 742 msg, sizeof(msg)); 743 ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 744 NS_LOGMODULE_QUERY, ISC_LOG_INFO, 745 "%s denied", msg); 746 } 747 } 748 749 if (queryacl == client->view->queryacl) { 750 if (result == ISC_R_SUCCESS) { 751 /* 752 * We were allowed by the default 753 * "allow-query" ACL. Remember this so we 754 * don't have to check again. 755 */ 756 client->query.attributes |= NS_QUERYATTR_QUERYOK; 757 } 758 /* 759 * We've now evaluated the view's query ACL, and 760 * the NS_QUERYATTR_QUERYOK attribute is now valid. 761 */ 762 client->query.attributes |= NS_QUERYATTR_QUERYOKVALID; 763 } 764 765 dbversion->acl_checked = ISC_TRUE; 766 if (result != ISC_R_SUCCESS) { 767 dbversion->queryok = ISC_FALSE; 768 return (DNS_R_REFUSED); 769 } 770 dbversion->queryok = ISC_TRUE; 771 772 approved: 773 /* Transfer ownership, if necessary. */ 774 if (versionp != NULL) 775 *versionp = dbversion->version; 776 return (ISC_R_SUCCESS); 777} 778 779static inline isc_result_t 780query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, 781 unsigned int options, dns_zone_t **zonep, dns_db_t **dbp, 782 dns_dbversion_t **versionp) 783{ 784 isc_result_t result; 785 unsigned int ztoptions; 786 dns_zone_t *zone = NULL; 787 dns_db_t *db = NULL; 788 isc_boolean_t partial = ISC_FALSE; 789 790 REQUIRE(zonep != NULL && *zonep == NULL); 791 REQUIRE(dbp != NULL && *dbp == NULL); 792 793 /*% 794 * Find a zone database to answer the query. 795 */ 796 ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ? 797 DNS_ZTFIND_NOEXACT : 0; 798 799 result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL, 800 &zone); 801 if (result == DNS_R_PARTIALMATCH) 802 partial = ISC_TRUE; 803 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) 804 result = dns_zone_getdb(zone, &db); 805 806 if (result != ISC_R_SUCCESS) 807 goto fail; 808 809 result = query_validatezonedb(client, name, qtype, options, zone, db, 810 versionp); 811 812 if (result != ISC_R_SUCCESS) 813 goto fail; 814 815 /* Transfer ownership. */ 816 *zonep = zone; 817 *dbp = db; 818 819 if (partial && (options & DNS_GETDB_PARTIAL) != 0) 820 return (DNS_R_PARTIALMATCH); 821 return (ISC_R_SUCCESS); 822 823 fail: 824 if (zone != NULL) 825 dns_zone_detach(&zone); 826 if (db != NULL) 827 dns_db_detach(&db); 828 829 return (result); 830} 831 832static void 833rpz_log_rewrite(ns_client_t *client, const char *disabled, 834 dns_rpz_policy_t policy, dns_rpz_type_t type, 835 dns_name_t *rpz_qname) { 836 char qname_buf[DNS_NAME_FORMATSIZE]; 837 char rpz_qname_buf[DNS_NAME_FORMATSIZE]; 838 839 if (!isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL)) 840 return; 841 842 dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf)); 843 dns_name_format(rpz_qname, rpz_qname_buf, sizeof(rpz_qname_buf)); 844 845 ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY, 846 DNS_RPZ_INFO_LEVEL, "%srpz %s %s rewrite %s via %s", 847 disabled, 848 dns_rpz_type2str(type), dns_rpz_policy2str(policy), 849 qname_buf, rpz_qname_buf); 850} 851 852static void 853rpz_log_fail(ns_client_t *client, int level, 854 dns_rpz_type_t rpz_type, dns_name_t *name, 855 const char *str, isc_result_t result) 856{ 857 char namebuf1[DNS_NAME_FORMATSIZE]; 858 char namebuf2[DNS_NAME_FORMATSIZE]; 859 860 if (!isc_log_wouldlog(ns_g_lctx, level)) 861 return; 862 863 dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1)); 864 dns_name_format(name, namebuf2, sizeof(namebuf2)); 865 ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, 866 NS_LOGMODULE_QUERY, level, 867 "rpz %s rewrite %s via %s %sfailed: %s", 868 dns_rpz_type2str(rpz_type), 869 namebuf1, namebuf2, str, isc_result_totext(result)); 870} 871 872/* 873 * Get a policy rewrite zone database. 874 */ 875static isc_result_t 876rpz_getdb(ns_client_t *client, dns_rpz_type_t rpz_type, dns_name_t *rpz_qname, 877 dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp) 878{ 879 char namebuf1[DNS_NAME_FORMATSIZE]; 880 char namebuf2[DNS_NAME_FORMATSIZE]; 881 dns_dbversion_t *rpz_version = NULL; 882 isc_result_t result; 883 884 result = query_getzonedb(client, rpz_qname, dns_rdatatype_any, 885 DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version); 886 if (result == ISC_R_SUCCESS) { 887 if (isc_log_wouldlog(ns_g_lctx, DNS_RPZ_DEBUG_LEVEL2)) { 888 dns_name_format(client->query.qname, namebuf1, 889 sizeof(namebuf1)); 890 dns_name_format(rpz_qname, namebuf2, sizeof(namebuf2)); 891 ns_client_log(client, DNS_LOGCATEGORY_RPZ, 892 NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2, 893 "try rpz %s rewrite %s via %s", 894 dns_rpz_type2str(rpz_type), 895 namebuf1, namebuf2); 896 } 897 *versionp = rpz_version; 898 return (ISC_R_SUCCESS); 899 } 900 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, rpz_qname, 901 "query_getzonedb() ", result); 902 return (result); 903} 904 905static inline isc_result_t 906query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, 907 dns_db_t **dbp, unsigned int options) 908{ 909 isc_result_t result; 910 isc_boolean_t check_acl; 911 dns_db_t *db = NULL; 912 913 REQUIRE(dbp != NULL && *dbp == NULL); 914 915 /*% 916 * Find a cache database to answer the query. 917 * This may fail with DNS_R_REFUSED if the client 918 * is not allowed to use the cache. 919 */ 920 921 if (!USECACHE(client)) 922 return (DNS_R_REFUSED); 923 dns_db_attach(client->view->cachedb, &db); 924 925 if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) != 0) { 926 /* 927 * We've evaluated the view's cacheacl already. If 928 * NS_QUERYATTR_CACHEACLOK is set, then the client is 929 * allowed to make queries, otherwise the query should 930 * be refused. 931 */ 932 check_acl = ISC_FALSE; 933 if ((client->query.attributes & NS_QUERYATTR_CACHEACLOK) == 0) 934 goto refuse; 935 } else { 936 /* 937 * We haven't evaluated the view's queryacl yet. 938 */ 939 check_acl = ISC_TRUE; 940 } 941 942 if (check_acl) { 943 isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0); 944 char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")]; 945 946 result = ns_client_checkaclsilent(client, NULL, 947 client->view->cacheacl, 948 ISC_TRUE); 949 if (result == ISC_R_SUCCESS) { 950 /* 951 * We were allowed by the "allow-query-cache" ACL. 952 * Remember this so we don't have to check again. 953 */ 954 client->query.attributes |= 955 NS_QUERYATTR_CACHEACLOK; 956 if (log && isc_log_wouldlog(ns_g_lctx, 957 ISC_LOG_DEBUG(3))) 958 { 959 ns_client_aclmsg("query (cache)", name, qtype, 960 client->view->rdclass, 961 msg, sizeof(msg)); 962 ns_client_log(client, 963 DNS_LOGCATEGORY_SECURITY, 964 NS_LOGMODULE_QUERY, 965 ISC_LOG_DEBUG(3), 966 "%s approved", msg); 967 } 968 } else if (log) { 969 ns_client_aclmsg("query (cache)", name, qtype, 970 client->view->rdclass, msg, 971 sizeof(msg)); 972 ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 973 NS_LOGMODULE_QUERY, ISC_LOG_INFO, 974 "%s denied", msg); 975 } 976 /* 977 * We've now evaluated the view's query ACL, and 978 * the NS_QUERYATTR_CACHEACLOKVALID attribute is now valid. 979 */ 980 client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID; 981 982 if (result != ISC_R_SUCCESS) 983 goto refuse; 984 } 985 986 /* Approved. */ 987 988 /* Transfer ownership. */ 989 *dbp = db; 990 991 return (ISC_R_SUCCESS); 992 993 refuse: 994 result = DNS_R_REFUSED; 995 996 if (db != NULL) 997 dns_db_detach(&db); 998 999 return (result); 1000} 1001 1002 1003static inline isc_result_t 1004query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, 1005 unsigned int options, dns_zone_t **zonep, dns_db_t **dbp, 1006 dns_dbversion_t **versionp, isc_boolean_t *is_zonep) 1007{ 1008 isc_result_t result; 1009 1010 isc_result_t tresult; 1011 unsigned int namelabels; 1012 unsigned int zonelabels; 1013 dns_zone_t *zone = NULL; 1014 dns_db_t *tdbp; 1015 1016 REQUIRE(zonep != NULL && *zonep == NULL); 1017 1018 tdbp = NULL; 1019 1020 /* Calculate how many labels are in name. */ 1021 namelabels = dns_name_countlabels(name); 1022 zonelabels = 0; 1023 1024 /* Try to find name in bind's standard database. */ 1025 result = query_getzonedb(client, name, qtype, options, &zone, 1026 dbp, versionp); 1027 1028 /* See how many labels are in the zone's name. */ 1029 if (result == ISC_R_SUCCESS && zone != NULL) 1030 zonelabels = dns_name_countlabels(dns_zone_getorigin(zone)); 1031 /* 1032 * If # zone labels < # name labels, try to find an even better match 1033 * Only try if a DLZ driver is loaded for this view 1034 */ 1035 if (zonelabels < namelabels && client->view->dlzdatabase != NULL) { 1036 tresult = dns_dlzfindzone(client->view, name, 1037 zonelabels, &tdbp); 1038 /* If we successful, we found a better match. */ 1039 if (tresult == ISC_R_SUCCESS) { 1040 /* 1041 * If the previous search returned a zone, detach it. 1042 */ 1043 if (zone != NULL) 1044 dns_zone_detach(&zone); 1045 1046 /* 1047 * If the previous search returned a database, 1048 * detach it. 1049 */ 1050 if (*dbp != NULL) 1051 dns_db_detach(dbp); 1052 1053 /* 1054 * If the previous search returned a version, clear it. 1055 */ 1056 *versionp = NULL; 1057 1058 /* 1059 * Get our database version. 1060 */ 1061 dns_db_currentversion(tdbp, versionp); 1062 1063 /* 1064 * Be sure to return our database. 1065 */ 1066 *dbp = tdbp; 1067 1068 /* 1069 * We return a null zone, No stats for DLZ zones. 1070 */ 1071 zone = NULL; 1072 result = tresult; 1073 } 1074 } 1075 1076 /* If successful, Transfer ownership of zone. */ 1077 if (result == ISC_R_SUCCESS) { 1078 *zonep = zone; 1079 /* 1080 * If neither attempt above succeeded, return the cache instead 1081 */ 1082 *is_zonep = ISC_TRUE; 1083 } else if (result == ISC_R_NOTFOUND) { 1084 result = query_getcachedb(client, name, qtype, dbp, options); 1085 *is_zonep = ISC_FALSE; 1086 } 1087 return (result); 1088} 1089 1090static inline isc_boolean_t 1091query_isduplicate(ns_client_t *client, dns_name_t *name, 1092 dns_rdatatype_t type, dns_name_t **mnamep) 1093{ 1094 dns_section_t section; 1095 dns_name_t *mname = NULL; 1096 isc_result_t result; 1097 1098 CTRACE("query_isduplicate"); 1099 1100 for (section = DNS_SECTION_ANSWER; 1101 section <= DNS_SECTION_ADDITIONAL; 1102 section++) { 1103 result = dns_message_findname(client->message, section, 1104 name, type, 0, &mname, NULL); 1105 if (result == ISC_R_SUCCESS) { 1106 /* 1107 * We've already got this RRset in the response. 1108 */ 1109 CTRACE("query_isduplicate: true: done"); 1110 return (ISC_TRUE); 1111 } else if (result == DNS_R_NXRRSET) { 1112 /* 1113 * The name exists, but the rdataset does not. 1114 */ 1115 if (section == DNS_SECTION_ADDITIONAL) 1116 break; 1117 } else 1118 RUNTIME_CHECK(result == DNS_R_NXDOMAIN); 1119 mname = NULL; 1120 } 1121 1122 /* 1123 * If the dns_name_t we're looking up is already in the message, 1124 * we don't want to trigger the caller's name replacement logic. 1125 */ 1126 if (name == mname) 1127 mname = NULL; 1128 1129 if (mnamep != NULL) 1130 *mnamep = mname; 1131 1132 CTRACE("query_isduplicate: false: done"); 1133 return (ISC_FALSE); 1134} 1135 1136static isc_result_t 1137query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { 1138 ns_client_t *client = arg; 1139 isc_result_t result, eresult; 1140 dns_dbnode_t *node; 1141 dns_db_t *db; 1142 dns_name_t *fname, *mname; 1143 dns_rdataset_t *rdataset, *sigrdataset, *trdataset; 1144 isc_buffer_t *dbuf; 1145 isc_buffer_t b; 1146 dns_dbversion_t *version; 1147 isc_boolean_t added_something, need_addname; 1148 dns_zone_t *zone; 1149 dns_rdatatype_t type; 1150 1151 REQUIRE(NS_CLIENT_VALID(client)); 1152 REQUIRE(qtype != dns_rdatatype_any); 1153 1154 if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype)) 1155 return (ISC_R_SUCCESS); 1156 1157 CTRACE("query_addadditional"); 1158 1159 /* 1160 * Initialization. 1161 */ 1162 eresult = ISC_R_SUCCESS; 1163 fname = NULL; 1164 rdataset = NULL; 1165 sigrdataset = NULL; 1166 trdataset = NULL; 1167 db = NULL; 1168 version = NULL; 1169 node = NULL; 1170 added_something = ISC_FALSE; 1171 need_addname = ISC_FALSE; 1172 zone = NULL; 1173 1174 /* 1175 * We treat type A additional section processing as if it 1176 * were "any address type" additional section processing. 1177 * To avoid multiple lookups, we do an 'any' database 1178 * lookup and iterate over the node. 1179 */ 1180 if (qtype == dns_rdatatype_a) 1181 type = dns_rdatatype_any; 1182 else 1183 type = qtype; 1184 1185 /* 1186 * Get some resources. 1187 */ 1188 dbuf = query_getnamebuf(client); 1189 if (dbuf == NULL) 1190 goto cleanup; 1191 fname = query_newname(client, dbuf, &b); 1192 rdataset = query_newrdataset(client); 1193 if (fname == NULL || rdataset == NULL) 1194 goto cleanup; 1195 if (WANTDNSSEC(client)) { 1196 sigrdataset = query_newrdataset(client); 1197 if (sigrdataset == NULL) 1198 goto cleanup; 1199 } 1200 1201 /* 1202 * Look for a zone database that might contain authoritative 1203 * additional data. 1204 */ 1205 result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG, 1206 &zone, &db, &version); 1207 if (result != ISC_R_SUCCESS) 1208 goto try_cache; 1209 1210 CTRACE("query_addadditional: db_find"); 1211 1212 /* 1213 * Since we are looking for authoritative data, we do not set 1214 * the GLUEOK flag. Glue will be looked for later, but not 1215 * necessarily in the same database. 1216 */ 1217 node = NULL; 1218 result = dns_db_find(db, name, version, type, client->query.dboptions, 1219 client->now, &node, fname, rdataset, 1220 sigrdataset); 1221 if (result == ISC_R_SUCCESS) { 1222 if (sigrdataset != NULL && !dns_db_issecure(db) && 1223 dns_rdataset_isassociated(sigrdataset)) 1224 dns_rdataset_disassociate(sigrdataset); 1225 goto found; 1226 } 1227 1228 if (dns_rdataset_isassociated(rdataset)) 1229 dns_rdataset_disassociate(rdataset); 1230 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) 1231 dns_rdataset_disassociate(sigrdataset); 1232 if (node != NULL) 1233 dns_db_detachnode(db, &node); 1234 version = NULL; 1235 dns_db_detach(&db); 1236 1237 /* 1238 * No authoritative data was found. The cache is our next best bet. 1239 */ 1240 1241 try_cache: 1242 result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG); 1243 if (result != ISC_R_SUCCESS) 1244 /* 1245 * Most likely the client isn't allowed to query the cache. 1246 */ 1247 goto try_glue; 1248 /* 1249 * Attempt to validate glue. 1250 */ 1251 if (sigrdataset == NULL) { 1252 sigrdataset = query_newrdataset(client); 1253 if (sigrdataset == NULL) 1254 goto cleanup; 1255 } 1256 result = dns_db_find(db, name, version, type, 1257 client->query.dboptions | 1258 DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, 1259 client->now, &node, fname, rdataset, 1260 sigrdataset); 1261 if (result == DNS_R_GLUE && 1262 validate(client, db, fname, rdataset, sigrdataset)) 1263 result = ISC_R_SUCCESS; 1264 if (!WANTDNSSEC(client)) 1265 query_putrdataset(client, &sigrdataset); 1266 if (result == ISC_R_SUCCESS) 1267 goto found; 1268 1269 if (dns_rdataset_isassociated(rdataset)) 1270 dns_rdataset_disassociate(rdataset); 1271 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) 1272 dns_rdataset_disassociate(sigrdataset); 1273 if (node != NULL) 1274 dns_db_detachnode(db, &node); 1275 dns_db_detach(&db); 1276 1277 try_glue: 1278 /* 1279 * No cached data was found. Glue is our last chance. 1280 * RFC1035 sayeth: 1281 * 1282 * NS records cause both the usual additional section 1283 * processing to locate a type A record, and, when used 1284 * in a referral, a special search of the zone in which 1285 * they reside for glue information. 1286 * 1287 * This is the "special search". Note that we must search 1288 * the zone where the NS record resides, not the zone it 1289 * points to, and that we only do the search in the delegation 1290 * case (identified by client->query.gluedb being set). 1291 */ 1292 1293 if (client->query.gluedb == NULL) 1294 goto cleanup; 1295 1296 /* 1297 * Don't poison caches using the bailiwick protection model. 1298 */ 1299 if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) 1300 goto cleanup; 1301 1302 dns_db_attach(client->query.gluedb, &db); 1303 result = dns_db_find(db, name, version, type, 1304 client->query.dboptions | DNS_DBFIND_GLUEOK, 1305 client->now, &node, fname, rdataset, 1306 sigrdataset); 1307 if (!(result == ISC_R_SUCCESS || 1308 result == DNS_R_ZONECUT || 1309 result == DNS_R_GLUE)) 1310 goto cleanup; 1311 1312 found: 1313 /* 1314 * We have found a potential additional data rdataset, or 1315 * at least a node to iterate over. 1316 */ 1317 query_keepname(client, fname, dbuf); 1318 1319 /* 1320 * If we have an rdataset, add it to the additional data 1321 * section. 1322 */ 1323 mname = NULL; 1324 if (dns_rdataset_isassociated(rdataset) && 1325 !query_isduplicate(client, fname, type, &mname)) { 1326 if (mname != NULL) { 1327 query_releasename(client, &fname); 1328 fname = mname; 1329 } else 1330 need_addname = ISC_TRUE; 1331 ISC_LIST_APPEND(fname->list, rdataset, link); 1332 trdataset = rdataset; 1333 rdataset = NULL; 1334 added_something = ISC_TRUE; 1335 /* 1336 * Note: we only add SIGs if we've added the type they cover, 1337 * so we do not need to check if the SIG rdataset is already 1338 * in the response. 1339 */ 1340 if (sigrdataset != NULL && 1341 dns_rdataset_isassociated(sigrdataset)) 1342 { 1343 ISC_LIST_APPEND(fname->list, sigrdataset, link); 1344 sigrdataset = NULL; 1345 } 1346 } 1347 1348 if (qtype == dns_rdatatype_a) { 1349#ifdef ALLOW_FILTER_AAAA_ON_V4 1350 isc_boolean_t have_a = ISC_FALSE; 1351#endif 1352 1353 /* 1354 * We now go looking for A and AAAA records, along with 1355 * their signatures. 1356 * 1357 * XXXRTH This code could be more efficient. 1358 */ 1359 if (rdataset != NULL) { 1360 if (dns_rdataset_isassociated(rdataset)) 1361 dns_rdataset_disassociate(rdataset); 1362 } else { 1363 rdataset = query_newrdataset(client); 1364 if (rdataset == NULL) 1365 goto addname; 1366 } 1367 if (sigrdataset != NULL) { 1368 if (dns_rdataset_isassociated(sigrdataset)) 1369 dns_rdataset_disassociate(sigrdataset); 1370 } else if (WANTDNSSEC(client)) { 1371 sigrdataset = query_newrdataset(client); 1372 if (sigrdataset == NULL) 1373 goto addname; 1374 } 1375 if (query_isduplicate(client, fname, dns_rdatatype_a, NULL)) 1376 goto aaaa_lookup; 1377 result = dns_db_findrdataset(db, node, version, 1378 dns_rdatatype_a, 0, 1379 client->now, rdataset, 1380 sigrdataset); 1381 if (result == DNS_R_NCACHENXDOMAIN) 1382 goto addname; 1383 if (result == DNS_R_NCACHENXRRSET) { 1384 dns_rdataset_disassociate(rdataset); 1385 if (sigrdataset != NULL && 1386 dns_rdataset_isassociated(sigrdataset)) 1387 dns_rdataset_disassociate(sigrdataset); 1388 } 1389 if (result == ISC_R_SUCCESS) { 1390 mname = NULL; 1391#ifdef ALLOW_FILTER_AAAA_ON_V4 1392 have_a = ISC_TRUE; 1393#endif 1394 if (!query_isduplicate(client, fname, 1395 dns_rdatatype_a, &mname)) { 1396 if (mname != NULL) { 1397 query_releasename(client, &fname); 1398 fname = mname; 1399 } else 1400 need_addname = ISC_TRUE; 1401 ISC_LIST_APPEND(fname->list, rdataset, link); 1402 added_something = ISC_TRUE; 1403 if (sigrdataset != NULL && 1404 dns_rdataset_isassociated(sigrdataset)) 1405 { 1406 ISC_LIST_APPEND(fname->list, 1407 sigrdataset, link); 1408 sigrdataset = 1409 query_newrdataset(client); 1410 } 1411 rdataset = query_newrdataset(client); 1412 if (rdataset == NULL) 1413 goto addname; 1414 if (WANTDNSSEC(client) && sigrdataset == NULL) 1415 goto addname; 1416 } else { 1417 dns_rdataset_disassociate(rdataset); 1418 if (sigrdataset != NULL && 1419 dns_rdataset_isassociated(sigrdataset)) 1420 dns_rdataset_disassociate(sigrdataset); 1421 } 1422 } 1423 aaaa_lookup: 1424 if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL)) 1425 goto addname; 1426 result = dns_db_findrdataset(db, node, version, 1427 dns_rdatatype_aaaa, 0, 1428 client->now, rdataset, 1429 sigrdataset); 1430 if (result == DNS_R_NCACHENXDOMAIN) 1431 goto addname; 1432 if (result == DNS_R_NCACHENXRRSET) { 1433 dns_rdataset_disassociate(rdataset); 1434 if (sigrdataset != NULL && 1435 dns_rdataset_isassociated(sigrdataset)) 1436 dns_rdataset_disassociate(sigrdataset); 1437 } 1438 if (result == ISC_R_SUCCESS) { 1439 mname = NULL; 1440 /* 1441 * There's an A; check whether we're filtering AAAA 1442 */ 1443#ifdef ALLOW_FILTER_AAAA_ON_V4 1444 if (have_a && 1445 (client->filter_aaaa == dns_v4_aaaa_break_dnssec || 1446 (client->filter_aaaa == dns_v4_aaaa_filter && 1447 (!WANTDNSSEC(client) || sigrdataset == NULL || 1448 !dns_rdataset_isassociated(sigrdataset))))) 1449 goto addname; 1450#endif 1451 if (!query_isduplicate(client, fname, 1452 dns_rdatatype_aaaa, &mname)) { 1453 if (mname != NULL) { 1454 query_releasename(client, &fname); 1455 fname = mname; 1456 } else 1457 need_addname = ISC_TRUE; 1458 ISC_LIST_APPEND(fname->list, rdataset, link); 1459 added_something = ISC_TRUE; 1460 if (sigrdataset != NULL && 1461 dns_rdataset_isassociated(sigrdataset)) 1462 { 1463 ISC_LIST_APPEND(fname->list, 1464 sigrdataset, link); 1465 sigrdataset = NULL; 1466 } 1467 rdataset = NULL; 1468 } 1469 } 1470 } 1471 1472 addname: 1473 CTRACE("query_addadditional: addname"); 1474 /* 1475 * If we haven't added anything, then we're done. 1476 */ 1477 if (!added_something) 1478 goto cleanup; 1479 1480 /* 1481 * We may have added our rdatasets to an existing name, if so, then 1482 * need_addname will be ISC_FALSE. Whether we used an existing name 1483 * or a new one, we must set fname to NULL to prevent cleanup. 1484 */ 1485 if (need_addname) 1486 dns_message_addname(client->message, fname, 1487 DNS_SECTION_ADDITIONAL); 1488 fname = NULL; 1489 1490 /* 1491 * In a few cases, we want to add additional data for additional 1492 * data. It's simpler to just deal with special cases here than 1493 * to try to create a general purpose mechanism and allow the 1494 * rdata implementations to do it themselves. 1495 * 1496 * This involves recursion, but the depth is limited. The 1497 * most complex case is adding a SRV rdataset, which involves 1498 * recursing to add address records, which in turn can cause 1499 * recursion to add KEYs. 1500 */ 1501 if (type == dns_rdatatype_srv && trdataset != NULL) { 1502 /* 1503 * If we're adding SRV records to the additional data 1504 * section, it's helpful if we add the SRV additional data 1505 * as well. 1506 */ 1507 eresult = dns_rdataset_additionaldata(trdataset, 1508 query_addadditional, 1509 client); 1510 } 1511 1512 cleanup: 1513 CTRACE("query_addadditional: cleanup"); 1514 query_putrdataset(client, &rdataset); 1515 if (sigrdataset != NULL) 1516 query_putrdataset(client, &sigrdataset); 1517 if (fname != NULL) 1518 query_releasename(client, &fname); 1519 if (node != NULL) 1520 dns_db_detachnode(db, &node); 1521 if (db != NULL) 1522 dns_db_detach(&db); 1523 if (zone != NULL) 1524 dns_zone_detach(&zone); 1525 1526 CTRACE("query_addadditional: done"); 1527 return (eresult); 1528} 1529 1530static inline void 1531query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base, 1532 dns_rdatasetadditional_t additionaltype, 1533 dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp, 1534 dns_dbversion_t **versionp, dns_dbnode_t **nodep, 1535 dns_name_t *fname) 1536{ 1537 dns_rdataset_t *rdataset; 1538 1539 while ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) { 1540 ISC_LIST_UNLINK(fname->list, rdataset, link); 1541 query_putrdataset(client, &rdataset); 1542 } 1543 if (*versionp != NULL) 1544 dns_db_closeversion(*dbp, versionp, ISC_FALSE); 1545 if (*nodep != NULL) 1546 dns_db_detachnode(*dbp, nodep); 1547 if (*dbp != NULL) 1548 dns_db_detach(dbp); 1549 if (*zonep != NULL) 1550 dns_zone_detach(zonep); 1551 (void)dns_rdataset_putadditional(client->view->acache, rdataset_base, 1552 additionaltype, type); 1553} 1554 1555static inline isc_result_t 1556query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0, 1557 dns_dbversion_t *version) 1558{ 1559 isc_result_t result = ISC_R_SUCCESS; 1560 dns_dbversion_t *version_current = NULL; 1561 dns_db_t *db_current = db0; 1562 1563 if (db_current == NULL) { 1564 result = dns_zone_getdb(zone, &db_current); 1565 if (result != ISC_R_SUCCESS) 1566 return (result); 1567 } 1568 dns_db_currentversion(db_current, &version_current); 1569 if (db_current != db || version_current != version) { 1570 result = ISC_R_FAILURE; 1571 goto cleanup; 1572 } 1573 1574 cleanup: 1575 dns_db_closeversion(db_current, &version_current, ISC_FALSE); 1576 if (db0 == NULL && db_current != NULL) 1577 dns_db_detach(&db_current); 1578 1579 return (result); 1580} 1581 1582static isc_result_t 1583query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { 1584 client_additionalctx_t *additionalctx = arg; 1585 dns_rdataset_t *rdataset_base; 1586 ns_client_t *client; 1587 isc_result_t result, eresult; 1588 dns_dbnode_t *node, *cnode; 1589 dns_db_t *db, *cdb; 1590 dns_name_t *fname, *mname0, cfname; 1591 dns_rdataset_t *rdataset, *sigrdataset; 1592 dns_rdataset_t *crdataset, *crdataset_next; 1593 isc_buffer_t *dbuf; 1594 isc_buffer_t b; 1595 dns_dbversion_t *version, *cversion; 1596 isc_boolean_t added_something, need_addname, needadditionalcache; 1597 isc_boolean_t need_sigrrset; 1598 dns_zone_t *zone; 1599 dns_rdatatype_t type; 1600 dns_rdatasetadditional_t additionaltype; 1601 1602 /* 1603 * If we don't have an additional cache call query_addadditional. 1604 */ 1605 client = additionalctx->client; 1606 REQUIRE(NS_CLIENT_VALID(client)); 1607 1608 if (qtype != dns_rdatatype_a || client->view->acache == NULL) { 1609 /* 1610 * This function is optimized for "address" types. For other 1611 * types, use a generic routine. 1612 * XXX: ideally, this function should be generic enough. 1613 */ 1614 return (query_addadditional(additionalctx->client, 1615 name, qtype)); 1616 } 1617 1618 /* 1619 * Initialization. 1620 */ 1621 rdataset_base = additionalctx->rdataset; 1622 eresult = ISC_R_SUCCESS; 1623 fname = NULL; 1624 rdataset = NULL; 1625 sigrdataset = NULL; 1626 db = NULL; 1627 cdb = NULL; 1628 version = NULL; 1629 cversion = NULL; 1630 node = NULL; 1631 cnode = NULL; 1632 added_something = ISC_FALSE; 1633 need_addname = ISC_FALSE; 1634 zone = NULL; 1635 needadditionalcache = ISC_FALSE; 1636 POST(needadditionalcache); 1637 additionaltype = dns_rdatasetadditional_fromauth; 1638 dns_name_init(&cfname, NULL); 1639 1640 CTRACE("query_addadditional2"); 1641 1642 /* 1643 * We treat type A additional section processing as if it 1644 * were "any address type" additional section processing. 1645 * To avoid multiple lookups, we do an 'any' database 1646 * lookup and iterate over the node. 1647 * XXXJT: this approach can cause a suboptimal result when the cache 1648 * DB only has partial address types and the glue DB has remaining 1649 * ones. 1650 */ 1651 type = dns_rdatatype_any; 1652 1653 /* 1654 * Get some resources. 1655 */ 1656 dbuf = query_getnamebuf(client); 1657 if (dbuf == NULL) 1658 goto cleanup; 1659 fname = query_newname(client, dbuf, &b); 1660 if (fname == NULL) 1661 goto cleanup; 1662 dns_name_setbuffer(&cfname, &b); /* share the buffer */ 1663 1664 /* Check additional cache */ 1665 result = dns_rdataset_getadditional(rdataset_base, additionaltype, 1666 type, client->view->acache, &zone, 1667 &cdb, &cversion, &cnode, &cfname, 1668 client->message, client->now); 1669 if (result != ISC_R_SUCCESS) 1670 goto findauthdb; 1671 if (zone == NULL) { 1672 CTRACE("query_addadditional2: auth zone not found"); 1673 goto try_cache; 1674 } 1675 1676 /* Is the cached DB up-to-date? */ 1677 result = query_iscachevalid(zone, cdb, NULL, cversion); 1678 if (result != ISC_R_SUCCESS) { 1679 CTRACE("query_addadditional2: old auth additional cache"); 1680 query_discardcache(client, rdataset_base, additionaltype, 1681 type, &zone, &cdb, &cversion, &cnode, 1682 &cfname); 1683 goto findauthdb; 1684 } 1685 1686 if (cnode == NULL) { 1687 /* 1688 * We have a negative cache. We don't have to check the zone 1689 * ACL, since the result (not using this zone) would be same 1690 * regardless of the result. 1691 */ 1692 CTRACE("query_addadditional2: negative auth additional cache"); 1693 dns_db_closeversion(cdb, &cversion, ISC_FALSE); 1694 dns_db_detach(&cdb); 1695 dns_zone_detach(&zone); 1696 goto try_cache; 1697 } 1698 1699 result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG, 1700 zone, cdb, NULL); 1701 if (result != ISC_R_SUCCESS) { 1702 query_discardcache(client, rdataset_base, additionaltype, 1703 type, &zone, &cdb, &cversion, &cnode, 1704 &cfname); 1705 goto try_cache; 1706 } 1707 1708 /* We've got an active cache. */ 1709 CTRACE("query_addadditional2: auth additional cache"); 1710 dns_db_closeversion(cdb, &cversion, ISC_FALSE); 1711 db = cdb; 1712 node = cnode; 1713 dns_name_clone(&cfname, fname); 1714 query_keepname(client, fname, dbuf); 1715 goto foundcache; 1716 1717 /* 1718 * Look for a zone database that might contain authoritative 1719 * additional data. 1720 */ 1721 findauthdb: 1722 result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG, 1723 &zone, &db, &version); 1724 if (result != ISC_R_SUCCESS) { 1725 /* Cache the negative result */ 1726 (void)dns_rdataset_setadditional(rdataset_base, additionaltype, 1727 type, client->view->acache, 1728 NULL, NULL, NULL, NULL, 1729 NULL); 1730 goto try_cache; 1731 } 1732 1733 CTRACE("query_addadditional2: db_find"); 1734 1735 /* 1736 * Since we are looking for authoritative data, we do not set 1737 * the GLUEOK flag. Glue will be looked for later, but not 1738 * necessarily in the same database. 1739 */ 1740 node = NULL; 1741 result = dns_db_find(db, name, version, type, client->query.dboptions, 1742 client->now, &node, fname, NULL, NULL); 1743 if (result == ISC_R_SUCCESS) 1744 goto found; 1745 1746 /* Cache the negative result */ 1747 (void)dns_rdataset_setadditional(rdataset_base, additionaltype, 1748 type, client->view->acache, zone, db, 1749 version, NULL, fname); 1750 1751 if (node != NULL) 1752 dns_db_detachnode(db, &node); 1753 version = NULL; 1754 dns_db_detach(&db); 1755 1756 /* 1757 * No authoritative data was found. The cache is our next best bet. 1758 */ 1759 1760 try_cache: 1761 additionaltype = dns_rdatasetadditional_fromcache; 1762 result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG); 1763 if (result != ISC_R_SUCCESS) 1764 /* 1765 * Most likely the client isn't allowed to query the cache. 1766 */ 1767 goto try_glue; 1768 1769 result = dns_db_find(db, name, version, type, 1770 client->query.dboptions | 1771 DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, 1772 client->now, &node, fname, NULL, NULL); 1773 if (result == ISC_R_SUCCESS) 1774 goto found; 1775 1776 if (node != NULL) 1777 dns_db_detachnode(db, &node); 1778 dns_db_detach(&db); 1779 1780 try_glue: 1781 /* 1782 * No cached data was found. Glue is our last chance. 1783 * RFC1035 sayeth: 1784 * 1785 * NS records cause both the usual additional section 1786 * processing to locate a type A record, and, when used 1787 * in a referral, a special search of the zone in which 1788 * they reside for glue information. 1789 * 1790 * This is the "special search". Note that we must search 1791 * the zone where the NS record resides, not the zone it 1792 * points to, and that we only do the search in the delegation 1793 * case (identified by client->query.gluedb being set). 1794 */ 1795 if (client->query.gluedb == NULL) 1796 goto cleanup; 1797 1798 /* 1799 * Don't poison caches using the bailiwick protection model. 1800 */ 1801 if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) 1802 goto cleanup; 1803 1804 /* Check additional cache */ 1805 additionaltype = dns_rdatasetadditional_fromglue; 1806 result = dns_rdataset_getadditional(rdataset_base, additionaltype, 1807 type, client->view->acache, NULL, 1808 &cdb, &cversion, &cnode, &cfname, 1809 client->message, client->now); 1810 if (result != ISC_R_SUCCESS) 1811 goto findglue; 1812 1813 result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion); 1814 if (result != ISC_R_SUCCESS) { 1815 CTRACE("query_addadditional2: old glue additional cache"); 1816 query_discardcache(client, rdataset_base, additionaltype, 1817 type, &zone, &cdb, &cversion, &cnode, 1818 &cfname); 1819 goto findglue; 1820 } 1821 1822 if (cnode == NULL) { 1823 /* We have a negative cache. */ 1824 CTRACE("query_addadditional2: negative glue additional cache"); 1825 dns_db_closeversion(cdb, &cversion, ISC_FALSE); 1826 dns_db_detach(&cdb); 1827 goto cleanup; 1828 } 1829 1830 /* Cache hit. */ 1831 CTRACE("query_addadditional2: glue additional cache"); 1832 dns_db_closeversion(cdb, &cversion, ISC_FALSE); 1833 db = cdb; 1834 node = cnode; 1835 dns_name_clone(&cfname, fname); 1836 query_keepname(client, fname, dbuf); 1837 goto foundcache; 1838 1839 findglue: 1840 dns_db_attach(client->query.gluedb, &db); 1841 result = dns_db_find(db, name, version, type, 1842 client->query.dboptions | DNS_DBFIND_GLUEOK, 1843 client->now, &node, fname, NULL, NULL); 1844 if (!(result == ISC_R_SUCCESS || 1845 result == DNS_R_ZONECUT || 1846 result == DNS_R_GLUE)) { 1847 /* cache the negative result */ 1848 (void)dns_rdataset_setadditional(rdataset_base, additionaltype, 1849 type, client->view->acache, 1850 NULL, db, version, NULL, 1851 fname); 1852 goto cleanup; 1853 } 1854 1855 found: 1856 /* 1857 * We have found a DB node to iterate over from a DB. 1858 * We are going to look for address RRsets (i.e., A and AAAA) in the DB 1859 * node we've just found. We'll then store the complete information 1860 * in the additional data cache. 1861 */ 1862 dns_name_clone(fname, &cfname); 1863 query_keepname(client, fname, dbuf); 1864 needadditionalcache = ISC_TRUE; 1865 1866 rdataset = query_newrdataset(client); 1867 if (rdataset == NULL) 1868 goto cleanup; 1869 1870 sigrdataset = query_newrdataset(client); 1871 if (sigrdataset == NULL) 1872 goto cleanup; 1873 1874 if (additionaltype == dns_rdatasetadditional_fromcache && 1875 query_isduplicate(client, fname, dns_rdatatype_a, NULL)) 1876 goto aaaa_lookup; 1877 /* 1878 * Find A RRset with sig RRset. Even if we don't find a sig RRset 1879 * for a client using DNSSEC, we'll continue the process to make a 1880 * complete list to be cached. However, we need to cancel the 1881 * caching when something unexpected happens, in order to avoid 1882 * caching incomplete information. 1883 */ 1884 result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0, 1885 client->now, rdataset, sigrdataset); 1886 /* 1887 * If we can't promote glue/pending from the cache to secure 1888 * then drop it. 1889 */ 1890 if (result == ISC_R_SUCCESS && 1891 additionaltype == dns_rdatasetadditional_fromcache && 1892 (DNS_TRUST_PENDING(rdataset->trust) || 1893 DNS_TRUST_GLUE(rdataset->trust)) && 1894 !validate(client, db, fname, rdataset, sigrdataset)) { 1895 dns_rdataset_disassociate(rdataset); 1896 if (dns_rdataset_isassociated(sigrdataset)) 1897 dns_rdataset_disassociate(sigrdataset); 1898 result = ISC_R_NOTFOUND; 1899 } 1900 if (result == DNS_R_NCACHENXDOMAIN) 1901 goto setcache; 1902 if (result == DNS_R_NCACHENXRRSET) { 1903 dns_rdataset_disassociate(rdataset); 1904 if (dns_rdataset_isassociated(sigrdataset)) 1905 dns_rdataset_disassociate(sigrdataset); 1906 } 1907 if (result == ISC_R_SUCCESS) { 1908 /* Remember the result as a cache */ 1909 ISC_LIST_APPEND(cfname.list, rdataset, link); 1910 if (dns_rdataset_isassociated(sigrdataset)) { 1911 ISC_LIST_APPEND(cfname.list, sigrdataset, link); 1912 sigrdataset = query_newrdataset(client); 1913 } 1914 rdataset = query_newrdataset(client); 1915 if (sigrdataset == NULL || rdataset == NULL) { 1916 /* do not cache incomplete information */ 1917 goto foundcache; 1918 } 1919 } 1920 1921 aaaa_lookup: 1922 if (additionaltype == dns_rdatasetadditional_fromcache && 1923 query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL)) 1924 goto foundcache; 1925 /* Find AAAA RRset with sig RRset */ 1926 result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa, 1927 0, client->now, rdataset, sigrdataset); 1928 /* 1929 * If we can't promote glue/pending from the cache to secure 1930 * then drop it. 1931 */ 1932 if (result == ISC_R_SUCCESS && 1933 additionaltype == dns_rdatasetadditional_fromcache && 1934 (DNS_TRUST_PENDING(rdataset->trust) || 1935 DNS_TRUST_GLUE(rdataset->trust)) && 1936 !validate(client, db, fname, rdataset, sigrdataset)) { 1937 dns_rdataset_disassociate(rdataset); 1938 if (dns_rdataset_isassociated(sigrdataset)) 1939 dns_rdataset_disassociate(sigrdataset); 1940 result = ISC_R_NOTFOUND; 1941 } 1942 if (result == ISC_R_SUCCESS) { 1943 ISC_LIST_APPEND(cfname.list, rdataset, link); 1944 rdataset = NULL; 1945 if (dns_rdataset_isassociated(sigrdataset)) { 1946 ISC_LIST_APPEND(cfname.list, sigrdataset, link); 1947 sigrdataset = NULL; 1948 } 1949 } 1950 1951 setcache: 1952 /* 1953 * Set the new result in the cache if required. We do not support 1954 * caching additional data from a cache DB. 1955 */ 1956 if (needadditionalcache == ISC_TRUE && 1957 (additionaltype == dns_rdatasetadditional_fromauth || 1958 additionaltype == dns_rdatasetadditional_fromglue)) { 1959 (void)dns_rdataset_setadditional(rdataset_base, additionaltype, 1960 type, client->view->acache, 1961 zone, db, version, node, 1962 &cfname); 1963 } 1964 1965 foundcache: 1966 need_sigrrset = ISC_FALSE; 1967 mname0 = NULL; 1968 for (crdataset = ISC_LIST_HEAD(cfname.list); 1969 crdataset != NULL; 1970 crdataset = crdataset_next) { 1971 dns_name_t *mname; 1972 1973 crdataset_next = ISC_LIST_NEXT(crdataset, link); 1974 1975 mname = NULL; 1976 if (crdataset->type == dns_rdatatype_a || 1977 crdataset->type == dns_rdatatype_aaaa) { 1978 if (!query_isduplicate(client, fname, crdataset->type, 1979 &mname)) { 1980 if (mname != NULL) { 1981 /* 1982 * A different type of this name is 1983 * already stored in the additional 1984 * section. We'll reuse the name. 1985 * Note that this should happen at most 1986 * once. Otherwise, fname->link could 1987 * leak below. 1988 */ 1989 INSIST(mname0 == NULL); 1990 1991 query_releasename(client, &fname); 1992 fname = mname; 1993 mname0 = mname; 1994 } else 1995 need_addname = ISC_TRUE; 1996 ISC_LIST_UNLINK(cfname.list, crdataset, link); 1997 ISC_LIST_APPEND(fname->list, crdataset, link); 1998 added_something = ISC_TRUE; 1999 need_sigrrset = ISC_TRUE; 2000 } else 2001 need_sigrrset = ISC_FALSE; 2002 } else if (crdataset->type == dns_rdatatype_rrsig && 2003 need_sigrrset && WANTDNSSEC(client)) { 2004 ISC_LIST_UNLINK(cfname.list, crdataset, link); 2005 ISC_LIST_APPEND(fname->list, crdataset, link); 2006 added_something = ISC_TRUE; /* just in case */ 2007 need_sigrrset = ISC_FALSE; 2008 } 2009 } 2010 2011 CTRACE("query_addadditional2: addname"); 2012 2013 /* 2014 * If we haven't added anything, then we're done. 2015 */ 2016 if (!added_something) 2017 goto cleanup; 2018 2019 /* 2020 * We may have added our rdatasets to an existing name, if so, then 2021 * need_addname will be ISC_FALSE. Whether we used an existing name 2022 * or a new one, we must set fname to NULL to prevent cleanup. 2023 */ 2024 if (need_addname) 2025 dns_message_addname(client->message, fname, 2026 DNS_SECTION_ADDITIONAL); 2027 fname = NULL; 2028 2029 cleanup: 2030 CTRACE("query_addadditional2: cleanup"); 2031 2032 if (rdataset != NULL) 2033 query_putrdataset(client, &rdataset); 2034 if (sigrdataset != NULL) 2035 query_putrdataset(client, &sigrdataset); 2036 while ((crdataset = ISC_LIST_HEAD(cfname.list)) != NULL) { 2037 ISC_LIST_UNLINK(cfname.list, crdataset, link); 2038 query_putrdataset(client, &crdataset); 2039 } 2040 if (fname != NULL) 2041 query_releasename(client, &fname); 2042 if (node != NULL) 2043 dns_db_detachnode(db, &node); 2044 if (db != NULL) 2045 dns_db_detach(&db); 2046 if (zone != NULL) 2047 dns_zone_detach(&zone); 2048 2049 CTRACE("query_addadditional2: done"); 2050 return (eresult); 2051} 2052 2053static inline void 2054query_addrdataset(ns_client_t *client, dns_name_t *fname, 2055 dns_rdataset_t *rdataset) 2056{ 2057 client_additionalctx_t additionalctx; 2058 2059 /* 2060 * Add 'rdataset' and any pertinent additional data to 2061 * 'fname', a name in the response message for 'client'. 2062 */ 2063 2064 CTRACE("query_addrdataset"); 2065 2066 ISC_LIST_APPEND(fname->list, rdataset, link); 2067 2068 if (client->view->order != NULL) 2069 rdataset->attributes |= dns_order_find(client->view->order, 2070 fname, rdataset->type, 2071 rdataset->rdclass); 2072 rdataset->attributes |= DNS_RDATASETATTR_LOADORDER; 2073 2074 if (NOADDITIONAL(client)) 2075 return; 2076 2077 /* 2078 * Add additional data. 2079 * 2080 * We don't care if dns_rdataset_additionaldata() fails. 2081 */ 2082 additionalctx.client = client; 2083 additionalctx.rdataset = rdataset; 2084 (void)dns_rdataset_additionaldata(rdataset, query_addadditional2, 2085 &additionalctx); 2086 CTRACE("query_addrdataset: done"); 2087} 2088 2089static isc_result_t 2090query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset, 2091 dns_rdataset_t *sigrdataset, isc_buffer_t *dbuf, 2092 dns_section_t section) 2093{ 2094 dns_name_t *name, *mname; 2095 dns_rdata_t *dns64_rdata; 2096 dns_rdata_t rdata = DNS_RDATA_INIT; 2097 dns_rdatalist_t *dns64_rdatalist; 2098 dns_rdataset_t *dns64_rdataset; 2099 dns_rdataset_t *mrdataset; 2100 isc_buffer_t *buffer; 2101 isc_region_t r; 2102 isc_result_t result; 2103 dns_view_t *view = client->view; 2104 isc_netaddr_t netaddr; 2105 dns_dns64_t *dns64; 2106 unsigned int flags = 0; 2107 2108 /*% 2109 * To the current response for 'client', add the answer RRset 2110 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with 2111 * owner name '*namep', to section 'section', unless they are 2112 * already there. Also add any pertinent additional data. 2113 * 2114 * If 'dbuf' is not NULL, then '*namep' is the name whose data is 2115 * stored in 'dbuf'. In this case, query_addrrset() guarantees that 2116 * when it returns the name will either have been kept or released. 2117 */ 2118 CTRACE("query_dns64"); 2119 name = *namep; 2120 mname = NULL; 2121 mrdataset = NULL; 2122 buffer = NULL; 2123 dns64_rdata = NULL; 2124 dns64_rdataset = NULL; 2125 dns64_rdatalist = NULL; 2126 result = dns_message_findname(client->message, section, 2127 name, dns_rdatatype_aaaa, 2128 rdataset->covers, 2129 &mname, &mrdataset); 2130 if (result == ISC_R_SUCCESS) { 2131 /* 2132 * We've already got an RRset of the given name and type. 2133 * There's nothing else to do; 2134 */ 2135 CTRACE("query_dns64: dns_message_findname succeeded: done"); 2136 if (dbuf != NULL) 2137 query_releasename(client, namep); 2138 return (ISC_R_SUCCESS); 2139 } else if (result == DNS_R_NXDOMAIN) { 2140 /* 2141 * The name doesn't exist. 2142 */ 2143 if (dbuf != NULL) 2144 query_keepname(client, name, dbuf); 2145 dns_message_addname(client->message, name, section); 2146 *namep = NULL; 2147 mname = name; 2148 } else { 2149 RUNTIME_CHECK(result == DNS_R_NXRRSET); 2150 if (dbuf != NULL) 2151 query_releasename(client, namep); 2152 } 2153 2154 if (rdataset->trust != dns_trust_secure && 2155 (section == DNS_SECTION_ANSWER || 2156 section == DNS_SECTION_AUTHORITY)) 2157 client->query.attributes &= ~NS_QUERYATTR_SECURE; 2158 2159 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); 2160 2161 result = isc_buffer_allocate(client->mctx, &buffer, view->dns64cnt * 2162 16 * dns_rdataset_count(rdataset)); 2163 if (result != ISC_R_SUCCESS) 2164 goto cleanup; 2165 result = dns_message_gettemprdataset(client->message, &dns64_rdataset); 2166 if (result != ISC_R_SUCCESS) 2167 goto cleanup; 2168 result = dns_message_gettemprdatalist(client->message, 2169 &dns64_rdatalist); 2170 if (result != ISC_R_SUCCESS) 2171 goto cleanup; 2172 2173 dns_rdataset_init(dns64_rdataset); 2174 dns_rdatalist_init(dns64_rdatalist); 2175 dns64_rdatalist->rdclass = dns_rdataclass_in; 2176 dns64_rdatalist->type = dns_rdatatype_aaaa; 2177 if (client->query.dns64_ttl != ISC_UINT32_MAX) 2178 dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, 2179 client->query.dns64_ttl); 2180 else 2181 dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, 600); 2182 2183 if (RECURSIONOK(client)) 2184 flags |= DNS_DNS64_RECURSIVE; 2185 2186 /* 2187 * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC 2188 * as this provides a easy way to see if the answer was signed. 2189 */ 2190 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) 2191 flags |= DNS_DNS64_DNSSEC; 2192 2193 for (result = dns_rdataset_first(rdataset); 2194 result == ISC_R_SUCCESS; 2195 result = dns_rdataset_next(rdataset)) { 2196 for (dns64 = ISC_LIST_HEAD(client->view->dns64); 2197 dns64 != NULL; dns64 = dns_dns64_next(dns64)) { 2198 2199 dns_rdataset_current(rdataset, &rdata); 2200 isc__buffer_availableregion(buffer, &r); 2201 INSIST(r.length >= 16); 2202 result = dns_dns64_aaaafroma(dns64, &netaddr, 2203 client->signer, 2204 &ns_g_server->aclenv, 2205 flags, rdata.data, r.base); 2206 if (result != ISC_R_SUCCESS) { 2207 dns_rdata_reset(&rdata); 2208 continue; 2209 } 2210 isc_buffer_add(buffer, 16); 2211 isc_buffer_remainingregion(buffer, &r); 2212 isc_buffer_forward(buffer, 16); 2213 result = dns_message_gettemprdata(client->message, 2214 &dns64_rdata); 2215 if (result != ISC_R_SUCCESS) 2216 goto cleanup; 2217 dns_rdata_init(dns64_rdata); 2218 dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in, 2219 dns_rdatatype_aaaa, &r); 2220 ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata, 2221 link); 2222 dns64_rdata = NULL; 2223 dns_rdata_reset(&rdata); 2224 } 2225 } 2226 if (result != ISC_R_NOMORE) 2227 goto cleanup; 2228 2229 if (ISC_LIST_EMPTY(dns64_rdatalist->rdata)) 2230 goto cleanup; 2231 2232 result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset); 2233 if (result != ISC_R_SUCCESS) 2234 goto cleanup; 2235 client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; 2236 dns64_rdataset->trust = rdataset->trust; 2237 query_addrdataset(client, mname, dns64_rdataset); 2238 dns64_rdataset = NULL; 2239 dns64_rdatalist = NULL; 2240 dns_message_takebuffer(client->message, &buffer); 2241 result = ISC_R_SUCCESS; 2242 2243 cleanup: 2244 if (buffer != NULL) 2245 isc_buffer_free(&buffer); 2246 2247 if (dns64_rdata != NULL) 2248 dns_message_puttemprdata(client->message, &dns64_rdata); 2249 2250 if (dns64_rdataset != NULL) 2251 dns_message_puttemprdataset(client->message, &dns64_rdataset); 2252 2253 if (dns64_rdatalist != NULL) { 2254 for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata); 2255 dns64_rdata != NULL; 2256 dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata)) 2257 { 2258 ISC_LIST_UNLINK(dns64_rdatalist->rdata, 2259 dns64_rdata, link); 2260 dns_message_puttemprdata(client->message, &dns64_rdata); 2261 } 2262 dns_message_puttemprdatalist(client->message, &dns64_rdatalist); 2263 } 2264 2265 CTRACE("query_dns64: done"); 2266 return (result); 2267} 2268 2269static void 2270query_filter64(ns_client_t *client, dns_name_t **namep, 2271 dns_rdataset_t *rdataset, isc_buffer_t *dbuf, 2272 dns_section_t section) 2273{ 2274 dns_name_t *name, *mname; 2275 dns_rdata_t *myrdata; 2276 dns_rdata_t rdata = DNS_RDATA_INIT; 2277 dns_rdatalist_t *myrdatalist; 2278 dns_rdataset_t *myrdataset; 2279 isc_buffer_t *buffer; 2280 isc_region_t r; 2281 isc_result_t result; 2282 unsigned int i; 2283 2284 CTRACE("query_filter64"); 2285 2286 INSIST(client->query.dns64_aaaaok != NULL); 2287 INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset)); 2288 2289 name = *namep; 2290 mname = NULL; 2291 buffer = NULL; 2292 myrdata = NULL; 2293 myrdataset = NULL; 2294 myrdatalist = NULL; 2295 result = dns_message_findname(client->message, section, 2296 name, dns_rdatatype_aaaa, 2297 rdataset->covers, 2298 &mname, &myrdataset); 2299 if (result == ISC_R_SUCCESS) { 2300 /* 2301 * We've already got an RRset of the given name and type. 2302 * There's nothing else to do; 2303 */ 2304 CTRACE("query_filter64: dns_message_findname succeeded: done"); 2305 if (dbuf != NULL) 2306 query_releasename(client, namep); 2307 return; 2308 } else if (result == DNS_R_NXDOMAIN) { 2309 mname = name; 2310 *namep = NULL; 2311 } else { 2312 RUNTIME_CHECK(result == DNS_R_NXRRSET); 2313 if (dbuf != NULL) 2314 query_releasename(client, namep); 2315 dbuf = NULL; 2316 } 2317 2318 if (rdataset->trust != dns_trust_secure && 2319 (section == DNS_SECTION_ANSWER || 2320 section == DNS_SECTION_AUTHORITY)) 2321 client->query.attributes &= ~NS_QUERYATTR_SECURE; 2322 2323 result = isc_buffer_allocate(client->mctx, &buffer, 2324 16 * dns_rdataset_count(rdataset)); 2325 if (result != ISC_R_SUCCESS) 2326 goto cleanup; 2327 result = dns_message_gettemprdataset(client->message, &myrdataset); 2328 if (result != ISC_R_SUCCESS) 2329 goto cleanup; 2330 result = dns_message_gettemprdatalist(client->message, &myrdatalist); 2331 if (result != ISC_R_SUCCESS) 2332 goto cleanup; 2333 2334 dns_rdataset_init(myrdataset); 2335 dns_rdatalist_init(myrdatalist); 2336 myrdatalist->rdclass = dns_rdataclass_in; 2337 myrdatalist->type = dns_rdatatype_aaaa; 2338 myrdatalist->ttl = rdataset->ttl; 2339 2340 i = 0; 2341 for (result = dns_rdataset_first(rdataset); 2342 result == ISC_R_SUCCESS; 2343 result = dns_rdataset_next(rdataset)) { 2344 if (!client->query.dns64_aaaaok[i++]) 2345 continue; 2346 dns_rdataset_current(rdataset, &rdata); 2347 INSIST(rdata.length == 16); 2348 isc_buffer_putmem(buffer, rdata.data, rdata.length); 2349 isc_buffer_remainingregion(buffer, &r); 2350 isc_buffer_forward(buffer, rdata.length); 2351 result = dns_message_gettemprdata(client->message, &myrdata); 2352 if (result != ISC_R_SUCCESS) 2353 goto cleanup; 2354 dns_rdata_init(myrdata); 2355 dns_rdata_fromregion(myrdata, dns_rdataclass_in, 2356 dns_rdatatype_aaaa, &r); 2357 ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link); 2358 myrdata = NULL; 2359 dns_rdata_reset(&rdata); 2360 } 2361 if (result != ISC_R_NOMORE) 2362 goto cleanup; 2363 2364 result = dns_rdatalist_tordataset(myrdatalist, myrdataset); 2365 if (result != ISC_R_SUCCESS) 2366 goto cleanup; 2367 client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; 2368 if (mname == name) { 2369 if (dbuf != NULL) 2370 query_keepname(client, name, dbuf); 2371 dns_message_addname(client->message, name, section); 2372 dbuf = NULL; 2373 } 2374 myrdataset->trust = rdataset->trust; 2375 query_addrdataset(client, mname, myrdataset); 2376 myrdataset = NULL; 2377 myrdatalist = NULL; 2378 dns_message_takebuffer(client->message, &buffer); 2379 2380 cleanup: 2381 if (buffer != NULL) 2382 isc_buffer_free(&buffer); 2383 2384 if (myrdata != NULL) 2385 dns_message_puttemprdata(client->message, &myrdata); 2386 2387 if (myrdataset != NULL) 2388 dns_message_puttemprdataset(client->message, &myrdataset); 2389 2390 if (myrdatalist != NULL) { 2391 for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata); 2392 myrdata != NULL; 2393 myrdata = ISC_LIST_HEAD(myrdatalist->rdata)) 2394 { 2395 ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link); 2396 dns_message_puttemprdata(client->message, &myrdata); 2397 } 2398 dns_message_puttemprdatalist(client->message, &myrdatalist); 2399 } 2400 if (dbuf != NULL) 2401 query_releasename(client, &name); 2402 2403 CTRACE("query_filter64: done"); 2404} 2405 2406static void 2407query_addrrset(ns_client_t *client, dns_name_t **namep, 2408 dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp, 2409 isc_buffer_t *dbuf, dns_section_t section) 2410{ 2411 dns_name_t *name, *mname; 2412 dns_rdataset_t *rdataset, *mrdataset, *sigrdataset; 2413 isc_result_t result; 2414 2415 /*% 2416 * To the current response for 'client', add the answer RRset 2417 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with 2418 * owner name '*namep', to section 'section', unless they are 2419 * already there. Also add any pertinent additional data. 2420 * 2421 * If 'dbuf' is not NULL, then '*namep' is the name whose data is 2422 * stored in 'dbuf'. In this case, query_addrrset() guarantees that 2423 * when it returns the name will either have been kept or released. 2424 */ 2425 CTRACE("query_addrrset"); 2426 name = *namep; 2427 rdataset = *rdatasetp; 2428 if (sigrdatasetp != NULL) 2429 sigrdataset = *sigrdatasetp; 2430 else 2431 sigrdataset = NULL; 2432 mname = NULL; 2433 mrdataset = NULL; 2434 result = dns_message_findname(client->message, section, 2435 name, rdataset->type, rdataset->covers, 2436 &mname, &mrdataset); 2437 if (result == ISC_R_SUCCESS) { 2438 /* 2439 * We've already got an RRset of the given name and type. 2440 * There's nothing else to do; 2441 */ 2442 CTRACE("query_addrrset: dns_message_findname succeeded: done"); 2443 if (dbuf != NULL) 2444 query_releasename(client, namep); 2445 return; 2446 } else if (result == DNS_R_NXDOMAIN) { 2447 /* 2448 * The name doesn't exist. 2449 */ 2450 if (dbuf != NULL) 2451 query_keepname(client, name, dbuf); 2452 dns_message_addname(client->message, name, section); 2453 *namep = NULL; 2454 mname = name; 2455 } else { 2456 RUNTIME_CHECK(result == DNS_R_NXRRSET); 2457 if (dbuf != NULL) 2458 query_releasename(client, namep); 2459 } 2460 2461 if (rdataset->trust != dns_trust_secure && 2462 (section == DNS_SECTION_ANSWER || 2463 section == DNS_SECTION_AUTHORITY)) 2464 client->query.attributes &= ~NS_QUERYATTR_SECURE; 2465 /* 2466 * Note: we only add SIGs if we've added the type they cover, so 2467 * we do not need to check if the SIG rdataset is already in the 2468 * response. 2469 */ 2470 query_addrdataset(client, mname, rdataset); 2471 *rdatasetp = NULL; 2472 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { 2473 /* 2474 * We have a signature. Add it to the response. 2475 */ 2476 ISC_LIST_APPEND(mname->list, sigrdataset, link); 2477 *sigrdatasetp = NULL; 2478 } 2479 CTRACE("query_addrrset: done"); 2480} 2481 2482static inline isc_result_t 2483query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, 2484 unsigned int override_ttl, isc_boolean_t isassociated) 2485{ 2486 dns_name_t *name; 2487 dns_dbnode_t *node; 2488 isc_result_t result, eresult; 2489 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 2490 dns_rdataset_t **sigrdatasetp = NULL; 2491 2492 CTRACE("query_addsoa"); 2493 /* 2494 * Initialization. 2495 */ 2496 eresult = ISC_R_SUCCESS; 2497 name = NULL; 2498 rdataset = NULL; 2499 node = NULL; 2500 2501 /* 2502 * Don't add the SOA record for test which set "-T nosoa". 2503 */ 2504 if (ns_g_nosoa && (!WANTDNSSEC(client) || !isassociated)) 2505 return (ISC_R_SUCCESS); 2506 2507 /* 2508 * Get resources and make 'name' be the database origin. 2509 */ 2510 result = dns_message_gettempname(client->message, &name); 2511 if (result != ISC_R_SUCCESS) 2512 return (result); 2513 dns_name_init(name, NULL); 2514 dns_name_clone(dns_db_origin(db), name); 2515 rdataset = query_newrdataset(client); 2516 if (rdataset == NULL) { 2517 eresult = DNS_R_SERVFAIL; 2518 goto cleanup; 2519 } 2520 if (WANTDNSSEC(client) && dns_db_issecure(db)) { 2521 sigrdataset = query_newrdataset(client); 2522 if (sigrdataset == NULL) { 2523 eresult = DNS_R_SERVFAIL; 2524 goto cleanup; 2525 } 2526 } 2527 2528 /* 2529 * Find the SOA. 2530 */ 2531 result = dns_db_getoriginnode(db, &node); 2532 if (result == ISC_R_SUCCESS) { 2533 result = dns_db_findrdataset(db, node, version, 2534 dns_rdatatype_soa, 2535 0, client->now, rdataset, 2536 sigrdataset); 2537 } else { 2538 dns_fixedname_t foundname; 2539 dns_name_t *fname; 2540 2541 dns_fixedname_init(&foundname); 2542 fname = dns_fixedname_name(&foundname); 2543 2544 result = dns_db_find(db, name, version, dns_rdatatype_soa, 2545 client->query.dboptions, 0, &node, 2546 fname, rdataset, sigrdataset); 2547 } 2548 if (result != ISC_R_SUCCESS) { 2549 /* 2550 * This is bad. We tried to get the SOA RR at the zone top 2551 * and it didn't work! 2552 */ 2553 eresult = DNS_R_SERVFAIL; 2554 } else { 2555 /* 2556 * Extract the SOA MINIMUM. 2557 */ 2558 dns_rdata_soa_t soa; 2559 dns_rdata_t rdata = DNS_RDATA_INIT; 2560 result = dns_rdataset_first(rdataset); 2561 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2562 dns_rdataset_current(rdataset, &rdata); 2563 result = dns_rdata_tostruct(&rdata, &soa, NULL); 2564 if (result != ISC_R_SUCCESS) 2565 goto cleanup; 2566 2567 if (override_ttl != ISC_UINT32_MAX && 2568 override_ttl < rdataset->ttl) { 2569 rdataset->ttl = override_ttl; 2570 if (sigrdataset != NULL) 2571 sigrdataset->ttl = override_ttl; 2572 } 2573 2574 /* 2575 * Add the SOA and its SIG to the response, with the 2576 * TTLs adjusted per RFC2308 section 3. 2577 */ 2578 if (rdataset->ttl > soa.minimum) 2579 rdataset->ttl = soa.minimum; 2580 if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum) 2581 sigrdataset->ttl = soa.minimum; 2582 2583 if (sigrdataset != NULL) 2584 sigrdatasetp = &sigrdataset; 2585 else 2586 sigrdatasetp = NULL; 2587 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL, 2588 DNS_SECTION_AUTHORITY); 2589 } 2590 2591 cleanup: 2592 query_putrdataset(client, &rdataset); 2593 if (sigrdataset != NULL) 2594 query_putrdataset(client, &sigrdataset); 2595 if (name != NULL) 2596 query_releasename(client, &name); 2597 if (node != NULL) 2598 dns_db_detachnode(db, &node); 2599 2600 return (eresult); 2601} 2602 2603static inline isc_result_t 2604query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { 2605 dns_name_t *name, *fname; 2606 dns_dbnode_t *node; 2607 isc_result_t result, eresult; 2608 dns_fixedname_t foundname; 2609 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 2610 dns_rdataset_t **sigrdatasetp = NULL; 2611 2612 CTRACE("query_addns"); 2613 /* 2614 * Initialization. 2615 */ 2616 eresult = ISC_R_SUCCESS; 2617 name = NULL; 2618 rdataset = NULL; 2619 node = NULL; 2620 dns_fixedname_init(&foundname); 2621 fname = dns_fixedname_name(&foundname); 2622 2623 /* 2624 * Get resources and make 'name' be the database origin. 2625 */ 2626 result = dns_message_gettempname(client->message, &name); 2627 if (result != ISC_R_SUCCESS) { 2628 CTRACE("query_addns: dns_message_gettempname failed: done"); 2629 return (result); 2630 } 2631 dns_name_init(name, NULL); 2632 dns_name_clone(dns_db_origin(db), name); 2633 rdataset = query_newrdataset(client); 2634 if (rdataset == NULL) { 2635 CTRACE("query_addns: query_newrdataset failed"); 2636 eresult = DNS_R_SERVFAIL; 2637 goto cleanup; 2638 } 2639 if (WANTDNSSEC(client) && dns_db_issecure(db)) { 2640 sigrdataset = query_newrdataset(client); 2641 if (sigrdataset == NULL) { 2642 CTRACE("query_addns: query_newrdataset failed"); 2643 eresult = DNS_R_SERVFAIL; 2644 goto cleanup; 2645 } 2646 } 2647 2648 /* 2649 * Find the NS rdataset. 2650 */ 2651 result = dns_db_getoriginnode(db, &node); 2652 if (result == ISC_R_SUCCESS) { 2653 result = dns_db_findrdataset(db, node, version, 2654 dns_rdatatype_ns, 2655 0, client->now, rdataset, 2656 sigrdataset); 2657 } else { 2658 CTRACE("query_addns: calling dns_db_find"); 2659 result = dns_db_find(db, name, NULL, dns_rdatatype_ns, 2660 client->query.dboptions, 0, &node, 2661 fname, rdataset, sigrdataset); 2662 CTRACE("query_addns: dns_db_find complete"); 2663 } 2664 if (result != ISC_R_SUCCESS) { 2665 CTRACE("query_addns: " 2666 "dns_db_findrdataset or dns_db_find failed"); 2667 /* 2668 * This is bad. We tried to get the NS rdataset at the zone 2669 * top and it didn't work! 2670 */ 2671 eresult = DNS_R_SERVFAIL; 2672 } else { 2673 if (sigrdataset != NULL) 2674 sigrdatasetp = &sigrdataset; 2675 else 2676 sigrdatasetp = NULL; 2677 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL, 2678 DNS_SECTION_AUTHORITY); 2679 } 2680 2681 cleanup: 2682 CTRACE("query_addns: cleanup"); 2683 query_putrdataset(client, &rdataset); 2684 if (sigrdataset != NULL) 2685 query_putrdataset(client, &sigrdataset); 2686 if (name != NULL) 2687 query_releasename(client, &name); 2688 if (node != NULL) 2689 dns_db_detachnode(db, &node); 2690 2691 CTRACE("query_addns: done"); 2692 return (eresult); 2693} 2694 2695static isc_result_t 2696query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname, 2697 dns_trust_t trust, dns_ttl_t ttl) 2698{ 2699 dns_rdataset_t *rdataset; 2700 dns_rdatalist_t *rdatalist; 2701 dns_rdata_t *rdata; 2702 isc_region_t r; 2703 dns_name_t *aname; 2704 isc_result_t result; 2705 2706 /* 2707 * We assume the name data referred to by tname won't go away. 2708 */ 2709 2710 aname = NULL; 2711 result = dns_message_gettempname(client->message, &aname); 2712 if (result != ISC_R_SUCCESS) 2713 return (result); 2714 result = dns_name_dup(qname, client->mctx, aname); 2715 if (result != ISC_R_SUCCESS) { 2716 dns_message_puttempname(client->message, &aname); 2717 return (result); 2718 } 2719 2720 rdatalist = NULL; 2721 result = dns_message_gettemprdatalist(client->message, &rdatalist); 2722 if (result != ISC_R_SUCCESS) { 2723 dns_message_puttempname(client->message, &aname); 2724 return (result); 2725 } 2726 rdata = NULL; 2727 result = dns_message_gettemprdata(client->message, &rdata); 2728 if (result != ISC_R_SUCCESS) { 2729 dns_message_puttempname(client->message, &aname); 2730 dns_message_puttemprdatalist(client->message, &rdatalist); 2731 return (result); 2732 } 2733 rdataset = NULL; 2734 result = dns_message_gettemprdataset(client->message, &rdataset); 2735 if (result != ISC_R_SUCCESS) { 2736 dns_message_puttempname(client->message, &aname); 2737 dns_message_puttemprdatalist(client->message, &rdatalist); 2738 dns_message_puttemprdata(client->message, &rdata); 2739 return (result); 2740 } 2741 dns_rdataset_init(rdataset); 2742 rdatalist->type = dns_rdatatype_cname; 2743 rdatalist->covers = 0; 2744 rdatalist->rdclass = client->message->rdclass; 2745 rdatalist->ttl = ttl; 2746 2747 dns_name_toregion(tname, &r); 2748 rdata->data = r.base; 2749 rdata->length = r.length; 2750 rdata->rdclass = client->message->rdclass; 2751 rdata->type = dns_rdatatype_cname; 2752 2753 ISC_LIST_INIT(rdatalist->rdata); 2754 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 2755 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) 2756 == ISC_R_SUCCESS); 2757 rdataset->trust = trust; 2758 2759 query_addrrset(client, &aname, &rdataset, NULL, NULL, 2760 DNS_SECTION_ANSWER); 2761 if (rdataset != NULL) { 2762 if (dns_rdataset_isassociated(rdataset)) 2763 dns_rdataset_disassociate(rdataset); 2764 dns_message_puttemprdataset(client->message, &rdataset); 2765 } 2766 if (aname != NULL) 2767 dns_message_puttempname(client->message, &aname); 2768 2769 return (ISC_R_SUCCESS); 2770} 2771 2772/* 2773 * Mark the RRsets as secure. Update the cache (db) to reflect the 2774 * change in trust level. 2775 */ 2776static void 2777mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name, 2778 isc_uint32_t ttl, dns_rdataset_t *rdataset, 2779 dns_rdataset_t *sigrdataset) 2780{ 2781 isc_result_t result; 2782 dns_dbnode_t *node = NULL; 2783 2784 rdataset->trust = dns_trust_secure; 2785 sigrdataset->trust = dns_trust_secure; 2786 2787 /* 2788 * Save the updated secure state. Ignore failures. 2789 */ 2790 result = dns_db_findnode(db, name, ISC_TRUE, &node); 2791 if (result != ISC_R_SUCCESS) 2792 return; 2793 /* 2794 * Bound the validated ttls then minimise. 2795 */ 2796 if (sigrdataset->ttl > ttl) 2797 sigrdataset->ttl = ttl; 2798 if (rdataset->ttl > ttl) 2799 rdataset->ttl = ttl; 2800 if (rdataset->ttl > sigrdataset->ttl) 2801 rdataset->ttl = sigrdataset->ttl; 2802 else 2803 sigrdataset->ttl = rdataset->ttl; 2804 2805 (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset, 2806 0, NULL); 2807 (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset, 2808 0, NULL); 2809 dns_db_detachnode(db, &node); 2810} 2811 2812/* 2813 * Find the secure key that corresponds to rrsig. 2814 * Note: 'keyrdataset' maintains state between successive calls, 2815 * there may be multiple keys with the same keyid. 2816 * Return ISC_FALSE if we have exhausted all the possible keys. 2817 */ 2818static isc_boolean_t 2819get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig, 2820 dns_rdataset_t *keyrdataset, dst_key_t **keyp) 2821{ 2822 isc_result_t result; 2823 dns_dbnode_t *node = NULL; 2824 isc_boolean_t secure = ISC_FALSE; 2825 2826 if (!dns_rdataset_isassociated(keyrdataset)) { 2827 result = dns_db_findnode(db, &rrsig->signer, ISC_FALSE, &node); 2828 if (result != ISC_R_SUCCESS) 2829 return (ISC_FALSE); 2830 2831 result = dns_db_findrdataset(db, node, NULL, 2832 dns_rdatatype_dnskey, 0, 2833 client->now, keyrdataset, NULL); 2834 dns_db_detachnode(db, &node); 2835 if (result != ISC_R_SUCCESS) 2836 return (ISC_FALSE); 2837 2838 if (keyrdataset->trust != dns_trust_secure) 2839 return (ISC_FALSE); 2840 2841 result = dns_rdataset_first(keyrdataset); 2842 } else 2843 result = dns_rdataset_next(keyrdataset); 2844 2845 for ( ; result == ISC_R_SUCCESS; 2846 result = dns_rdataset_next(keyrdataset)) { 2847 dns_rdata_t rdata = DNS_RDATA_INIT; 2848 isc_buffer_t b; 2849 2850 dns_rdataset_current(keyrdataset, &rdata); 2851 isc_buffer_init(&b, rdata.data, rdata.length); 2852 isc_buffer_add(&b, rdata.length); 2853 result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b, 2854 client->mctx, keyp); 2855 if (result != ISC_R_SUCCESS) 2856 continue; 2857 if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) && 2858 rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) && 2859 dst_key_iszonekey(*keyp)) { 2860 secure = ISC_TRUE; 2861 break; 2862 } 2863 dst_key_free(keyp); 2864 } 2865 return (secure); 2866} 2867 2868static isc_boolean_t 2869verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset, 2870 dns_rdata_t *rdata, isc_mem_t *mctx, isc_boolean_t acceptexpired) 2871{ 2872 isc_result_t result; 2873 dns_fixedname_t fixed; 2874 isc_boolean_t ignore = ISC_FALSE; 2875 2876 dns_fixedname_init(&fixed); 2877 2878again: 2879 result = dns_dnssec_verify2(name, rdataset, key, ignore, mctx, 2880 rdata, NULL); 2881 if (result == DNS_R_SIGEXPIRED && acceptexpired) { 2882 ignore = ISC_TRUE; 2883 goto again; 2884 } 2885 if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) 2886 return (ISC_TRUE); 2887 return (ISC_FALSE); 2888} 2889 2890/* 2891 * Validate the rdataset if possible with available records. 2892 */ 2893static isc_boolean_t 2894validate(ns_client_t *client, dns_db_t *db, dns_name_t *name, 2895 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 2896{ 2897 isc_result_t result; 2898 dns_rdata_t rdata = DNS_RDATA_INIT; 2899 dns_rdata_rrsig_t rrsig; 2900 dst_key_t *key = NULL; 2901 dns_rdataset_t keyrdataset; 2902 2903 if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)) 2904 return (ISC_FALSE); 2905 2906 for (result = dns_rdataset_first(sigrdataset); 2907 result == ISC_R_SUCCESS; 2908 result = dns_rdataset_next(sigrdataset)) { 2909 2910 dns_rdata_reset(&rdata); 2911 dns_rdataset_current(sigrdataset, &rdata); 2912 result = dns_rdata_tostruct(&rdata, &rrsig, NULL); 2913 if (result != ISC_R_SUCCESS) 2914 return (ISC_FALSE); 2915 if (!dns_resolver_algorithm_supported(client->view->resolver, 2916 name, rrsig.algorithm)) 2917 continue; 2918 if (!dns_name_issubdomain(name, &rrsig.signer)) 2919 continue; 2920 dns_rdataset_init(&keyrdataset); 2921 do { 2922 if (!get_key(client, db, &rrsig, &keyrdataset, &key)) 2923 break; 2924 if (verify(key, name, rdataset, &rdata, client->mctx, 2925 client->view->acceptexpired)) { 2926 dst_key_free(&key); 2927 dns_rdataset_disassociate(&keyrdataset); 2928 mark_secure(client, db, name, 2929 rrsig.originalttl, 2930 rdataset, sigrdataset); 2931 return (ISC_TRUE); 2932 } 2933 dst_key_free(&key); 2934 } while (1); 2935 if (dns_rdataset_isassociated(&keyrdataset)) 2936 dns_rdataset_disassociate(&keyrdataset); 2937 } 2938 return (ISC_FALSE); 2939} 2940 2941static void 2942query_addbestns(ns_client_t *client) { 2943 dns_db_t *db, *zdb; 2944 dns_dbnode_t *node; 2945 dns_name_t *fname, *zfname; 2946 dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset; 2947 isc_boolean_t is_zone, use_zone; 2948 isc_buffer_t *dbuf; 2949 isc_result_t result; 2950 dns_dbversion_t *version; 2951 dns_zone_t *zone; 2952 isc_buffer_t b; 2953 2954 CTRACE("query_addbestns"); 2955 fname = NULL; 2956 zfname = NULL; 2957 rdataset = NULL; 2958 zrdataset = NULL; 2959 sigrdataset = NULL; 2960 zsigrdataset = NULL; 2961 node = NULL; 2962 db = NULL; 2963 zdb = NULL; 2964 version = NULL; 2965 zone = NULL; 2966 is_zone = ISC_FALSE; 2967 use_zone = ISC_FALSE; 2968 2969 /* 2970 * Find the right database. 2971 */ 2972 result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0, 2973 &zone, &db, &version, &is_zone); 2974 if (result != ISC_R_SUCCESS) 2975 goto cleanup; 2976 2977 db_find: 2978 /* 2979 * We'll need some resources... 2980 */ 2981 dbuf = query_getnamebuf(client); 2982 if (dbuf == NULL) 2983 goto cleanup; 2984 fname = query_newname(client, dbuf, &b); 2985 rdataset = query_newrdataset(client); 2986 if (fname == NULL || rdataset == NULL) 2987 goto cleanup; 2988 /* 2989 * Get the RRSIGs if the client requested them or if we may 2990 * need to validate answers from the cache. 2991 */ 2992 if (WANTDNSSEC(client) || !is_zone) { 2993 sigrdataset = query_newrdataset(client); 2994 if (sigrdataset == NULL) 2995 goto cleanup; 2996 } 2997 2998 /* 2999 * Now look for the zonecut. 3000 */ 3001 if (is_zone) { 3002 result = dns_db_find(db, client->query.qname, version, 3003 dns_rdatatype_ns, client->query.dboptions, 3004 client->now, &node, fname, 3005 rdataset, sigrdataset); 3006 if (result != DNS_R_DELEGATION) 3007 goto cleanup; 3008 if (USECACHE(client)) { 3009 query_keepname(client, fname, dbuf); 3010 zdb = db; 3011 zfname = fname; 3012 fname = NULL; 3013 zrdataset = rdataset; 3014 rdataset = NULL; 3015 zsigrdataset = sigrdataset; 3016 sigrdataset = NULL; 3017 dns_db_detachnode(db, &node); 3018 version = NULL; 3019 db = NULL; 3020 dns_db_attach(client->view->cachedb, &db); 3021 is_zone = ISC_FALSE; 3022 goto db_find; 3023 } 3024 } else { 3025 result = dns_db_findzonecut(db, client->query.qname, 3026 client->query.dboptions, 3027 client->now, &node, fname, 3028 rdataset, sigrdataset); 3029 if (result == ISC_R_SUCCESS) { 3030 if (zfname != NULL && 3031 !dns_name_issubdomain(fname, zfname)) { 3032 /* 3033 * We found a zonecut in the cache, but our 3034 * zone delegation is better. 3035 */ 3036 use_zone = ISC_TRUE; 3037 } 3038 } else if (result == ISC_R_NOTFOUND && zfname != NULL) { 3039 /* 3040 * We didn't find anything in the cache, but we 3041 * have a zone delegation, so use it. 3042 */ 3043 use_zone = ISC_TRUE; 3044 } else 3045 goto cleanup; 3046 } 3047 3048 if (use_zone) { 3049 query_releasename(client, &fname); 3050 fname = zfname; 3051 zfname = NULL; 3052 /* 3053 * We've already done query_keepname() on 3054 * zfname, so we must set dbuf to NULL to 3055 * prevent query_addrrset() from trying to 3056 * call query_keepname() again. 3057 */ 3058 dbuf = NULL; 3059 query_putrdataset(client, &rdataset); 3060 if (sigrdataset != NULL) 3061 query_putrdataset(client, &sigrdataset); 3062 rdataset = zrdataset; 3063 zrdataset = NULL; 3064 sigrdataset = zsigrdataset; 3065 zsigrdataset = NULL; 3066 } 3067 3068 /* 3069 * Attempt to validate RRsets that are pending or that are glue. 3070 */ 3071 if ((DNS_TRUST_PENDING(rdataset->trust) || 3072 (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust))) 3073 && !validate(client, db, fname, rdataset, sigrdataset) && 3074 !PENDINGOK(client->query.dboptions)) 3075 goto cleanup; 3076 3077 if ((DNS_TRUST_GLUE(rdataset->trust) || 3078 (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) && 3079 !validate(client, db, fname, rdataset, sigrdataset) && 3080 SECURE(client) && WANTDNSSEC(client)) 3081 goto cleanup; 3082 3083 /* 3084 * If the client doesn't want DNSSEC we can discard the sigrdataset 3085 * now. 3086 */ 3087 if (!WANTDNSSEC(client)) 3088 query_putrdataset(client, &sigrdataset); 3089 query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, 3090 DNS_SECTION_AUTHORITY); 3091 3092 cleanup: 3093 if (rdataset != NULL) 3094 query_putrdataset(client, &rdataset); 3095 if (sigrdataset != NULL) 3096 query_putrdataset(client, &sigrdataset); 3097 if (fname != NULL) 3098 query_releasename(client, &fname); 3099 if (node != NULL) 3100 dns_db_detachnode(db, &node); 3101 if (db != NULL) 3102 dns_db_detach(&db); 3103 if (zone != NULL) 3104 dns_zone_detach(&zone); 3105 if (zdb != NULL) { 3106 query_putrdataset(client, &zrdataset); 3107 if (zsigrdataset != NULL) 3108 query_putrdataset(client, &zsigrdataset); 3109 if (zfname != NULL) 3110 query_releasename(client, &zfname); 3111 dns_db_detach(&zdb); 3112 } 3113} 3114 3115static void 3116fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) { 3117 if (*rdataset == NULL) 3118 *rdataset = query_newrdataset(client); 3119 else if (dns_rdataset_isassociated(*rdataset)) 3120 dns_rdataset_disassociate(*rdataset); 3121} 3122 3123static void 3124fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf, 3125 isc_buffer_t *nbuf) 3126{ 3127 if (*fname == NULL) { 3128 *dbuf = query_getnamebuf(client); 3129 if (*dbuf == NULL) 3130 return; 3131 *fname = query_newname(client, *dbuf, nbuf); 3132 } 3133} 3134 3135static void 3136query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node, 3137 dns_dbversion_t *version, dns_name_t *name) 3138{ 3139 dns_fixedname_t fixed; 3140 dns_name_t *fname = NULL; 3141 dns_name_t *rname; 3142 dns_rdataset_t *rdataset, *sigrdataset; 3143 isc_buffer_t *dbuf, b; 3144 isc_result_t result; 3145 unsigned int count; 3146 3147 CTRACE("query_addds"); 3148 rname = NULL; 3149 rdataset = NULL; 3150 sigrdataset = NULL; 3151 3152 /* 3153 * We'll need some resources... 3154 */ 3155 rdataset = query_newrdataset(client); 3156 sigrdataset = query_newrdataset(client); 3157 if (rdataset == NULL || sigrdataset == NULL) 3158 goto cleanup; 3159 3160 /* 3161 * Look for the DS record, which may or may not be present. 3162 */ 3163 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ds, 0, 3164 client->now, rdataset, sigrdataset); 3165 /* 3166 * If we didn't find it, look for an NSEC. 3167 */ 3168 if (result == ISC_R_NOTFOUND) 3169 result = dns_db_findrdataset(db, node, version, 3170 dns_rdatatype_nsec, 0, client->now, 3171 rdataset, sigrdataset); 3172 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) 3173 goto addnsec3; 3174 if (!dns_rdataset_isassociated(rdataset) || 3175 !dns_rdataset_isassociated(sigrdataset)) 3176 goto addnsec3; 3177 3178 /* 3179 * We've already added the NS record, so if the name's not there, 3180 * we have other problems. Use this name rather than calling 3181 * query_addrrset(). 3182 */ 3183 result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY); 3184 if (result != ISC_R_SUCCESS) 3185 goto cleanup; 3186 3187 rname = NULL; 3188 dns_message_currentname(client->message, DNS_SECTION_AUTHORITY, 3189 &rname); 3190 result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL); 3191 if (result != ISC_R_SUCCESS) 3192 goto cleanup; 3193 3194 ISC_LIST_APPEND(rname->list, rdataset, link); 3195 ISC_LIST_APPEND(rname->list, sigrdataset, link); 3196 rdataset = NULL; 3197 sigrdataset = NULL; 3198 return; 3199 3200 addnsec3: 3201 if (!dns_db_iszone(db)) 3202 goto cleanup; 3203 /* 3204 * Add the NSEC3 which proves the DS does not exist. 3205 */ 3206 dbuf = query_getnamebuf(client); 3207 if (dbuf == NULL) 3208 goto cleanup; 3209 fname = query_newname(client, dbuf, &b); 3210 dns_fixedname_init(&fixed); 3211 if (dns_rdataset_isassociated(rdataset)) 3212 dns_rdataset_disassociate(rdataset); 3213 if (dns_rdataset_isassociated(sigrdataset)) 3214 dns_rdataset_disassociate(sigrdataset); 3215 query_findclosestnsec3(name, db, version, client, rdataset, 3216 sigrdataset, fname, ISC_TRUE, 3217 dns_fixedname_name(&fixed)); 3218 if (!dns_rdataset_isassociated(rdataset)) 3219 goto cleanup; 3220 query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, 3221 DNS_SECTION_AUTHORITY); 3222 /* 3223 * Did we find the closest provable encloser instead? 3224 * If so add the nearest to the closest provable encloser. 3225 */ 3226 if (!dns_name_equal(name, dns_fixedname_name(&fixed))) { 3227 count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1; 3228 dns_name_getlabelsequence(name, 3229 dns_name_countlabels(name) - count, 3230 count, dns_fixedname_name(&fixed)); 3231 fixfname(client, &fname, &dbuf, &b); 3232 fixrdataset(client, &rdataset); 3233 fixrdataset(client, &sigrdataset); 3234 if (fname == NULL || rdataset == NULL || sigrdataset == NULL) 3235 goto cleanup; 3236 query_findclosestnsec3(dns_fixedname_name(&fixed), db, version, 3237 client, rdataset, sigrdataset, fname, 3238 ISC_FALSE, NULL); 3239 if (!dns_rdataset_isassociated(rdataset)) 3240 goto cleanup; 3241 query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, 3242 DNS_SECTION_AUTHORITY); 3243 } 3244 3245 cleanup: 3246 if (rdataset != NULL) 3247 query_putrdataset(client, &rdataset); 3248 if (sigrdataset != NULL) 3249 query_putrdataset(client, &sigrdataset); 3250 if (fname != NULL) 3251 query_releasename(client, &fname); 3252} 3253 3254static void 3255query_addwildcardproof(ns_client_t *client, dns_db_t *db, 3256 dns_dbversion_t *version, dns_name_t *name, 3257 isc_boolean_t ispositive, isc_boolean_t nodata) 3258{ 3259 isc_buffer_t *dbuf, b; 3260 dns_name_t *fname; 3261 dns_rdataset_t *rdataset, *sigrdataset; 3262 dns_fixedname_t wfixed; 3263 dns_name_t *wname; 3264 dns_dbnode_t *node; 3265 unsigned int options; 3266 unsigned int olabels, nlabels, labels; 3267 isc_result_t result; 3268 dns_rdata_t rdata = DNS_RDATA_INIT; 3269 dns_rdata_nsec_t nsec; 3270 isc_boolean_t have_wname; 3271 int order; 3272 dns_fixedname_t cfixed; 3273 dns_name_t *cname; 3274 3275 CTRACE("query_addwildcardproof"); 3276 fname = NULL; 3277 rdataset = NULL; 3278 sigrdataset = NULL; 3279 node = NULL; 3280 3281 /* 3282 * Get the NOQNAME proof then if !ispositive 3283 * get the NOWILDCARD proof. 3284 * 3285 * DNS_DBFIND_NOWILD finds the NSEC records that covers the 3286 * name ignoring any wildcard. From the owner and next names 3287 * of this record you can compute which wildcard (if it exists) 3288 * will match by finding the longest common suffix of the 3289 * owner name and next names with the qname and prefixing that 3290 * with the wildcard label. 3291 * 3292 * e.g. 3293 * Given: 3294 * example SOA 3295 * example NSEC b.example 3296 * b.example A 3297 * b.example NSEC a.d.example 3298 * a.d.example A 3299 * a.d.example NSEC g.f.example 3300 * g.f.example A 3301 * g.f.example NSEC z.i.example 3302 * z.i.example A 3303 * z.i.example NSEC example 3304 * 3305 * QNAME: 3306 * a.example -> example NSEC b.example 3307 * owner common example 3308 * next common example 3309 * wild *.example 3310 * d.b.example -> b.example NSEC a.d.example 3311 * owner common b.example 3312 * next common example 3313 * wild *.b.example 3314 * a.f.example -> a.d.example NSEC g.f.example 3315 * owner common example 3316 * next common f.example 3317 * wild *.f.example 3318 * j.example -> z.i.example NSEC example 3319 * owner common example 3320 * next common example 3321 * wild *.example 3322 */ 3323 options = client->query.dboptions | DNS_DBFIND_NOWILD; 3324 dns_fixedname_init(&wfixed); 3325 wname = dns_fixedname_name(&wfixed); 3326 again: 3327 have_wname = ISC_FALSE; 3328 /* 3329 * We'll need some resources... 3330 */ 3331 dbuf = query_getnamebuf(client); 3332 if (dbuf == NULL) 3333 goto cleanup; 3334 fname = query_newname(client, dbuf, &b); 3335 rdataset = query_newrdataset(client); 3336 sigrdataset = query_newrdataset(client); 3337 if (fname == NULL || rdataset == NULL || sigrdataset == NULL) 3338 goto cleanup; 3339 3340 result = dns_db_find(db, name, version, dns_rdatatype_nsec, options, 3341 0, &node, fname, rdataset, sigrdataset); 3342 if (node != NULL) 3343 dns_db_detachnode(db, &node); 3344 3345 if (!dns_rdataset_isassociated(rdataset)) { 3346 /* 3347 * No NSEC proof available, return NSEC3 proofs instead. 3348 */ 3349 dns_fixedname_init(&cfixed); 3350 cname = dns_fixedname_name(&cfixed); 3351 /* 3352 * Find the closest encloser. 3353 */ 3354 dns_name_copy(name, cname, NULL); 3355 while (result == DNS_R_NXDOMAIN) { 3356 labels = dns_name_countlabels(cname) - 1; 3357 /* 3358 * Sanity check. 3359 */ 3360 if (labels == 0U) 3361 goto cleanup; 3362 dns_name_split(cname, labels, NULL, cname); 3363 result = dns_db_find(db, cname, version, 3364 dns_rdatatype_nsec, 3365 options, 0, NULL, fname, 3366 NULL, NULL); 3367 } 3368 /* 3369 * Add closest (provable) encloser NSEC3. 3370 */ 3371 query_findclosestnsec3(cname, db, NULL, client, rdataset, 3372 sigrdataset, fname, ISC_TRUE, cname); 3373 if (!dns_rdataset_isassociated(rdataset)) 3374 goto cleanup; 3375 if (!ispositive) 3376 query_addrrset(client, &fname, &rdataset, &sigrdataset, 3377 dbuf, DNS_SECTION_AUTHORITY); 3378 3379 /* 3380 * Replace resources which were consumed by query_addrrset. 3381 */ 3382 if (fname == NULL) { 3383 dbuf = query_getnamebuf(client); 3384 if (dbuf == NULL) 3385 goto cleanup; 3386 fname = query_newname(client, dbuf, &b); 3387 } 3388 3389 if (rdataset == NULL) 3390 rdataset = query_newrdataset(client); 3391 else if (dns_rdataset_isassociated(rdataset)) 3392 dns_rdataset_disassociate(rdataset); 3393 3394 if (sigrdataset == NULL) 3395 sigrdataset = query_newrdataset(client); 3396 else if (dns_rdataset_isassociated(sigrdataset)) 3397 dns_rdataset_disassociate(sigrdataset); 3398 3399 if (fname == NULL || rdataset == NULL || sigrdataset == NULL) 3400 goto cleanup; 3401 /* 3402 * Add no qname proof. 3403 */ 3404 labels = dns_name_countlabels(cname) + 1; 3405 if (dns_name_countlabels(name) == labels) 3406 dns_name_copy(name, wname, NULL); 3407 else 3408 dns_name_split(name, labels, NULL, wname); 3409 3410 query_findclosestnsec3(wname, db, NULL, client, rdataset, 3411 sigrdataset, fname, ISC_FALSE, NULL); 3412 if (!dns_rdataset_isassociated(rdataset)) 3413 goto cleanup; 3414 query_addrrset(client, &fname, &rdataset, &sigrdataset, 3415 dbuf, DNS_SECTION_AUTHORITY); 3416 3417 if (ispositive) 3418 goto cleanup; 3419 3420 /* 3421 * Replace resources which were consumed by query_addrrset. 3422 */ 3423 if (fname == NULL) { 3424 dbuf = query_getnamebuf(client); 3425 if (dbuf == NULL) 3426 goto cleanup; 3427 fname = query_newname(client, dbuf, &b); 3428 } 3429 3430 if (rdataset == NULL) 3431 rdataset = query_newrdataset(client); 3432 else if (dns_rdataset_isassociated(rdataset)) 3433 dns_rdataset_disassociate(rdataset); 3434 3435 if (sigrdataset == NULL) 3436 sigrdataset = query_newrdataset(client); 3437 else if (dns_rdataset_isassociated(sigrdataset)) 3438 dns_rdataset_disassociate(sigrdataset); 3439 3440 if (fname == NULL || rdataset == NULL || sigrdataset == NULL) 3441 goto cleanup; 3442 /* 3443 * Add the no wildcard proof. 3444 */ 3445 result = dns_name_concatenate(dns_wildcardname, 3446 cname, wname, NULL); 3447 if (result != ISC_R_SUCCESS) 3448 goto cleanup; 3449 3450 query_findclosestnsec3(wname, db, NULL, client, rdataset, 3451 sigrdataset, fname, nodata, NULL); 3452 if (!dns_rdataset_isassociated(rdataset)) 3453 goto cleanup; 3454 query_addrrset(client, &fname, &rdataset, &sigrdataset, 3455 dbuf, DNS_SECTION_AUTHORITY); 3456 3457 goto cleanup; 3458 } else if (result == DNS_R_NXDOMAIN) { 3459 if (!ispositive) 3460 result = dns_rdataset_first(rdataset); 3461 if (result == ISC_R_SUCCESS) { 3462 dns_rdataset_current(rdataset, &rdata); 3463 result = dns_rdata_tostruct(&rdata, &nsec, NULL); 3464 } 3465 if (result == ISC_R_SUCCESS) { 3466 (void)dns_name_fullcompare(name, fname, &order, 3467 &olabels); 3468 (void)dns_name_fullcompare(name, &nsec.next, &order, 3469 &nlabels); 3470 /* 3471 * Check for a pathological condition created when 3472 * serving some malformed signed zones and bail out. 3473 */ 3474 if (dns_name_countlabels(name) == nlabels) 3475 goto cleanup; 3476 3477 if (olabels > nlabels) 3478 dns_name_split(name, olabels, NULL, wname); 3479 else 3480 dns_name_split(name, nlabels, NULL, wname); 3481 result = dns_name_concatenate(dns_wildcardname, 3482 wname, wname, NULL); 3483 if (result == ISC_R_SUCCESS) 3484 have_wname = ISC_TRUE; 3485 dns_rdata_freestruct(&nsec); 3486 } 3487 query_addrrset(client, &fname, &rdataset, &sigrdataset, 3488 dbuf, DNS_SECTION_AUTHORITY); 3489 } 3490 if (rdataset != NULL) 3491 query_putrdataset(client, &rdataset); 3492 if (sigrdataset != NULL) 3493 query_putrdataset(client, &sigrdataset); 3494 if (fname != NULL) 3495 query_releasename(client, &fname); 3496 if (have_wname) { 3497 ispositive = ISC_TRUE; /* prevent loop */ 3498 if (!dns_name_equal(name, wname)) { 3499 name = wname; 3500 goto again; 3501 } 3502 } 3503 cleanup: 3504 if (rdataset != NULL) 3505 query_putrdataset(client, &rdataset); 3506 if (sigrdataset != NULL) 3507 query_putrdataset(client, &sigrdataset); 3508 if (fname != NULL) 3509 query_releasename(client, &fname); 3510} 3511 3512static void 3513query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db, 3514 dns_dbversion_t *version, dns_name_t **namep, 3515 dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp) 3516{ 3517 dns_name_t *name; 3518 dns_rdataset_t *sigrdataset; 3519 dns_rdata_t sigrdata; 3520 dns_rdata_rrsig_t sig; 3521 unsigned int labels; 3522 isc_buffer_t *dbuf, b; 3523 dns_name_t *fname; 3524 isc_result_t result; 3525 3526 name = *namep; 3527 if ((name->attributes & DNS_NAMEATTR_WILDCARD) == 0) { 3528 query_addrrset(client, namep, rdatasetp, sigrdatasetp, 3529 NULL, DNS_SECTION_AUTHORITY); 3530 return; 3531 } 3532 3533 if (sigrdatasetp == NULL) 3534 return; 3535 3536 sigrdataset = *sigrdatasetp; 3537 if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)) 3538 return; 3539 result = dns_rdataset_first(sigrdataset); 3540 if (result != ISC_R_SUCCESS) 3541 return; 3542 dns_rdata_init(&sigrdata); 3543 dns_rdataset_current(sigrdataset, &sigrdata); 3544 result = dns_rdata_tostruct(&sigrdata, &sig, NULL); 3545 if (result != ISC_R_SUCCESS) 3546 return; 3547 3548 labels = dns_name_countlabels(name); 3549 if ((unsigned int)sig.labels + 1 >= labels) 3550 return; 3551 3552 /* XXX */ 3553 query_addwildcardproof(client, db, version, client->query.qname, 3554 ISC_TRUE, ISC_FALSE); 3555 3556 /* 3557 * We'll need some resources... 3558 */ 3559 dbuf = query_getnamebuf(client); 3560 if (dbuf == NULL) 3561 return; 3562 fname = query_newname(client, dbuf, &b); 3563 if (fname == NULL) 3564 return; 3565 dns_name_split(name, sig.labels + 1, NULL, fname); 3566 /* This will succeed, since we've stripped labels. */ 3567 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname, 3568 NULL) == ISC_R_SUCCESS); 3569 query_addrrset(client, &fname, rdatasetp, sigrdatasetp, 3570 dbuf, DNS_SECTION_AUTHORITY); 3571} 3572 3573static void 3574query_resume(isc_task_t *task, isc_event_t *event) { 3575 dns_fetchevent_t *devent = (dns_fetchevent_t *)event; 3576 dns_fetch_t *fetch; 3577 ns_client_t *client; 3578 isc_boolean_t fetch_canceled, client_shuttingdown; 3579 isc_result_t result; 3580 isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_EERRORS; 3581 int errorloglevel; 3582 3583 /* 3584 * Resume a query after recursion. 3585 */ 3586 3587 UNUSED(task); 3588 3589 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE); 3590 client = devent->ev_arg; 3591 REQUIRE(NS_CLIENT_VALID(client)); 3592 REQUIRE(task == client->task); 3593 REQUIRE(RECURSING(client)); 3594 3595 LOCK(&client->query.fetchlock); 3596 if (client->query.fetch != NULL) { 3597 /* 3598 * This is the fetch we've been waiting for. 3599 */ 3600 INSIST(devent->fetch == client->query.fetch); 3601 client->query.fetch = NULL; 3602 fetch_canceled = ISC_FALSE; 3603 /* 3604 * Update client->now. 3605 */ 3606 isc_stdtime_get(&client->now); 3607 } else { 3608 /* 3609 * This is a fetch completion event for a canceled fetch. 3610 * Clean up and don't resume the find. 3611 */ 3612 fetch_canceled = ISC_TRUE; 3613 } 3614 UNLOCK(&client->query.fetchlock); 3615 INSIST(client->query.fetch == NULL); 3616 3617 client->query.attributes &= ~NS_QUERYATTR_RECURSING; 3618 fetch = devent->fetch; 3619 devent->fetch = NULL; 3620 3621 /* 3622 * If this client is shutting down, or this transaction 3623 * has timed out, do not resume the find. 3624 */ 3625 client_shuttingdown = ns_client_shuttingdown(client); 3626 if (fetch_canceled || client_shuttingdown) { 3627 if (devent->node != NULL) 3628 dns_db_detachnode(devent->db, &devent->node); 3629 if (devent->db != NULL) 3630 dns_db_detach(&devent->db); 3631 query_putrdataset(client, &devent->rdataset); 3632 if (devent->sigrdataset != NULL) 3633 query_putrdataset(client, &devent->sigrdataset); 3634 isc_event_free(&event); 3635 if (fetch_canceled) 3636 query_error(client, DNS_R_SERVFAIL, __LINE__); 3637 else 3638 query_next(client, ISC_R_CANCELED); 3639 /* 3640 * This may destroy the client. 3641 */ 3642 ns_client_detach(&client); 3643 } else { 3644 result = query_find(client, devent, 0); 3645 if (result != ISC_R_SUCCESS) { 3646 if (result == DNS_R_SERVFAIL) 3647 errorloglevel = ISC_LOG_DEBUG(2); 3648 else 3649 errorloglevel = ISC_LOG_DEBUG(4); 3650 if (isc_log_wouldlog(ns_g_lctx, errorloglevel)) { 3651 dns_resolver_logfetch(fetch, ns_g_lctx, 3652 logcategory, 3653 NS_LOGMODULE_QUERY, 3654 errorloglevel, ISC_FALSE); 3655 } 3656 } 3657 } 3658 3659 dns_resolver_destroyfetch(&fetch); 3660} 3661 3662static isc_result_t 3663query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, 3664 dns_name_t *qdomain, dns_rdataset_t *nameservers, 3665 isc_boolean_t resuming) 3666{ 3667 isc_result_t result; 3668 dns_rdataset_t *rdataset, *sigrdataset; 3669 isc_sockaddr_t *peeraddr; 3670 3671 if (!resuming) 3672 inc_stats(client, dns_nsstatscounter_recursion); 3673 3674 /* 3675 * We are about to recurse, which means that this client will 3676 * be unavailable for serving new requests for an indeterminate 3677 * amount of time. If this client is currently responsible 3678 * for handling incoming queries, set up a new client 3679 * object to handle them while we are waiting for a 3680 * response. There is no need to replace TCP clients 3681 * because those have already been replaced when the 3682 * connection was accepted (if allowed by the TCP quota). 3683 */ 3684 if (client->recursionquota == NULL) { 3685 result = isc_quota_attach(&ns_g_server->recursionquota, 3686 &client->recursionquota); 3687 if (result == ISC_R_SOFTQUOTA) { 3688 static isc_stdtime_t last = 0; 3689 isc_stdtime_t now; 3690 isc_stdtime_get(&now); 3691 if (now != last) { 3692 last = now; 3693 ns_client_log(client, NS_LOGCATEGORY_CLIENT, 3694 NS_LOGMODULE_QUERY, 3695 ISC_LOG_WARNING, 3696 "recursive-clients soft limit " 3697 "exceeded (%d/%d/%d), " 3698 "aborting oldest query", 3699 client->recursionquota->used, 3700 client->recursionquota->soft, 3701 client->recursionquota->max); 3702 } 3703 ns_client_killoldestquery(client); 3704 result = ISC_R_SUCCESS; 3705 } else if (result == ISC_R_QUOTA) { 3706 static isc_stdtime_t last = 0; 3707 isc_stdtime_t now; 3708 isc_stdtime_get(&now); 3709 if (now != last) { 3710 last = now; 3711 ns_client_log(client, NS_LOGCATEGORY_CLIENT, 3712 NS_LOGMODULE_QUERY, 3713 ISC_LOG_WARNING, 3714 "no more recursive clients " 3715 "(%d/%d/%d): %s", 3716 ns_g_server->recursionquota.used, 3717 ns_g_server->recursionquota.soft, 3718 ns_g_server->recursionquota.max, 3719 isc_result_totext(result)); 3720 } 3721 ns_client_killoldestquery(client); 3722 } 3723 if (result == ISC_R_SUCCESS && !client->mortal && 3724 (client->attributes & NS_CLIENTATTR_TCP) == 0) { 3725 result = ns_client_replace(client); 3726 if (result != ISC_R_SUCCESS) { 3727 ns_client_log(client, NS_LOGCATEGORY_CLIENT, 3728 NS_LOGMODULE_QUERY, 3729 ISC_LOG_WARNING, 3730 "ns_client_replace() failed: %s", 3731 isc_result_totext(result)); 3732 isc_quota_detach(&client->recursionquota); 3733 } 3734 } 3735 if (result != ISC_R_SUCCESS) 3736 return (result); 3737 ns_client_recursing(client); 3738 } 3739 3740 /* 3741 * Invoke the resolver. 3742 */ 3743 REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns); 3744 REQUIRE(client->query.fetch == NULL); 3745 3746 rdataset = query_newrdataset(client); 3747 if (rdataset == NULL) 3748 return (ISC_R_NOMEMORY); 3749 if (WANTDNSSEC(client)) { 3750 sigrdataset = query_newrdataset(client); 3751 if (sigrdataset == NULL) { 3752 query_putrdataset(client, &rdataset); 3753 return (ISC_R_NOMEMORY); 3754 } 3755 } else 3756 sigrdataset = NULL; 3757 3758 if (client->query.timerset == ISC_FALSE) 3759 ns_client_settimeout(client, 60); 3760 if ((client->attributes & NS_CLIENTATTR_TCP) == 0) 3761 peeraddr = &client->peeraddr; 3762 else 3763 peeraddr = NULL; 3764 result = dns_resolver_createfetch2(client->view->resolver, 3765 qname, qtype, qdomain, nameservers, 3766 NULL, peeraddr, client->message->id, 3767 client->query.fetchoptions, 3768 client->task, 3769 query_resume, client, 3770 rdataset, sigrdataset, 3771 &client->query.fetch); 3772 3773 if (result == ISC_R_SUCCESS) { 3774 /* 3775 * Record that we're waiting for an event. A client which 3776 * is shutting down will not be destroyed until all the 3777 * events have been received. 3778 */ 3779 } else { 3780 query_putrdataset(client, &rdataset); 3781 if (sigrdataset != NULL) 3782 query_putrdataset(client, &sigrdataset); 3783 } 3784 3785 return (result); 3786} 3787 3788static inline void 3789rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep, 3790 dns_rdataset_t **rdatasetp) 3791{ 3792 if (nodep != NULL && *nodep != NULL) { 3793 REQUIRE(dbp != NULL && *dbp != NULL); 3794 dns_db_detachnode(*dbp, nodep); 3795 } 3796 if (dbp != NULL && *dbp != NULL) 3797 dns_db_detach(dbp); 3798 if (zonep != NULL && *zonep != NULL) 3799 dns_zone_detach(zonep); 3800 if (rdatasetp != NULL && *rdatasetp != NULL && 3801 dns_rdataset_isassociated(*rdatasetp)) 3802 dns_rdataset_disassociate(*rdatasetp); 3803} 3804 3805static inline isc_result_t 3806rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp, 3807 dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp) 3808{ 3809 REQUIRE(rdatasetp != NULL); 3810 3811 rpz_clean(zonep, dbp, nodep, rdatasetp); 3812 if (*rdatasetp == NULL) { 3813 *rdatasetp = query_newrdataset(client); 3814 if (*rdatasetp == NULL) 3815 return (DNS_R_SERVFAIL); 3816 } 3817 return (ISC_R_SUCCESS); 3818} 3819 3820static void 3821rpz_st_clear(ns_client_t *client) { 3822 dns_rpz_st_t *st = client->query.rpz_st; 3823 3824 rpz_clean(&st->m.zone, &st->m.db, &st->m.node, NULL); 3825 st->m.version = NULL; 3826 if (st->m.rdataset != NULL) 3827 query_putrdataset(client, &st->m.rdataset); 3828 3829 rpz_clean(NULL, &st->r.db, NULL, NULL); 3830 if (st->r.ns_rdataset != NULL) 3831 query_putrdataset(client, &st->r.ns_rdataset); 3832 if (st->r.r_rdataset != NULL) 3833 query_putrdataset(client, &st->r.r_rdataset); 3834 3835 rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL); 3836 if (st->q.rdataset != NULL) 3837 query_putrdataset(client, &st->q.rdataset); 3838 if (st->q.sigrdataset != NULL) 3839 query_putrdataset(client, &st->q.sigrdataset); 3840 st->state = 0; 3841 st->m.type = DNS_RPZ_TYPE_BAD; 3842 st->m.policy = DNS_RPZ_POLICY_MISS; 3843} 3844 3845/* 3846 * Get NS, A, or AAAA rrset for response policy zone checks. 3847 */ 3848static isc_result_t 3849rpz_rrset_find(ns_client_t *client, dns_rpz_type_t rpz_type, 3850 dns_name_t *name, dns_rdatatype_t type, 3851 dns_db_t **dbp, dns_dbversion_t *version, 3852 dns_rdataset_t **rdatasetp, isc_boolean_t resuming) 3853{ 3854 dns_rpz_st_t *st; 3855 isc_boolean_t is_zone; 3856 dns_dbnode_t *node; 3857 dns_fixedname_t fixed; 3858 dns_name_t *found; 3859 isc_result_t result; 3860 3861 st = client->query.rpz_st; 3862 if ((st->state & DNS_RPZ_RECURSING) != 0) { 3863 INSIST(st->r.r_type == type); 3864 INSIST(dns_name_equal(name, st->r_name)); 3865 INSIST(*rdatasetp == NULL || 3866 !dns_rdataset_isassociated(*rdatasetp)); 3867 st->state &= ~DNS_RPZ_RECURSING; 3868 *dbp = st->r.db; 3869 st->r.db = NULL; 3870 if (*rdatasetp != NULL) 3871 query_putrdataset(client, rdatasetp); 3872 *rdatasetp = st->r.r_rdataset; 3873 st->r.r_rdataset = NULL; 3874 result = st->r.r_result; 3875 if (result == DNS_R_DELEGATION) { 3876 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, 3877 rpz_type, name, 3878 "rpz_rrset_find(1) ", result); 3879 st->m.policy = DNS_RPZ_POLICY_ERROR; 3880 result = DNS_R_SERVFAIL; 3881 } 3882 return (result); 3883 } 3884 3885 result = rpz_ready(client, NULL, NULL, NULL, rdatasetp); 3886 if (result != ISC_R_SUCCESS) { 3887 st->m.policy = DNS_RPZ_POLICY_ERROR; 3888 return (result); 3889 } 3890 if (*dbp != NULL) { 3891 is_zone = ISC_FALSE; 3892 } else { 3893 dns_zone_t *zone; 3894 3895 version = NULL; 3896 zone = NULL; 3897 result = query_getdb(client, name, type, 0, &zone, dbp, 3898 &version, &is_zone); 3899 if (result != ISC_R_SUCCESS) { 3900 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, 3901 rpz_type, name, 3902 "rpz_rrset_find(2) ", result); 3903 st->m.policy = DNS_RPZ_POLICY_ERROR; 3904 if (zone != NULL) 3905 dns_zone_detach(&zone); 3906 return (result); 3907 } 3908 if (zone != NULL) 3909 dns_zone_detach(&zone); 3910 } 3911 3912 node = NULL; 3913 dns_fixedname_init(&fixed); 3914 found = dns_fixedname_name(&fixed); 3915 result = dns_db_find(*dbp, name, version, type, DNS_DBFIND_GLUEOK, 3916 client->now, &node, found, *rdatasetp, NULL); 3917 if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) { 3918 /* 3919 * Try the cache if we're authoritative for an 3920 * ancestor but not the domain itself. 3921 */ 3922 rpz_clean(NULL, dbp, &node, rdatasetp); 3923 version = NULL; 3924 dns_db_attach(client->view->cachedb, dbp); 3925 result = dns_db_find(*dbp, name, version, dns_rdatatype_ns, 3926 0, client->now, &node, found, 3927 *rdatasetp, NULL); 3928 } 3929 rpz_clean(NULL, dbp, &node, NULL); 3930 if (result == DNS_R_DELEGATION) { 3931 rpz_clean(NULL, NULL, NULL, rdatasetp); 3932 /* 3933 * Recurse for NS rrset or A or AAAA rrset for an NS. 3934 * Do not recurse for addresses for the query name. 3935 */ 3936 if (rpz_type == DNS_RPZ_TYPE_IP) { 3937 result = DNS_R_NXRRSET; 3938 } else { 3939 dns_name_copy(name, st->r_name, NULL); 3940 result = query_recurse(client, type, st->r_name, 3941 NULL, NULL, resuming); 3942 if (result == ISC_R_SUCCESS) { 3943 st->state |= DNS_RPZ_RECURSING; 3944 result = DNS_R_DELEGATION; 3945 } 3946 } 3947 } 3948 return (result); 3949} 3950 3951/* 3952 * Check the IP address in an A or AAAA rdataset against 3953 * the IP or NSIP response policy rules of a view. 3954 */ 3955static isc_result_t 3956rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset, 3957 dns_rpz_type_t rpz_type) 3958{ 3959 dns_rpz_st_t *st; 3960 dns_dbversion_t *version; 3961 dns_zone_t *zone; 3962 dns_db_t *db; 3963 dns_rpz_zone_t *rpz; 3964 isc_result_t result; 3965 3966 st = client->query.rpz_st; 3967 if (st->m.rdataset == NULL) { 3968 st->m.rdataset = query_newrdataset(client); 3969 if (st->m.rdataset == NULL) 3970 return (DNS_R_SERVFAIL); 3971 } 3972 zone = NULL; 3973 db = NULL; 3974 for (rpz = ISC_LIST_HEAD(client->view->rpz_zones); 3975 rpz != NULL; 3976 rpz = ISC_LIST_NEXT(rpz, link)) { 3977 /* 3978 * Do not check policy zones that cannot replace a policy 3979 * already known to match. 3980 */ 3981 if (st->m.policy != DNS_RPZ_POLICY_MISS) { 3982 if (st->m.rpz->num < rpz->num) 3983 break; 3984 if (st->m.rpz->num == rpz->num && 3985 st->m.type < rpz_type) 3986 continue; 3987 } 3988 3989 /* 3990 * Find the database for this policy zone to get its radix tree. 3991 */ 3992 version = NULL; 3993 result = rpz_getdb(client, rpz_type, &rpz->origin, 3994 &zone, &db, &version); 3995 if (result != ISC_R_SUCCESS) { 3996 rpz_clean(&zone, &db, NULL, NULL); 3997 continue; 3998 } 3999 /* 4000 * Look for a better (e.g. longer prefix) hit for an IP address 4001 * in this rdataset in this radix tree than than the previous 4002 * hit, if any. Note the domain name and quality of the 4003 * best hit. 4004 */ 4005 (void)dns_db_rpz_findips(rpz, rpz_type, zone, db, version, 4006 rdataset, st, 4007 client->query.rpz_st->qname); 4008 rpz_clean(&zone, &db, NULL, NULL); 4009 } 4010 return (ISC_R_SUCCESS); 4011} 4012 4013/* 4014 * Look for an A or AAAA rdataset 4015 * and check for IP or NSIP rewrite policy rules. 4016 */ 4017static isc_result_t 4018rpz_rewrite_rrset(ns_client_t *client, dns_rpz_type_t rpz_type, 4019 dns_rdatatype_t type, dns_name_t *name, 4020 dns_db_t **dbp, dns_dbversion_t *version, 4021 dns_rdataset_t **rdatasetp, isc_boolean_t resuming) 4022{ 4023 isc_result_t result; 4024 4025 result = rpz_rrset_find(client, rpz_type, name, type, dbp, version, 4026 rdatasetp, resuming); 4027 switch (result) { 4028 case ISC_R_SUCCESS: 4029 result = rpz_rewrite_ip(client, *rdatasetp, rpz_type); 4030 break; 4031 case DNS_R_EMPTYNAME: 4032 case DNS_R_EMPTYWILD: 4033 case DNS_R_NXDOMAIN: 4034 case DNS_R_NCACHENXDOMAIN: 4035 case DNS_R_NXRRSET: 4036 case DNS_R_NCACHENXRRSET: 4037 case ISC_R_NOTFOUND: 4038 result = ISC_R_SUCCESS; 4039 break; 4040 case DNS_R_DELEGATION: 4041 case DNS_R_DUPLICATE: 4042 case DNS_R_DROP: 4043 break; 4044 case DNS_R_CNAME: 4045 case DNS_R_DNAME: 4046 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, rpz_type, 4047 name, "NS address rewrite rrset ", result); 4048 result = ISC_R_SUCCESS; 4049 break; 4050 default: 4051 if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { 4052 client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR; 4053 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, 4054 name, "NS address rewrite rrset ", result); 4055 } 4056 break; 4057 } 4058 return (result); 4059} 4060 4061/* 4062 * Look for both A and AAAA rdatasets 4063 * and check for IP or NSIP rewrite policy rules. 4064 * Look only for addresses that will be in the ANSWER section 4065 * when checking for IP rules. 4066 */ 4067static isc_result_t 4068rpz_rewrite_rrsets(ns_client_t *client, dns_rpz_type_t rpz_type, 4069 dns_name_t *name, dns_rdatatype_t type, 4070 dns_rdataset_t **rdatasetp, isc_boolean_t resuming) 4071{ 4072 dns_rpz_st_t *st; 4073 dns_dbversion_t *version; 4074 dns_db_t *ipdb; 4075 isc_result_t result; 4076 4077 st = client->query.rpz_st; 4078 version = NULL; 4079 ipdb = NULL; 4080 if ((st->state & DNS_RPZ_DONE_IPv4) == 0 && 4081 ((rpz_type == DNS_RPZ_TYPE_NSIP) ? 4082 (st->state & DNS_RPZ_HAVE_NSIPv4) : 4083 (st->state & DNS_RPZ_HAVE_IP)) != 0 && 4084 (type == dns_rdatatype_any || type == dns_rdatatype_a)) { 4085 result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_a, 4086 name, &ipdb, version, rdatasetp, 4087 resuming); 4088 if (result == ISC_R_SUCCESS) 4089 st->state |= DNS_RPZ_DONE_IPv4; 4090 } else { 4091 result = ISC_R_SUCCESS; 4092 } 4093 if (result == ISC_R_SUCCESS && 4094 ((rpz_type == DNS_RPZ_TYPE_NSIP) ? 4095 (st->state & DNS_RPZ_HAVE_NSIPv6) : 4096 (st->state & DNS_RPZ_HAVE_IP)) != 0 && 4097 (type == dns_rdatatype_any || type == dns_rdatatype_aaaa)) { 4098 result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_aaaa, 4099 name, &ipdb, version, rdatasetp, 4100 resuming); 4101 } 4102 if (ipdb != NULL) 4103 dns_db_detach(&ipdb); 4104 return (result); 4105} 4106 4107/* 4108 * Get the rrset from a response policy zone. 4109 */ 4110static isc_result_t 4111rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef, 4112 dns_name_t *sname, dns_rpz_type_t rpz_type, dns_zone_t **zonep, 4113 dns_db_t **dbp, dns_dbversion_t **versionp, 4114 dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, 4115 dns_rpz_policy_t *policyp) 4116{ 4117 dns_rpz_policy_t policy; 4118 dns_fixedname_t fixed; 4119 dns_name_t *found; 4120 isc_result_t result; 4121 4122 result = rpz_ready(client, zonep, dbp, nodep, rdatasetp); 4123 if (result != ISC_R_SUCCESS) { 4124 *policyp = DNS_RPZ_POLICY_ERROR; 4125 return (result); 4126 } 4127 4128 /* 4129 * Try to get either a CNAME or the type of record demanded by the 4130 * request from the policy zone. 4131 */ 4132 *versionp = NULL; 4133 result = rpz_getdb(client, rpz_type, qnamef, zonep, dbp, versionp); 4134 if (result != ISC_R_SUCCESS) { 4135 *policyp = DNS_RPZ_POLICY_MISS; 4136 return (DNS_R_NXDOMAIN); 4137 } 4138 4139 dns_fixedname_init(&fixed); 4140 found = dns_fixedname_name(&fixed); 4141 result = dns_db_find(*dbp, qnamef, *versionp, dns_rdatatype_any, 0, 4142 client->now, nodep, found, *rdatasetp, NULL); 4143 if (result == ISC_R_SUCCESS) { 4144 dns_rdatasetiter_t *rdsiter; 4145 4146 rdsiter = NULL; 4147 result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0, 4148 &rdsiter); 4149 if (result != ISC_R_SUCCESS) { 4150 dns_db_detachnode(*dbp, nodep); 4151 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, 4152 qnamef, "allrdatasets()", result); 4153 *policyp = DNS_RPZ_POLICY_ERROR; 4154 return (DNS_R_SERVFAIL); 4155 } 4156 for (result = dns_rdatasetiter_first(rdsiter); 4157 result == ISC_R_SUCCESS; 4158 result = dns_rdatasetiter_next(rdsiter)) { 4159 dns_rdatasetiter_current(rdsiter, *rdatasetp); 4160 if ((*rdatasetp)->type == dns_rdatatype_cname || 4161 (*rdatasetp)->type == qtype) 4162 break; 4163 dns_rdataset_disassociate(*rdatasetp); 4164 } 4165 dns_rdatasetiter_destroy(&rdsiter); 4166 if (result != ISC_R_SUCCESS) { 4167 if (result != ISC_R_NOMORE) { 4168 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, 4169 rpz_type, qnamef, "rdatasetiter", 4170 result); 4171 *policyp = DNS_RPZ_POLICY_ERROR; 4172 return (DNS_R_SERVFAIL); 4173 } 4174 /* 4175 * Ask again to get the right DNS_R_DNAME/NXRRSET/... 4176 * result if there is neither a CNAME nor target type. 4177 */ 4178 if (dns_rdataset_isassociated(*rdatasetp)) 4179 dns_rdataset_disassociate(*rdatasetp); 4180 dns_db_detachnode(*dbp, nodep); 4181 4182 if (qtype == dns_rdatatype_rrsig || 4183 qtype == dns_rdatatype_sig) 4184 result = DNS_R_NXRRSET; 4185 else 4186 result = dns_db_find(*dbp, qnamef, *versionp, 4187 qtype, 0, client->now, 4188 nodep, found, *rdatasetp, 4189 NULL); 4190 } 4191 } 4192 switch (result) { 4193 case ISC_R_SUCCESS: 4194 if ((*rdatasetp)->type != dns_rdatatype_cname) { 4195 policy = DNS_RPZ_POLICY_RECORD; 4196 } else { 4197 policy = dns_rpz_decode_cname(*rdatasetp, sname); 4198 if ((policy == DNS_RPZ_POLICY_RECORD || 4199 policy == DNS_RPZ_POLICY_WILDCNAME) && 4200 qtype != dns_rdatatype_cname && 4201 qtype != dns_rdatatype_any) 4202 result = DNS_R_CNAME; 4203 } 4204 break; 4205 case DNS_R_DNAME: 4206 /* 4207 * DNAME policy RRs have very few if any uses that are not 4208 * better served with simple wildcards. Making the work would 4209 * require complications to get the number of labels matched 4210 * in the name or the found name to the main DNS_R_DNAME case 4211 * in query_find(). So fall through to treat them as NODATA. 4212 */ 4213 case DNS_R_NXRRSET: 4214 policy = DNS_RPZ_POLICY_NODATA; 4215 break; 4216 case DNS_R_NXDOMAIN: 4217 case DNS_R_EMPTYNAME: 4218 /* 4219 * If we don't get a qname hit, 4220 * see if it is worth looking for other types. 4221 */ 4222 dns_db_rpz_enabled(*dbp, client->query.rpz_st); 4223 dns_db_detach(dbp); 4224 dns_zone_detach(zonep); 4225 policy = DNS_RPZ_POLICY_MISS; 4226 break; 4227 default: 4228 dns_db_detach(dbp); 4229 dns_zone_detach(zonep); 4230 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, qnamef, 4231 "", result); 4232 policy = DNS_RPZ_POLICY_ERROR; 4233 result = DNS_R_SERVFAIL; 4234 break; 4235 } 4236 4237 *policyp = policy; 4238 return (result); 4239} 4240 4241/* 4242 * Build and look for a QNAME or NSDNAME owner name in a response policy zone. 4243 */ 4244static isc_result_t 4245rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, 4246 dns_rpz_type_t rpz_type, dns_rdataset_t **rdatasetp) 4247{ 4248 dns_rpz_st_t *st; 4249 dns_rpz_zone_t *rpz; 4250 dns_fixedname_t prefixf, rpz_qnamef; 4251 dns_name_t *prefix, *suffix, *rpz_qname; 4252 dns_zone_t *zone; 4253 dns_db_t *db; 4254 dns_dbversion_t *version; 4255 dns_dbnode_t *node; 4256 dns_rpz_policy_t policy; 4257 unsigned int labels; 4258 isc_result_t result; 4259 4260 st = client->query.rpz_st; 4261 zone = NULL; 4262 db = NULL; 4263 node = NULL; 4264 4265 for (rpz = ISC_LIST_HEAD(client->view->rpz_zones); 4266 rpz != NULL; 4267 rpz = ISC_LIST_NEXT(rpz, link)) { 4268 /* 4269 * Do not check policy zones that cannot replace a policy 4270 * already known to match. 4271 */ 4272 if (st->m.policy != DNS_RPZ_POLICY_MISS) { 4273 if (st->m.rpz->num < rpz->num) 4274 break; 4275 if (st->m.rpz->num == rpz->num && 4276 st->m.type < rpz_type) 4277 continue; 4278 } 4279 /* 4280 * Construct the policy's owner name. 4281 */ 4282 dns_fixedname_init(&prefixf); 4283 prefix = dns_fixedname_name(&prefixf); 4284 dns_name_split(qname, 1, prefix, NULL); 4285 if (rpz_type == DNS_RPZ_TYPE_NSDNAME) 4286 suffix = &rpz->nsdname; 4287 else 4288 suffix = &rpz->origin; 4289 dns_fixedname_init(&rpz_qnamef); 4290 rpz_qname = dns_fixedname_name(&rpz_qnamef); 4291 for (;;) { 4292 result = dns_name_concatenate(prefix, suffix, 4293 rpz_qname, NULL); 4294 if (result == ISC_R_SUCCESS) 4295 break; 4296 INSIST(result == DNS_R_NAMETOOLONG); 4297 labels = dns_name_countlabels(prefix); 4298 if (labels < 2) { 4299 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, 4300 rpz_type, suffix, 4301 "concatentate() ", result); 4302 return (ISC_R_SUCCESS); 4303 } 4304 if (labels+1 == dns_name_countlabels(qname)) { 4305 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, 4306 rpz_type, suffix, 4307 "concatentate() ", result); 4308 } 4309 dns_name_split(prefix, labels - 1, NULL, prefix); 4310 } 4311 4312 /* 4313 * See if the policy record exists. 4314 */ 4315 result = rpz_find(client, qtype, rpz_qname, qname, rpz_type, 4316 &zone, &db, &version, &node, rdatasetp, 4317 &policy); 4318 switch (result) { 4319 case DNS_R_NXDOMAIN: 4320 case DNS_R_EMPTYNAME: 4321 break; 4322 case DNS_R_SERVFAIL: 4323 rpz_clean(&zone, &db, &node, rdatasetp); 4324 st->m.policy = DNS_RPZ_POLICY_ERROR; 4325 return (DNS_R_SERVFAIL); 4326 default: 4327 /* 4328 * We are dealing with names here. 4329 * With more than one applicable policy, prefer 4330 * the earliest configured policy, 4331 * QNAME over IP over NSDNAME over NSIP, 4332 * and the smallest name. 4333 * Because of the testing above, 4334 * we known st->m.rpz->num >= rpz->num and either 4335 * st->m.rpz->num > rpz->num or st->m.type >= rpz_type 4336 */ 4337 if (st->m.policy != DNS_RPZ_POLICY_MISS && 4338 rpz->num == st->m.rpz->num && 4339 (st->m.type < rpz_type || 4340 (st->m.type == rpz_type && 4341 0 >= dns_name_compare(rpz_qname, st->qname)))) 4342 continue; 4343 4344 /* 4345 * Merely log DNS_RPZ_POLICY_DISABLED hits. 4346 */ 4347 if (rpz->policy == DNS_RPZ_POLICY_DISABLED) { 4348 rpz_log_rewrite(client, "disabled ", 4349 policy, rpz_type, rpz_qname); 4350 continue; 4351 } 4352 4353 rpz_clean(&st->m.zone, &st->m.db, &st->m.node, 4354 &st->m.rdataset); 4355 st->m.rpz = rpz; 4356 st->m.type = rpz_type; 4357 st->m.prefix = 0; 4358 st->m.policy = policy; 4359 st->m.result = result; 4360 dns_name_copy(rpz_qname, st->qname, NULL); 4361 if (*rdatasetp != NULL && 4362 dns_rdataset_isassociated(*rdatasetp)) { 4363 dns_rdataset_t *trdataset; 4364 4365 trdataset = st->m.rdataset; 4366 st->m.rdataset = *rdatasetp; 4367 *rdatasetp = trdataset; 4368 st->m.ttl = st->m.rdataset->ttl; 4369 } else { 4370 st->m.ttl = DNS_RPZ_TTL_DEFAULT; 4371 } 4372 st->m.node = node; 4373 node = NULL; 4374 st->m.db = db; 4375 db = NULL; 4376 st->m.version = version; 4377 st->m.zone = zone; 4378 zone = NULL; 4379 } 4380 } 4381 4382 rpz_clean(&zone, &db, &node, rdatasetp); 4383 return (ISC_R_SUCCESS); 4384} 4385 4386static void 4387rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname, 4388 isc_result_t result, int level, const char *str) 4389{ 4390 dns_rpz_st_t *st; 4391 4392 st = client->query.rpz_st; 4393 4394 if (str != NULL) 4395 rpz_log_fail(client, level, DNS_RPZ_TYPE_NSIP, nsname, 4396 str, result); 4397 if (st->r.ns_rdataset != NULL && 4398 dns_rdataset_isassociated(st->r.ns_rdataset)) 4399 dns_rdataset_disassociate(st->r.ns_rdataset); 4400 4401 st->r.label--; 4402} 4403 4404/* 4405 * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting. 4406 */ 4407static isc_result_t 4408rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, 4409 isc_boolean_t resuming) 4410{ 4411 dns_rpz_st_t *st; 4412 dns_rdataset_t *rdataset; 4413 dns_fixedname_t nsnamef; 4414 dns_name_t *nsname; 4415 isc_boolean_t ck_ip; 4416 isc_result_t result; 4417 4418 st = client->query.rpz_st; 4419 if (st == NULL) { 4420 st = isc_mem_get(client->mctx, sizeof(*st)); 4421 if (st == NULL) 4422 return (ISC_R_NOMEMORY); 4423 st->state = 0; 4424 memset(&st->m, 0, sizeof(st->m)); 4425 st->m.type = DNS_RPZ_TYPE_BAD; 4426 st->m.policy = DNS_RPZ_POLICY_MISS; 4427 memset(&st->r, 0, sizeof(st->r)); 4428 memset(&st->q, 0, sizeof(st->q)); 4429 dns_fixedname_init(&st->_qnamef); 4430 dns_fixedname_init(&st->_r_namef); 4431 dns_fixedname_init(&st->_fnamef); 4432 st->qname = dns_fixedname_name(&st->_qnamef); 4433 st->r_name = dns_fixedname_name(&st->_r_namef); 4434 st->fname = dns_fixedname_name(&st->_fnamef); 4435 client->query.rpz_st = st; 4436 } 4437 4438 /* 4439 * There is nothing to rewrite if the main query failed. 4440 */ 4441 switch (qresult) { 4442 case ISC_R_SUCCESS: 4443 case DNS_R_GLUE: 4444 case DNS_R_ZONECUT: 4445 ck_ip = ISC_TRUE; 4446 break; 4447 case DNS_R_EMPTYNAME: 4448 case DNS_R_NXRRSET: 4449 case DNS_R_NXDOMAIN: 4450 case DNS_R_EMPTYWILD: 4451 case DNS_R_NCACHENXDOMAIN: 4452 case DNS_R_NCACHENXRRSET: 4453 case DNS_R_CNAME: 4454 case DNS_R_DNAME: 4455 ck_ip = ISC_FALSE; 4456 break; 4457 case DNS_R_DELEGATION: 4458 case ISC_R_NOTFOUND: 4459 return (ISC_R_SUCCESS); 4460 case ISC_R_FAILURE: 4461 case ISC_R_TIMEDOUT: 4462 case DNS_R_BROKENCHAIN: 4463 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, DNS_RPZ_TYPE_QNAME, 4464 client->query.qname, 4465 "stop on qresult in rpz_rewrite()", 4466 qresult); 4467 return (ISC_R_SUCCESS); 4468 default: 4469 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, DNS_RPZ_TYPE_QNAME, 4470 client->query.qname, 4471 "stop on unrecognized qresult in rpz_rewrite()", 4472 qresult); 4473 return (ISC_R_SUCCESS); 4474 } 4475 4476 rdataset = NULL; 4477 if ((st->state & DNS_RPZ_DONE_QNAME) == 0) { 4478 /* 4479 * Check rules for the query name if this it the first time 4480 * for the current qname, i.e. we've not been recursing. 4481 * There is a first time for each name in a CNAME chain. 4482 */ 4483 result = rpz_rewrite_name(client, qtype, client->query.qname, 4484 DNS_RPZ_TYPE_QNAME, &rdataset); 4485 if (result != ISC_R_SUCCESS) 4486 goto cleanup; 4487 4488 st->r.label = dns_name_countlabels(client->query.qname); 4489 4490 st->state &= ~(DNS_RPZ_DONE_QNAME_IP | DNS_RPZ_DONE_IPv4); 4491 st->state |= DNS_RPZ_DONE_QNAME; 4492 } 4493 4494 /* 4495 * Check known IP addresses for the query name. 4496 * Any recursion required for the query has already happened. 4497 * Do not check addresses that will not be in the ANSWER section. 4498 */ 4499 if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 && 4500 (st->state & DNS_RPZ_HAVE_IP) != 0 && ck_ip) { 4501 result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_IP, 4502 client->query.qname, qtype, 4503 &rdataset, resuming); 4504 if (result != ISC_R_SUCCESS) 4505 goto cleanup; 4506 st->state &= ~DNS_RPZ_DONE_IPv4; 4507 st->state |= DNS_RPZ_DONE_QNAME_IP; 4508 } 4509 4510 /* 4511 * Stop looking for rules if there are none of the other kinds. 4512 */ 4513 if ((st->state & (DNS_RPZ_HAVE_NSIPv4 | DNS_RPZ_HAVE_NSIPv6 | 4514 DNS_RPZ_HAVE_NSDNAME)) == 0) { 4515 result = ISC_R_SUCCESS; 4516 goto cleanup; 4517 } 4518 4519 dns_fixedname_init(&nsnamef); 4520 dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef)); 4521 while (st->r.label > 1) { 4522 /* 4523 * Get NS rrset for each domain in the current qname. 4524 */ 4525 if (st->r.label == dns_name_countlabels(client->query.qname)) { 4526 nsname = client->query.qname; 4527 } else { 4528 nsname = dns_fixedname_name(&nsnamef); 4529 dns_name_split(client->query.qname, st->r.label, 4530 NULL, nsname); 4531 } 4532 if (st->r.ns_rdataset == NULL || 4533 !dns_rdataset_isassociated(st->r.ns_rdataset)) { 4534 dns_db_t *db = NULL; 4535 result = rpz_rrset_find(client, DNS_RPZ_TYPE_NSDNAME, 4536 nsname, dns_rdatatype_ns, 4537 &db, NULL, &st->r.ns_rdataset, 4538 resuming); 4539 if (db != NULL) 4540 dns_db_detach(&db); 4541 if (st->m.policy == DNS_RPZ_POLICY_ERROR) 4542 goto cleanup; 4543 switch (result) { 4544 case ISC_R_SUCCESS: 4545 result = dns_rdataset_first(st->r.ns_rdataset); 4546 if (result != ISC_R_SUCCESS) 4547 goto cleanup; 4548 st->state &= ~(DNS_RPZ_DONE_NSDNAME | 4549 DNS_RPZ_DONE_IPv4); 4550 break; 4551 case DNS_R_DELEGATION: 4552 goto cleanup; 4553 case DNS_R_EMPTYNAME: 4554 case DNS_R_NXRRSET: 4555 case DNS_R_EMPTYWILD: 4556 case DNS_R_NXDOMAIN: 4557 case DNS_R_NCACHENXDOMAIN: 4558 case DNS_R_NCACHENXRRSET: 4559 case ISC_R_NOTFOUND: 4560 case DNS_R_CNAME: 4561 case DNS_R_DNAME: 4562 rpz_rewrite_ns_skip(client, nsname, result, 4563 0, NULL); 4564 continue; 4565 case ISC_R_TIMEDOUT: 4566 case DNS_R_BROKENCHAIN: 4567 case ISC_R_FAILURE: 4568 rpz_rewrite_ns_skip(client, nsname, result, 4569 DNS_RPZ_DEBUG_LEVEL3, 4570 "NS db_find() "); 4571 continue; 4572 default: 4573 rpz_rewrite_ns_skip(client, nsname, result, 4574 DNS_RPZ_INFO_LEVEL, 4575 "unrecognized NS db_find() "); 4576 continue; 4577 } 4578 } 4579 /* 4580 * Check all NS names. 4581 */ 4582 do { 4583 dns_rdata_ns_t ns; 4584 dns_rdata_t nsrdata = DNS_RDATA_INIT; 4585 4586 dns_rdataset_current(st->r.ns_rdataset, &nsrdata); 4587 result = dns_rdata_tostruct(&nsrdata, &ns, NULL); 4588 dns_rdata_reset(&nsrdata); 4589 if (result != ISC_R_SUCCESS) { 4590 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, 4591 DNS_RPZ_TYPE_NSIP, nsname, 4592 "rdata_tostruct() ", result); 4593 st->m.policy = DNS_RPZ_POLICY_ERROR; 4594 goto cleanup; 4595 } 4596 /* 4597 * Do nothing about "NS ." 4598 */ 4599 if (dns_name_equal(&ns.name, dns_rootname)) { 4600 dns_rdata_freestruct(&ns); 4601 result = dns_rdataset_next(st->r.ns_rdataset); 4602 continue; 4603 } 4604 /* 4605 * Check this NS name if we did not handle it 4606 * during a previous recursion. 4607 */ 4608 if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0 && 4609 (st->state & DNS_RPZ_HAVE_NSDNAME) != 0) { 4610 result = rpz_rewrite_name(client, qtype, 4611 &ns.name, 4612 DNS_RPZ_TYPE_NSDNAME, 4613 &rdataset); 4614 if (result != ISC_R_SUCCESS) { 4615 dns_rdata_freestruct(&ns); 4616 goto cleanup; 4617 } 4618 st->state |= DNS_RPZ_DONE_NSDNAME; 4619 } 4620 /* 4621 * Check all IP addresses for this NS name. 4622 */ 4623 result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_NSIP, 4624 &ns.name, dns_rdatatype_any, 4625 &rdataset, resuming); 4626 dns_rdata_freestruct(&ns); 4627 if (result != ISC_R_SUCCESS) 4628 goto cleanup; 4629 st->state &= ~(DNS_RPZ_DONE_NSDNAME | 4630 DNS_RPZ_DONE_IPv4); 4631 result = dns_rdataset_next(st->r.ns_rdataset); 4632 } while (result == ISC_R_SUCCESS); 4633 dns_rdataset_disassociate(st->r.ns_rdataset); 4634 st->r.label--; 4635 } 4636 4637 /* 4638 * Use the best, if any, hit. 4639 */ 4640 result = ISC_R_SUCCESS; 4641 4642cleanup: 4643 if (st->m.policy != DNS_RPZ_POLICY_MISS && 4644 st->m.policy != DNS_RPZ_POLICY_ERROR && 4645 st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN) 4646 st->m.policy = st->m.rpz->policy; 4647 if (st->m.policy == DNS_RPZ_POLICY_MISS || 4648 st->m.policy == DNS_RPZ_POLICY_PASSTHRU || 4649 st->m.policy == DNS_RPZ_POLICY_ERROR) { 4650 if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU) 4651 rpz_log_rewrite(client, "", st->m.policy, st->m.type, 4652 st->qname); 4653 rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset); 4654 } 4655 if (st->m.policy == DNS_RPZ_POLICY_ERROR) { 4656 st->m.type = DNS_RPZ_TYPE_BAD; 4657 result = DNS_R_SERVFAIL; 4658 } 4659 query_putrdataset(client, &rdataset); 4660 if ((st->state & DNS_RPZ_RECURSING) == 0) 4661 rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset); 4662 4663 return (result); 4664} 4665 4666/* 4667 * Add a CNAME to the query response, including translating foo.evil.com and 4668 * *.evil.com CNAME *.example.com 4669 * to 4670 * foo.evil.com CNAME foo.evil.com.example.com 4671 */ 4672static isc_result_t 4673rpz_add_cname(ns_client_t *client, dns_rpz_st_t *st, 4674 dns_name_t *cname, dns_name_t *fname, isc_buffer_t *dbuf) 4675{ 4676 dns_fixedname_t prefix, suffix; 4677 unsigned int labels; 4678 isc_result_t result; 4679 4680 labels = dns_name_countlabels(cname); 4681 if (labels > 2 && dns_name_iswildcard(cname)) { 4682 dns_fixedname_init(&prefix); 4683 dns_name_split(client->query.qname, 1, 4684 dns_fixedname_name(&prefix), NULL); 4685 dns_fixedname_init(&suffix); 4686 dns_name_split(cname, labels-1, 4687 NULL, dns_fixedname_name(&suffix)); 4688 result = dns_name_concatenate(dns_fixedname_name(&prefix), 4689 dns_fixedname_name(&suffix), 4690 fname, NULL); 4691 if (result == DNS_R_NAMETOOLONG) 4692 client->message->rcode = dns_rcode_yxdomain; 4693 } else { 4694 result = dns_name_copy(cname, fname, NULL); 4695 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4696 } 4697 if (result != ISC_R_SUCCESS) 4698 return (result); 4699 query_keepname(client, fname, dbuf); 4700 result = query_add_cname(client, client->query.qname, 4701 fname, dns_trust_authanswer, st->m.ttl); 4702 if (result != ISC_R_SUCCESS) 4703 return (result); 4704 rpz_log_rewrite(client, "", st->m.policy, st->m.type, st->qname); 4705 ns_client_qnamereplace(client, fname); 4706 /* 4707 * Turn off DNSSEC because the results of a 4708 * response policy zone cannot verify. 4709 */ 4710 client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC; 4711 return (ISC_R_SUCCESS); 4712} 4713 4714#define MAX_RESTARTS 16 4715 4716#define QUERY_ERROR(r) \ 4717do { \ 4718 eresult = r; \ 4719 want_restart = ISC_FALSE; \ 4720 line = __LINE__; \ 4721} while (0) 4722 4723#define RECURSE_ERROR(r) \ 4724do { \ 4725 if ((r) == DNS_R_DUPLICATE || (r) == DNS_R_DROP) \ 4726 QUERY_ERROR(r); \ 4727 else \ 4728 QUERY_ERROR(DNS_R_SERVFAIL); \ 4729} while (0) 4730 4731/* 4732 * Extract a network address from the RDATA of an A or AAAA 4733 * record. 4734 * 4735 * Returns: 4736 * ISC_R_SUCCESS 4737 * ISC_R_NOTIMPLEMENTED The rdata is not a known address type. 4738 */ 4739static isc_result_t 4740rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) { 4741 struct in_addr ina; 4742 struct in6_addr in6a; 4743 4744 switch (rdata->type) { 4745 case dns_rdatatype_a: 4746 INSIST(rdata->length == 4); 4747 memcpy(&ina.s_addr, rdata->data, 4); 4748 isc_netaddr_fromin(netaddr, &ina); 4749 return (ISC_R_SUCCESS); 4750 case dns_rdatatype_aaaa: 4751 INSIST(rdata->length == 16); 4752 memcpy(in6a.s6_addr, rdata->data, 16); 4753 isc_netaddr_fromin6(netaddr, &in6a); 4754 return (ISC_R_SUCCESS); 4755 default: 4756 return (ISC_R_NOTIMPLEMENTED); 4757 } 4758} 4759 4760/* 4761 * Find the sort order of 'rdata' in the topology-like 4762 * ACL forming the second element in a 2-element top-level 4763 * sortlist statement. 4764 */ 4765static int 4766query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) { 4767 isc_netaddr_t netaddr; 4768 4769 if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) 4770 return (INT_MAX); 4771 return (ns_sortlist_addrorder2(&netaddr, arg)); 4772} 4773 4774/* 4775 * Find the sort order of 'rdata' in the matching element 4776 * of a 1-element top-level sortlist statement. 4777 */ 4778static int 4779query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) { 4780 isc_netaddr_t netaddr; 4781 4782 if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) 4783 return (INT_MAX); 4784 return (ns_sortlist_addrorder1(&netaddr, arg)); 4785} 4786 4787/* 4788 * Find the sortlist statement that applies to 'client' and set up 4789 * the sortlist info in in client->message appropriately. 4790 */ 4791static void 4792setup_query_sortlist(ns_client_t *client) { 4793 isc_netaddr_t netaddr; 4794 dns_rdatasetorderfunc_t order = NULL; 4795 const void *order_arg = NULL; 4796 4797 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); 4798 switch (ns_sortlist_setup(client->view->sortlist, 4799 &netaddr, &order_arg)) { 4800 case NS_SORTLISTTYPE_1ELEMENT: 4801 order = query_sortlist_order_1element; 4802 break; 4803 case NS_SORTLISTTYPE_2ELEMENT: 4804 order = query_sortlist_order_2element; 4805 break; 4806 case NS_SORTLISTTYPE_NONE: 4807 order = NULL; 4808 break; 4809 default: 4810 INSIST(0); 4811 break; 4812 } 4813 dns_message_setsortorder(client->message, order, order_arg); 4814} 4815 4816static void 4817query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) { 4818 isc_buffer_t *dbuf, b; 4819 dns_name_t *fname; 4820 dns_rdataset_t *neg, *negsig; 4821 isc_result_t result = ISC_R_NOMEMORY; 4822 4823 CTRACE("query_addnoqnameproof"); 4824 4825 fname = NULL; 4826 neg = NULL; 4827 negsig = NULL; 4828 4829 dbuf = query_getnamebuf(client); 4830 if (dbuf == NULL) 4831 goto cleanup; 4832 fname = query_newname(client, dbuf, &b); 4833 neg = query_newrdataset(client); 4834 negsig = query_newrdataset(client); 4835 if (fname == NULL || neg == NULL || negsig == NULL) 4836 goto cleanup; 4837 4838 result = dns_rdataset_getnoqname(rdataset, fname, neg, negsig); 4839 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4840 4841 query_addrrset(client, &fname, &neg, &negsig, dbuf, 4842 DNS_SECTION_AUTHORITY); 4843 4844 if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) == 0) 4845 goto cleanup; 4846 4847 if (fname == NULL) { 4848 dbuf = query_getnamebuf(client); 4849 if (dbuf == NULL) 4850 goto cleanup; 4851 fname = query_newname(client, dbuf, &b); 4852 } 4853 if (neg == NULL) 4854 neg = query_newrdataset(client); 4855 else if (dns_rdataset_isassociated(neg)) 4856 dns_rdataset_disassociate(neg); 4857 if (negsig == NULL) 4858 negsig = query_newrdataset(client); 4859 else if (dns_rdataset_isassociated(negsig)) 4860 dns_rdataset_disassociate(negsig); 4861 if (fname == NULL || neg == NULL || negsig == NULL) 4862 goto cleanup; 4863 result = dns_rdataset_getclosest(rdataset, fname, neg, negsig); 4864 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4865 4866 query_addrrset(client, &fname, &neg, &negsig, dbuf, 4867 DNS_SECTION_AUTHORITY); 4868 4869 cleanup: 4870 if (neg != NULL) 4871 query_putrdataset(client, &neg); 4872 if (negsig != NULL) 4873 query_putrdataset(client, &negsig); 4874 if (fname != NULL) 4875 query_releasename(client, &fname); 4876} 4877 4878static inline void 4879answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) { 4880 dns_name_t *name; 4881 dns_message_t *msg; 4882 dns_section_t section = DNS_SECTION_ADDITIONAL; 4883 dns_rdataset_t *rdataset = NULL; 4884 4885 msg = client->message; 4886 for (name = ISC_LIST_HEAD(msg->sections[section]); 4887 name != NULL; 4888 name = ISC_LIST_NEXT(name, link)) 4889 if (dns_name_equal(name, client->query.qname)) { 4890 for (rdataset = ISC_LIST_HEAD(name->list); 4891 rdataset != NULL; 4892 rdataset = ISC_LIST_NEXT(rdataset, link)) 4893 if (rdataset->type == qtype) 4894 break; 4895 break; 4896 } 4897 if (rdataset != NULL) { 4898 ISC_LIST_UNLINK(msg->sections[section], name, link); 4899 ISC_LIST_PREPEND(msg->sections[section], name, link); 4900 ISC_LIST_UNLINK(name->list, rdataset, link); 4901 ISC_LIST_PREPEND(name->list, rdataset, link); 4902 rdataset->attributes |= DNS_RDATASETATTR_REQUIREDGLUE; 4903 } 4904} 4905 4906#define NS_NAME_INIT(A,B) \ 4907 { \ 4908 DNS_NAME_MAGIC, \ 4909 A, sizeof(A), sizeof(B), \ 4910 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \ 4911 B, NULL, { (void *)-1, (void *)-1}, \ 4912 {NULL, NULL} \ 4913 } 4914 4915static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 }; 4916static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 }; 4917static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 }; 4918 4919static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA"; 4920 4921static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA"; 4922static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA"; 4923static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA"; 4924static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA"; 4925static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA"; 4926static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA"; 4927static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA"; 4928static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA"; 4929static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA"; 4930static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA"; 4931static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA"; 4932static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA"; 4933static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA"; 4934static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA"; 4935static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA"; 4936static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA"; 4937 4938static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA"; 4939 4940static dns_name_t rfc1918names[] = { 4941 NS_NAME_INIT(inaddr10, inaddr10_offsets), 4942 NS_NAME_INIT(inaddr16172, inaddr172_offsets), 4943 NS_NAME_INIT(inaddr17172, inaddr172_offsets), 4944 NS_NAME_INIT(inaddr18172, inaddr172_offsets), 4945 NS_NAME_INIT(inaddr19172, inaddr172_offsets), 4946 NS_NAME_INIT(inaddr20172, inaddr172_offsets), 4947 NS_NAME_INIT(inaddr21172, inaddr172_offsets), 4948 NS_NAME_INIT(inaddr22172, inaddr172_offsets), 4949 NS_NAME_INIT(inaddr23172, inaddr172_offsets), 4950 NS_NAME_INIT(inaddr24172, inaddr172_offsets), 4951 NS_NAME_INIT(inaddr25172, inaddr172_offsets), 4952 NS_NAME_INIT(inaddr26172, inaddr172_offsets), 4953 NS_NAME_INIT(inaddr27172, inaddr172_offsets), 4954 NS_NAME_INIT(inaddr28172, inaddr172_offsets), 4955 NS_NAME_INIT(inaddr29172, inaddr172_offsets), 4956 NS_NAME_INIT(inaddr30172, inaddr172_offsets), 4957 NS_NAME_INIT(inaddr31172, inaddr172_offsets), 4958 NS_NAME_INIT(inaddr168192, inaddr192_offsets) 4959}; 4960 4961 4962static unsigned char prisoner_data[] = "\010prisoner\004iana\003org"; 4963static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org"; 4964 4965static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 }; 4966static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 }; 4967 4968static dns_name_t prisoner = NS_NAME_INIT(prisoner_data, prisoner_offsets); 4969static dns_name_t hostmaster = NS_NAME_INIT(hostmaster_data, hostmaster_offsets); 4970 4971static void 4972warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) { 4973 unsigned int i; 4974 dns_rdata_t rdata = DNS_RDATA_INIT; 4975 dns_rdata_soa_t soa; 4976 dns_rdataset_t found; 4977 isc_result_t result; 4978 4979 for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) { 4980 if (dns_name_issubdomain(fname, &rfc1918names[i])) { 4981 dns_rdataset_init(&found); 4982 result = dns_ncache_getrdataset(rdataset, 4983 &rfc1918names[i], 4984 dns_rdatatype_soa, 4985 &found); 4986 if (result != ISC_R_SUCCESS) 4987 return; 4988 4989 result = dns_rdataset_first(&found); 4990 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4991 dns_rdataset_current(&found, &rdata); 4992 result = dns_rdata_tostruct(&rdata, &soa, NULL); 4993 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4994 if (dns_name_equal(&soa.origin, &prisoner) && 4995 dns_name_equal(&soa.contact, &hostmaster)) { 4996 char buf[DNS_NAME_FORMATSIZE]; 4997 dns_name_format(fname, buf, sizeof(buf)); 4998 ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 4999 NS_LOGMODULE_QUERY, 5000 ISC_LOG_WARNING, 5001 "RFC 1918 response from " 5002 "Internet for %s", buf); 5003 } 5004 dns_rdataset_disassociate(&found); 5005 return; 5006 } 5007 } 5008} 5009 5010static void 5011query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, 5012 dns_dbversion_t *version, ns_client_t *client, 5013 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 5014 dns_name_t *fname, isc_boolean_t exact, 5015 dns_name_t *found) 5016{ 5017 unsigned char salt[256]; 5018 size_t salt_length; 5019 isc_uint16_t iterations; 5020 isc_result_t result; 5021 unsigned int dboptions; 5022 dns_fixedname_t fixed; 5023 dns_hash_t hash; 5024 dns_name_t name; 5025 int order; 5026 unsigned int count; 5027 dns_rdata_nsec3_t nsec3; 5028 dns_rdata_t rdata = DNS_RDATA_INIT; 5029 isc_boolean_t optout; 5030 5031 salt_length = sizeof(salt); 5032 result = dns_db_getnsec3parameters(db, version, &hash, NULL, 5033 &iterations, salt, &salt_length); 5034 if (result != ISC_R_SUCCESS) 5035 return; 5036 5037 dns_name_init(&name, NULL); 5038 dns_name_clone(qname, &name); 5039 5040 /* 5041 * Map unknown algorithm to known value. 5042 */ 5043 if (hash == DNS_NSEC3_UNKNOWNALG) 5044 hash = 1; 5045 5046 again: 5047 dns_fixedname_init(&fixed); 5048 result = dns_nsec3_hashname(&fixed, NULL, NULL, &name, 5049 dns_db_origin(db), hash, 5050 iterations, salt, salt_length); 5051 if (result != ISC_R_SUCCESS) 5052 return; 5053 5054 dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3; 5055 result = dns_db_find(db, dns_fixedname_name(&fixed), version, 5056 dns_rdatatype_nsec3, dboptions, client->now, 5057 NULL, fname, rdataset, sigrdataset); 5058 5059 if (result == DNS_R_NXDOMAIN) { 5060 if (!dns_rdataset_isassociated(rdataset)) { 5061 return; 5062 } 5063 result = dns_rdataset_first(rdataset); 5064 INSIST(result == ISC_R_SUCCESS); 5065 dns_rdataset_current(rdataset, &rdata); 5066 dns_rdata_tostruct(&rdata, &nsec3, NULL); 5067 dns_rdata_reset(&rdata); 5068 optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); 5069 if (found != NULL && optout && 5070 dns_name_fullcompare(&name, dns_db_origin(db), &order, 5071 &count) == dns_namereln_subdomain) { 5072 dns_rdataset_disassociate(rdataset); 5073 if (dns_rdataset_isassociated(sigrdataset)) 5074 dns_rdataset_disassociate(sigrdataset); 5075 count = dns_name_countlabels(&name) - 1; 5076 dns_name_getlabelsequence(&name, 1, count, &name); 5077 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, 5078 NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3), 5079 "looking for closest provable encloser"); 5080 goto again; 5081 } 5082 if (exact) 5083 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, 5084 NS_LOGMODULE_QUERY, ISC_LOG_WARNING, 5085 "expected a exact match NSEC3, got " 5086 "a covering record"); 5087 5088 } else if (result != ISC_R_SUCCESS) { 5089 return; 5090 } else if (!exact) 5091 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, 5092 NS_LOGMODULE_QUERY, ISC_LOG_WARNING, 5093 "expected covering NSEC3, got an exact match"); 5094 if (found != NULL) 5095 dns_name_copy(&name, found, NULL); 5096 return; 5097} 5098 5099#ifdef ALLOW_FILTER_AAAA_ON_V4 5100static isc_boolean_t 5101is_v4_client(ns_client_t *client) { 5102 if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) 5103 return (ISC_TRUE); 5104 if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 && 5105 IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr)) 5106 return (ISC_TRUE); 5107 return (ISC_FALSE); 5108} 5109#endif 5110 5111static isc_uint32_t 5112dns64_ttl(dns_db_t *db, dns_dbversion_t *version) { 5113 dns_dbnode_t *node = NULL; 5114 dns_rdata_soa_t soa; 5115 dns_rdata_t rdata = DNS_RDATA_INIT; 5116 dns_rdataset_t rdataset; 5117 isc_result_t result; 5118 isc_uint32_t ttl = ISC_UINT32_MAX; 5119 5120 result = dns_db_getoriginnode(db, &node); 5121 if (result != ISC_R_SUCCESS) 5122 goto cleanup; 5123 dns_rdataset_init(&rdataset); 5124 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, 5125 0, 0, &rdataset, NULL); 5126 if (result != ISC_R_SUCCESS) 5127 goto cleanup; 5128 result = dns_rdataset_first(&rdataset); 5129 if (result != ISC_R_SUCCESS) 5130 goto cleanup; 5131 5132 dns_rdataset_current(&rdataset, &rdata); 5133 result = dns_rdata_tostruct(&rdata, &soa, NULL); 5134 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5135 ttl = ISC_MIN(rdataset.ttl, soa.minimum); 5136 5137cleanup: 5138 if (dns_rdataset_isassociated(&rdataset)) 5139 dns_rdataset_disassociate(&rdataset); 5140 if (node != NULL) 5141 dns_db_detachnode(db, &node); 5142 return (ttl); 5143} 5144 5145static isc_boolean_t 5146dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset, 5147 dns_rdataset_t *sigrdataset) 5148{ 5149 isc_netaddr_t netaddr; 5150 dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64); 5151 unsigned int flags = 0; 5152 unsigned int i, count; 5153 isc_boolean_t *aaaaok; 5154 5155 INSIST(client->query.dns64_aaaaok == NULL); 5156 INSIST(client->query.dns64_aaaaoklen == 0); 5157 INSIST(client->query.dns64_aaaa == NULL); 5158 INSIST(client->query.dns64_sigaaaa == NULL); 5159 5160 if (dns64 == NULL) 5161 return (ISC_TRUE); 5162 5163 if (RECURSIONOK(client)) 5164 flags |= DNS_DNS64_RECURSIVE; 5165 5166 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) 5167 flags |= DNS_DNS64_DNSSEC; 5168 5169 count = dns_rdataset_count(rdataset); 5170 aaaaok = isc_mem_get(client->mctx, sizeof(isc_boolean_t) * count); 5171 5172 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); 5173 if (dns_dns64_aaaaok(dns64, &netaddr, client->signer, 5174 &ns_g_server->aclenv, flags, rdataset, 5175 aaaaok, count)) { 5176 for (i = 0; i < count; i++) { 5177 if (aaaaok != NULL && !aaaaok[i]) { 5178 client->query.dns64_aaaaok = aaaaok; 5179 client->query.dns64_aaaaoklen = count; 5180 break; 5181 } 5182 } 5183 if (i == count && aaaaok != NULL) 5184 isc_mem_put(client->mctx, aaaaok, 5185 sizeof(isc_boolean_t) * count); 5186 return (ISC_TRUE); 5187 } 5188 if (aaaaok != NULL) 5189 isc_mem_put(client->mctx, aaaaok, 5190 sizeof(isc_boolean_t) * count); 5191 return (ISC_FALSE); 5192} 5193 5194/* 5195 * Do the bulk of query processing for the current query of 'client'. 5196 * If 'event' is non-NULL, we are returning from recursion and 'qtype' 5197 * is ignored. Otherwise, 'qtype' is the query type. 5198 */ 5199static isc_result_t 5200query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) 5201{ 5202 dns_db_t *db, *zdb; 5203 dns_dbnode_t *node; 5204 dns_rdatatype_t type; 5205 dns_name_t *fname, *zfname, *tname, *prefix; 5206 dns_rdataset_t *rdataset, *trdataset; 5207 dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset; 5208 dns_rdataset_t **sigrdatasetp; 5209 dns_rdata_t rdata = DNS_RDATA_INIT; 5210 dns_rdatasetiter_t *rdsiter; 5211 isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof; 5212 isc_boolean_t is_staticstub_zone; 5213 unsigned int n, nlabels; 5214 dns_namereln_t namereln; 5215 int order; 5216 isc_buffer_t *dbuf; 5217 isc_buffer_t b; 5218 isc_result_t result, eresult; 5219 dns_fixedname_t fixed; 5220 dns_fixedname_t wildcardname; 5221 dns_dbversion_t *version, *zversion; 5222 dns_zone_t *zone; 5223 dns_rdata_cname_t cname; 5224 dns_rdata_dname_t dname; 5225 unsigned int options; 5226 isc_boolean_t empty_wild; 5227 dns_rdataset_t *noqname; 5228 dns_rpz_st_t *rpz_st; 5229 isc_boolean_t resuming; 5230 int line = -1; 5231 isc_boolean_t dns64_exclude, dns64; 5232 5233 CTRACE("query_find"); 5234 5235 /* 5236 * One-time initialization. 5237 * 5238 * It's especially important to initialize anything that the cleanup 5239 * code might cleanup. 5240 */ 5241 5242 eresult = ISC_R_SUCCESS; 5243 fname = NULL; 5244 zfname = NULL; 5245 rdataset = NULL; 5246 zrdataset = NULL; 5247 sigrdataset = NULL; 5248 zsigrdataset = NULL; 5249 zversion = NULL; 5250 node = NULL; 5251 db = NULL; 5252 zdb = NULL; 5253 version = NULL; 5254 zone = NULL; 5255 need_wildcardproof = ISC_FALSE; 5256 empty_wild = ISC_FALSE; 5257 dns64_exclude = dns64 = ISC_FALSE; 5258 options = 0; 5259 resuming = ISC_FALSE; 5260 is_zone = ISC_FALSE; 5261 is_staticstub_zone = ISC_FALSE; 5262 5263 if (event != NULL) { 5264 /* 5265 * We're returning from recursion. Restore the query context 5266 * and resume. 5267 */ 5268 want_restart = ISC_FALSE; 5269 5270 rpz_st = client->query.rpz_st; 5271 if (rpz_st != NULL && 5272 (rpz_st->state & DNS_RPZ_RECURSING) != 0) { 5273 is_zone = rpz_st->q.is_zone; 5274 authoritative = rpz_st->q.authoritative; 5275 zone = rpz_st->q.zone; 5276 rpz_st->q.zone = NULL; 5277 node = rpz_st->q.node; 5278 rpz_st->q.node = NULL; 5279 db = rpz_st->q.db; 5280 rpz_st->q.db = NULL; 5281 rdataset = rpz_st->q.rdataset; 5282 rpz_st->q.rdataset = NULL; 5283 sigrdataset = rpz_st->q.sigrdataset; 5284 rpz_st->q.sigrdataset = NULL; 5285 qtype = rpz_st->q.qtype; 5286 5287 rpz_st->r.db = event->db; 5288 if (event->node != NULL) 5289 dns_db_detachnode(event->db, &event->node); 5290 rpz_st->r.r_type = event->qtype; 5291 rpz_st->r.r_rdataset = event->rdataset; 5292 query_putrdataset(client, &event->sigrdataset); 5293 } else { 5294 authoritative = ISC_FALSE; 5295 5296 qtype = event->qtype; 5297 db = event->db; 5298 node = event->node; 5299 rdataset = event->rdataset; 5300 sigrdataset = event->sigrdataset; 5301 } 5302 5303 if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig) 5304 type = dns_rdatatype_any; 5305 else 5306 type = qtype; 5307 5308 if (DNS64(client)) { 5309 client->query.attributes &= ~NS_QUERYATTR_DNS64; 5310 dns64 = ISC_TRUE; 5311 } 5312 if (DNS64EXCLUDE(client)) { 5313 client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE; 5314 dns64_exclude = ISC_TRUE; 5315 } 5316 5317 /* 5318 * We'll need some resources... 5319 */ 5320 dbuf = query_getnamebuf(client); 5321 if (dbuf == NULL) { 5322 QUERY_ERROR(DNS_R_SERVFAIL); 5323 goto cleanup; 5324 } 5325 fname = query_newname(client, dbuf, &b); 5326 if (fname == NULL) { 5327 QUERY_ERROR(DNS_R_SERVFAIL); 5328 goto cleanup; 5329 } 5330 if (rpz_st != NULL && 5331 (rpz_st->state & DNS_RPZ_RECURSING) != 0) { 5332 tname = rpz_st->fname; 5333 } else { 5334 tname = dns_fixedname_name(&event->foundname); 5335 } 5336 result = dns_name_copy(tname, fname, NULL); 5337 if (result != ISC_R_SUCCESS) { 5338 QUERY_ERROR(DNS_R_SERVFAIL); 5339 goto cleanup; 5340 } 5341 if (rpz_st != NULL && 5342 (rpz_st->state & DNS_RPZ_RECURSING) != 0) { 5343 rpz_st->r.r_result = event->result; 5344 result = rpz_st->q.result; 5345 isc_event_free(ISC_EVENT_PTR(&event)); 5346 } else { 5347 result = event->result; 5348 } 5349 resuming = ISC_TRUE; 5350 goto resume; 5351 } 5352 5353 /* 5354 * Not returning from recursion. 5355 */ 5356 5357 /* 5358 * If it's a SIG query, we'll iterate the node. 5359 */ 5360 if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig) 5361 type = dns_rdatatype_any; 5362 else 5363 type = qtype; 5364 5365 restart: 5366 CTRACE("query_find: restart"); 5367 want_restart = ISC_FALSE; 5368 authoritative = ISC_FALSE; 5369 version = NULL; 5370 need_wildcardproof = ISC_FALSE; 5371 5372 if (client->view->checknames && 5373 !dns_rdata_checkowner(client->query.qname, 5374 client->message->rdclass, 5375 qtype, ISC_FALSE)) { 5376 char namebuf[DNS_NAME_FORMATSIZE]; 5377 char typename[DNS_RDATATYPE_FORMATSIZE]; 5378 char classname[DNS_RDATACLASS_FORMATSIZE]; 5379 5380 dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); 5381 dns_rdatatype_format(qtype, typename, sizeof(typename)); 5382 dns_rdataclass_format(client->message->rdclass, classname, 5383 sizeof(classname)); 5384 ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 5385 NS_LOGMODULE_QUERY, ISC_LOG_ERROR, 5386 "check-names failure %s/%s/%s", namebuf, 5387 typename, classname); 5388 QUERY_ERROR(DNS_R_REFUSED); 5389 goto cleanup; 5390 } 5391 5392 /* 5393 * First we must find the right database. 5394 */ 5395 options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */ 5396 if (dns_rdatatype_atparent(qtype) && 5397 !dns_name_equal(client->query.qname, dns_rootname)) 5398 options |= DNS_GETDB_NOEXACT; 5399 result = query_getdb(client, client->query.qname, qtype, options, 5400 &zone, &db, &version, &is_zone); 5401 if ((result != ISC_R_SUCCESS || !is_zone) && !RECURSIONOK(client) && 5402 (options & DNS_GETDB_NOEXACT) != 0 && qtype == dns_rdatatype_ds) { 5403 /* 5404 * Look to see if we are authoritative for the 5405 * child zone if the query type is DS. 5406 */ 5407 dns_db_t *tdb = NULL; 5408 dns_zone_t *tzone = NULL; 5409 dns_dbversion_t *tversion = NULL; 5410 isc_result_t tresult; 5411 5412 tresult = query_getzonedb(client, client->query.qname, qtype, 5413 DNS_GETDB_PARTIAL, &tzone, &tdb, 5414 &tversion); 5415 if (tresult == ISC_R_SUCCESS) { 5416 options &= ~DNS_GETDB_NOEXACT; 5417 query_putrdataset(client, &rdataset); 5418 if (db != NULL) 5419 dns_db_detach(&db); 5420 if (zone != NULL) 5421 dns_zone_detach(&zone); 5422 version = tversion; 5423 db = tdb; 5424 zone = tzone; 5425 is_zone = ISC_TRUE; 5426 result = ISC_R_SUCCESS; 5427 } else { 5428 if (tdb != NULL) 5429 dns_db_detach(&tdb); 5430 if (tzone != NULL) 5431 dns_zone_detach(&tzone); 5432 } 5433 } 5434 if (result != ISC_R_SUCCESS) { 5435 if (result == DNS_R_REFUSED) { 5436 if (WANTRECURSION(client)) { 5437 inc_stats(client, 5438 dns_nsstatscounter_recurserej); 5439 } else 5440 inc_stats(client, dns_nsstatscounter_authrej); 5441 if (!PARTIALANSWER(client)) 5442 QUERY_ERROR(DNS_R_REFUSED); 5443 } else 5444 QUERY_ERROR(DNS_R_SERVFAIL); 5445 goto cleanup; 5446 } 5447 5448 is_staticstub_zone = ISC_FALSE; 5449 if (is_zone) { 5450 authoritative = ISC_TRUE; 5451 if (zone != NULL && 5452 dns_zone_gettype(zone) == dns_zone_staticstub) 5453 is_staticstub_zone = ISC_TRUE; 5454 } 5455 5456 if (event == NULL && client->query.restarts == 0) { 5457 if (is_zone) { 5458 if (zone != NULL) { 5459 /* 5460 * if is_zone = true, zone = NULL then this is 5461 * a DLZ zone. Don't attempt to attach zone. 5462 */ 5463 dns_zone_attach(zone, &client->query.authzone); 5464 } 5465 dns_db_attach(db, &client->query.authdb); 5466 } 5467 client->query.authdbset = ISC_TRUE; 5468 } 5469 5470 db_find: 5471 CTRACE("query_find: db_find"); 5472 /* 5473 * We'll need some resources... 5474 */ 5475 dbuf = query_getnamebuf(client); 5476 if (dbuf == NULL) { 5477 QUERY_ERROR(DNS_R_SERVFAIL); 5478 goto cleanup; 5479 } 5480 fname = query_newname(client, dbuf, &b); 5481 rdataset = query_newrdataset(client); 5482 if (fname == NULL || rdataset == NULL) { 5483 QUERY_ERROR(DNS_R_SERVFAIL); 5484 goto cleanup; 5485 } 5486 if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) { 5487 sigrdataset = query_newrdataset(client); 5488 if (sigrdataset == NULL) { 5489 QUERY_ERROR(DNS_R_SERVFAIL); 5490 goto cleanup; 5491 } 5492 } 5493 5494 /* 5495 * Now look for an answer in the database. 5496 */ 5497 result = dns_db_find(db, client->query.qname, version, type, 5498 client->query.dboptions, client->now, 5499 &node, fname, rdataset, sigrdataset); 5500 5501 resume: 5502 CTRACE("query_find: resume"); 5503 5504 if (!ISC_LIST_EMPTY(client->view->rpz_zones) && 5505 RECURSIONOK(client) && !RECURSING(client) && 5506 (!WANTDNSSEC(client) || sigrdataset == NULL || 5507 !dns_rdataset_isassociated(sigrdataset)) && 5508 (client->query.rpz_st == NULL || 5509 (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) && 5510 !dns_name_equal(client->query.qname, dns_rootname)) { 5511 isc_result_t rresult; 5512 5513 rresult = rpz_rewrite(client, qtype, result, resuming); 5514 rpz_st = client->query.rpz_st; 5515 switch (rresult) { 5516 case ISC_R_SUCCESS: 5517 break; 5518 case DNS_R_DELEGATION: 5519 /* 5520 * recursing for NS names or addresses, 5521 * so save the main query state 5522 */ 5523 rpz_st->q.qtype = qtype; 5524 rpz_st->q.is_zone = is_zone; 5525 rpz_st->q.authoritative = authoritative; 5526 rpz_st->q.zone = zone; 5527 zone = NULL; 5528 rpz_st->q.db = db; 5529 db = NULL; 5530 rpz_st->q.node = node; 5531 node = NULL; 5532 rpz_st->q.rdataset = rdataset; 5533 rdataset = NULL; 5534 rpz_st->q.sigrdataset = sigrdataset; 5535 sigrdataset = NULL; 5536 dns_name_copy(fname, rpz_st->fname, NULL); 5537 rpz_st->q.result = result; 5538 client->query.attributes |= NS_QUERYATTR_RECURSING; 5539 goto cleanup; 5540 default: 5541 RECURSE_ERROR(rresult); 5542 goto cleanup; 5543 } 5544 if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS) 5545 rpz_st->state |= DNS_RPZ_REWRITTEN; 5546 if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS && 5547 rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU && 5548 rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { 5549 if (rpz_st->m.type == DNS_RPZ_TYPE_QNAME) { 5550 result = dns_name_copy(client->query.qname, 5551 fname, NULL); 5552 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5553 } 5554 rpz_clean(&zone, &db, &node, NULL); 5555 if (rpz_st->m.rdataset != NULL) { 5556 query_putrdataset(client, &rdataset); 5557 rdataset = rpz_st->m.rdataset; 5558 rpz_st->m.rdataset = NULL; 5559 } else if (rdataset != NULL && 5560 dns_rdataset_isassociated(rdataset)) { 5561 dns_rdataset_disassociate(rdataset); 5562 } 5563 node = rpz_st->m.node; 5564 rpz_st->m.node = NULL; 5565 db = rpz_st->m.db; 5566 rpz_st->m.db = NULL; 5567 version = rpz_st->m.version; 5568 rpz_st->m.version = NULL; 5569 zone = rpz_st->m.zone; 5570 rpz_st->m.zone = NULL; 5571 5572 switch (rpz_st->m.policy) { 5573 case DNS_RPZ_POLICY_NXDOMAIN: 5574 result = DNS_R_NXDOMAIN; 5575 break; 5576 case DNS_RPZ_POLICY_NODATA: 5577 result = DNS_R_NXRRSET; 5578 break; 5579 case DNS_RPZ_POLICY_RECORD: 5580 result = rpz_st->m.result; 5581 if (type == dns_rdatatype_any && 5582 result != DNS_R_CNAME && 5583 dns_rdataset_isassociated(rdataset)) 5584 dns_rdataset_disassociate(rdataset); 5585 break; 5586 case DNS_RPZ_POLICY_WILDCNAME: 5587 result = dns_rdataset_first(rdataset); 5588 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5589 dns_rdataset_current(rdataset, &rdata); 5590 result = dns_rdata_tostruct(&rdata, &cname, 5591 NULL); 5592 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5593 dns_rdata_reset(&rdata); 5594 result = rpz_add_cname(client, rpz_st, 5595 &cname.cname, 5596 fname, dbuf); 5597 if (result != ISC_R_SUCCESS) 5598 goto cleanup; 5599 fname = NULL; 5600 want_restart = ISC_TRUE; 5601 goto cleanup; 5602 case DNS_RPZ_POLICY_CNAME: 5603 /* 5604 * Add overridding CNAME from a named.conf 5605 * response-policy statement 5606 */ 5607 result = rpz_add_cname(client, rpz_st, 5608 &rpz_st->m.rpz->cname, 5609 fname, dbuf); 5610 if (result != ISC_R_SUCCESS) 5611 goto cleanup; 5612 fname = NULL; 5613 want_restart = ISC_TRUE; 5614 goto cleanup; 5615 default: 5616 INSIST(0); 5617 } 5618 5619 /* 5620 * Turn off DNSSEC because the results of a 5621 * response policy zone cannot verify. 5622 */ 5623 client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC; 5624 query_putrdataset(client, &sigrdataset); 5625 is_zone = ISC_TRUE; 5626 rpz_log_rewrite(client, "", rpz_st->m.policy, 5627 rpz_st->m.type, rpz_st->qname); 5628 } 5629 } 5630 5631 switch (result) { 5632 case ISC_R_SUCCESS: 5633 /* 5634 * This case is handled in the main line below. 5635 */ 5636 break; 5637 case DNS_R_GLUE: 5638 case DNS_R_ZONECUT: 5639 /* 5640 * These cases are handled in the main line below. 5641 */ 5642 INSIST(is_zone); 5643 authoritative = ISC_FALSE; 5644 break; 5645 case ISC_R_NOTFOUND: 5646 /* 5647 * The cache doesn't even have the root NS. Get them from 5648 * the hints DB. 5649 */ 5650 INSIST(!is_zone); 5651 if (db != NULL) 5652 dns_db_detach(&db); 5653 5654 if (client->view->hints == NULL) { 5655 /* We have no hints. */ 5656 result = ISC_R_FAILURE; 5657 } else { 5658 dns_db_attach(client->view->hints, &db); 5659 result = dns_db_find(db, dns_rootname, 5660 NULL, dns_rdatatype_ns, 5661 0, client->now, &node, fname, 5662 rdataset, sigrdataset); 5663 } 5664 if (result != ISC_R_SUCCESS) { 5665 /* 5666 * Nonsensical root hints may require cleanup. 5667 */ 5668 if (dns_rdataset_isassociated(rdataset)) 5669 dns_rdataset_disassociate(rdataset); 5670 if (sigrdataset != NULL && 5671 dns_rdataset_isassociated(sigrdataset)) 5672 dns_rdataset_disassociate(sigrdataset); 5673 if (node != NULL) 5674 dns_db_detachnode(db, &node); 5675 5676 /* 5677 * We don't have any root server hints, but 5678 * we may have working forwarders, so try to 5679 * recurse anyway. 5680 */ 5681 if (RECURSIONOK(client)) { 5682 result = query_recurse(client, qtype, 5683 client->query.qname, 5684 NULL, NULL, resuming); 5685 if (result == ISC_R_SUCCESS) { 5686 client->query.attributes |= 5687 NS_QUERYATTR_RECURSING; 5688 if (dns64) 5689 client->query.attributes |= 5690 NS_QUERYATTR_DNS64; 5691 if (dns64_exclude) 5692 client->query.attributes |= 5693 NS_QUERYATTR_DNS64EXCLUDE; 5694 } else 5695 RECURSE_ERROR(result); 5696 goto cleanup; 5697 } else { 5698 /* Unable to give root server referral. */ 5699 QUERY_ERROR(DNS_R_SERVFAIL); 5700 goto cleanup; 5701 } 5702 } 5703 /* 5704 * XXXRTH We should trigger root server priming here. 5705 */ 5706 /* FALLTHROUGH */ 5707 case DNS_R_DELEGATION: 5708 authoritative = ISC_FALSE; 5709 if (is_zone) { 5710 /* 5711 * Look to see if we are authoritative for the 5712 * child zone if the query type is DS. 5713 */ 5714 if (!RECURSIONOK(client) && 5715 (options & DNS_GETDB_NOEXACT) != 0 && 5716 qtype == dns_rdatatype_ds) { 5717 dns_db_t *tdb = NULL; 5718 dns_zone_t *tzone = NULL; 5719 dns_dbversion_t *tversion = NULL; 5720 result = query_getzonedb(client, 5721 client->query.qname, 5722 qtype, 5723 DNS_GETDB_PARTIAL, 5724 &tzone, &tdb, 5725 &tversion); 5726 if (result == ISC_R_SUCCESS) { 5727 options &= ~DNS_GETDB_NOEXACT; 5728 query_putrdataset(client, &rdataset); 5729 if (sigrdataset != NULL) 5730 query_putrdataset(client, 5731 &sigrdataset); 5732 if (fname != NULL) 5733 query_releasename(client, 5734 &fname); 5735 if (node != NULL) 5736 dns_db_detachnode(db, &node); 5737 if (db != NULL) 5738 dns_db_detach(&db); 5739 if (zone != NULL) 5740 dns_zone_detach(&zone); 5741 version = tversion; 5742 db = tdb; 5743 zone = tzone; 5744 authoritative = ISC_TRUE; 5745 goto db_find; 5746 } 5747 if (tdb != NULL) 5748 dns_db_detach(&tdb); 5749 if (tzone != NULL) 5750 dns_zone_detach(&tzone); 5751 } 5752 /* 5753 * We're authoritative for an ancestor of QNAME. 5754 */ 5755 if (!USECACHE(client) || !RECURSIONOK(client)) { 5756 dns_fixedname_t fixed; 5757 5758 dns_fixedname_init(&fixed); 5759 dns_name_copy(fname, 5760 dns_fixedname_name(&fixed), NULL); 5761 5762 /* 5763 * If we don't have a cache, this is the best 5764 * answer. 5765 * 5766 * If the client is making a nonrecursive 5767 * query we always give out the authoritative 5768 * delegation. This way even if we get 5769 * junk in our cache, we won't fail in our 5770 * role as the delegating authority if another 5771 * nameserver asks us about a delegated 5772 * subzone. 5773 * 5774 * We enable the retrieval of glue for this 5775 * database by setting client->query.gluedb. 5776 */ 5777 client->query.gluedb = db; 5778 client->query.isreferral = ISC_TRUE; 5779 /* 5780 * We must ensure NOADDITIONAL is off, 5781 * because the generation of 5782 * additional data is required in 5783 * delegations. 5784 */ 5785 client->query.attributes &= 5786 ~NS_QUERYATTR_NOADDITIONAL; 5787 if (sigrdataset != NULL) 5788 sigrdatasetp = &sigrdataset; 5789 else 5790 sigrdatasetp = NULL; 5791 query_addrrset(client, &fname, 5792 &rdataset, sigrdatasetp, 5793 dbuf, DNS_SECTION_AUTHORITY); 5794 client->query.gluedb = NULL; 5795 if (WANTDNSSEC(client)) 5796 query_addds(client, db, node, version, 5797 dns_fixedname_name(&fixed)); 5798 } else { 5799 /* 5800 * We might have a better answer or delegation 5801 * in the cache. We'll remember the current 5802 * values of fname, rdataset, and sigrdataset. 5803 * We'll then go looking for QNAME in the 5804 * cache. If we find something better, we'll 5805 * use it instead. 5806 */ 5807 query_keepname(client, fname, dbuf); 5808 zdb = db; 5809 zfname = fname; 5810 fname = NULL; 5811 zrdataset = rdataset; 5812 rdataset = NULL; 5813 zsigrdataset = sigrdataset; 5814 sigrdataset = NULL; 5815 dns_db_detachnode(db, &node); 5816 zversion = version; 5817 version = NULL; 5818 db = NULL; 5819 dns_db_attach(client->view->cachedb, &db); 5820 is_zone = ISC_FALSE; 5821 goto db_find; 5822 } 5823 } else { 5824 if (zfname != NULL && 5825 (!dns_name_issubdomain(fname, zfname) || 5826 (is_staticstub_zone && 5827 dns_name_equal(fname, zfname)))) { 5828 /* 5829 * In the following cases use "authoritative" 5830 * data instead of the cache delegation: 5831 * 1. We've already got a delegation from 5832 * authoritative data, and it is better 5833 * than what we found in the cache. 5834 * 2. The query name matches the origin name 5835 * of a static-stub zone. This needs to be 5836 * considered for the case where the NS of 5837 * the static-stub zone and the cached NS 5838 * are different. We still need to contact 5839 * the nameservers configured in the 5840 * static-stub zone. 5841 */ 5842 query_releasename(client, &fname); 5843 fname = zfname; 5844 zfname = NULL; 5845 /* 5846 * We've already done query_keepname() on 5847 * zfname, so we must set dbuf to NULL to 5848 * prevent query_addrrset() from trying to 5849 * call query_keepname() again. 5850 */ 5851 dbuf = NULL; 5852 query_putrdataset(client, &rdataset); 5853 if (sigrdataset != NULL) 5854 query_putrdataset(client, 5855 &sigrdataset); 5856 rdataset = zrdataset; 5857 zrdataset = NULL; 5858 sigrdataset = zsigrdataset; 5859 zsigrdataset = NULL; 5860 version = zversion; 5861 zversion = NULL; 5862 /* 5863 * We don't clean up zdb here because we 5864 * may still need it. It will get cleaned 5865 * up by the main cleanup code. 5866 */ 5867 } 5868 5869 if (RECURSIONOK(client)) { 5870 /* 5871 * Recurse! 5872 */ 5873 if (dns_rdatatype_atparent(type)) 5874 result = query_recurse(client, qtype, 5875 client->query.qname, 5876 NULL, NULL, resuming); 5877 else if (dns64) 5878 result = query_recurse(client, 5879 dns_rdatatype_a, 5880 client->query.qname, 5881 NULL, NULL, resuming); 5882 else 5883 result = query_recurse(client, qtype, 5884 client->query.qname, 5885 fname, rdataset, 5886 resuming); 5887 5888 if (result == ISC_R_SUCCESS) { 5889 client->query.attributes |= 5890 NS_QUERYATTR_RECURSING; 5891 if (dns64) 5892 client->query.attributes |= 5893 NS_QUERYATTR_DNS64; 5894 if (dns64_exclude) 5895 client->query.attributes |= 5896 NS_QUERYATTR_DNS64EXCLUDE; 5897 } else if (result == DNS_R_DUPLICATE || 5898 result == DNS_R_DROP) 5899 QUERY_ERROR(result); 5900 else 5901 RECURSE_ERROR(result); 5902 } else { 5903 dns_fixedname_t fixed; 5904 5905 dns_fixedname_init(&fixed); 5906 dns_name_copy(fname, 5907 dns_fixedname_name(&fixed), NULL); 5908 /* 5909 * This is the best answer. 5910 */ 5911 client->query.attributes |= 5912 NS_QUERYATTR_CACHEGLUEOK; 5913 client->query.gluedb = zdb; 5914 client->query.isreferral = ISC_TRUE; 5915 /* 5916 * We must ensure NOADDITIONAL is off, 5917 * because the generation of 5918 * additional data is required in 5919 * delegations. 5920 */ 5921 client->query.attributes &= 5922 ~NS_QUERYATTR_NOADDITIONAL; 5923 if (sigrdataset != NULL) 5924 sigrdatasetp = &sigrdataset; 5925 else 5926 sigrdatasetp = NULL; 5927 query_addrrset(client, &fname, 5928 &rdataset, sigrdatasetp, 5929 dbuf, DNS_SECTION_AUTHORITY); 5930 client->query.gluedb = NULL; 5931 client->query.attributes &= 5932 ~NS_QUERYATTR_CACHEGLUEOK; 5933 if (WANTDNSSEC(client)) 5934 query_addds(client, db, node, version, 5935 dns_fixedname_name(&fixed)); 5936 } 5937 } 5938 goto cleanup; 5939 5940 case DNS_R_EMPTYNAME: 5941 case DNS_R_NXRRSET: 5942 iszone_nxrrset: 5943 INSIST(is_zone); 5944 5945#ifdef dns64_bis_return_excluded_addresses 5946 if (dns64) 5947#else 5948 if (dns64 && !dns64_exclude) 5949#endif 5950 { 5951 /* 5952 * Restore the answers from the previous AAAA lookup. 5953 */ 5954 if (rdataset != NULL) 5955 query_putrdataset(client, &rdataset); 5956 if (sigrdataset != NULL) 5957 query_putrdataset(client, &sigrdataset); 5958 rdataset = client->query.dns64_aaaa; 5959 sigrdataset = client->query.dns64_sigaaaa; 5960 client->query.dns64_aaaa = NULL; 5961 client->query.dns64_sigaaaa = NULL; 5962 if (fname == NULL) { 5963 dbuf = query_getnamebuf(client); 5964 if (dbuf == NULL) { 5965 QUERY_ERROR(DNS_R_SERVFAIL); 5966 goto cleanup; 5967 } 5968 fname = query_newname(client, dbuf, &b); 5969 if (fname == NULL) { 5970 QUERY_ERROR(DNS_R_SERVFAIL); 5971 goto cleanup; 5972 } 5973 } 5974 dns_name_copy(client->query.qname, fname, NULL); 5975 dns64 = ISC_FALSE; 5976#ifdef dns64_bis_return_excluded_addresses 5977 /* 5978 * Resume the diverted processing of the AAAA response? 5979 */ 5980 if (dns64_excluded) 5981 break; 5982#endif 5983 } else if (result == DNS_R_NXRRSET && 5984 !ISC_LIST_EMPTY(client->view->dns64) && 5985 client->message->rdclass == dns_rdataclass_in && 5986 qtype == dns_rdatatype_aaaa) 5987 { 5988 /* 5989 * Look to see if there are A records for this 5990 * name. 5991 */ 5992 INSIST(client->query.dns64_aaaa == NULL); 5993 INSIST(client->query.dns64_sigaaaa == NULL); 5994 client->query.dns64_aaaa = rdataset; 5995 client->query.dns64_sigaaaa = sigrdataset; 5996 client->query.dns64_ttl = dns64_ttl(db, version); 5997 query_releasename(client, &fname); 5998 dns_db_detachnode(db, &node); 5999 rdataset = NULL; 6000 sigrdataset = NULL; 6001 type = qtype = dns_rdatatype_a; 6002 dns64 = ISC_TRUE; 6003 goto db_find; 6004 } 6005 6006 /* 6007 * Look for a NSEC3 record if we don't have a NSEC record. 6008 */ 6009 nxrrset_rrsig: 6010 if (!dns_rdataset_isassociated(rdataset) && 6011 WANTDNSSEC(client)) { 6012 if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) { 6013 dns_name_t *found; 6014 dns_name_t *qname; 6015 6016 dns_fixedname_init(&fixed); 6017 found = dns_fixedname_name(&fixed); 6018 qname = client->query.qname; 6019 6020 query_findclosestnsec3(qname, db, version, 6021 client, rdataset, 6022 sigrdataset, fname, 6023 ISC_TRUE, found); 6024 /* 6025 * Did we find the closest provable encloser 6026 * instead? If so add the nearest to the 6027 * closest provable encloser. 6028 */ 6029 if (dns_rdataset_isassociated(rdataset) && 6030 !dns_name_equal(qname, found)) { 6031 unsigned int count; 6032 unsigned int skip; 6033 6034 /* 6035 * Add the closest provable encloser. 6036 */ 6037 query_addrrset(client, &fname, 6038 &rdataset, &sigrdataset, 6039 dbuf, 6040 DNS_SECTION_AUTHORITY); 6041 6042 count = dns_name_countlabels(found) 6043 + 1; 6044 skip = dns_name_countlabels(qname) - 6045 count; 6046 dns_name_getlabelsequence(qname, skip, 6047 count, 6048 found); 6049 6050 fixfname(client, &fname, &dbuf, &b); 6051 fixrdataset(client, &rdataset); 6052 fixrdataset(client, &sigrdataset); 6053 if (fname == NULL || 6054 rdataset == NULL || 6055 sigrdataset == NULL) { 6056 QUERY_ERROR(DNS_R_SERVFAIL); 6057 goto cleanup; 6058 } 6059 /* 6060 * 'nearest' doesn't exist so 6061 * 'exist' is set to ISC_FALSE. 6062 */ 6063 query_findclosestnsec3(found, db, 6064 version, 6065 client, 6066 rdataset, 6067 sigrdataset, 6068 fname, 6069 ISC_FALSE, 6070 NULL); 6071 } 6072 } else { 6073 query_releasename(client, &fname); 6074 query_addwildcardproof(client, db, version, 6075 client->query.qname, 6076 ISC_FALSE, ISC_TRUE); 6077 } 6078 } 6079 if (dns_rdataset_isassociated(rdataset)) { 6080 /* 6081 * If we've got a NSEC record, we need to save the 6082 * name now because we're going call query_addsoa() 6083 * below, and it needs to use the name buffer. 6084 */ 6085 query_keepname(client, fname, dbuf); 6086 } else if (fname != NULL) { 6087 /* 6088 * We're not going to use fname, and need to release 6089 * our hold on the name buffer so query_addsoa() 6090 * may use it. 6091 */ 6092 query_releasename(client, &fname); 6093 } 6094 /* 6095 * Add SOA. 6096 */ 6097 result = query_addsoa(client, db, version, ISC_UINT32_MAX, 6098 dns_rdataset_isassociated(rdataset)); 6099 if (result != ISC_R_SUCCESS) { 6100 QUERY_ERROR(result); 6101 goto cleanup; 6102 } 6103 /* 6104 * Add NSEC record if we found one. 6105 */ 6106 if (WANTDNSSEC(client)) { 6107 if (dns_rdataset_isassociated(rdataset)) 6108 query_addnxrrsetnsec(client, db, version, 6109 &fname, &rdataset, 6110 &sigrdataset); 6111 } 6112 goto cleanup; 6113 6114 case DNS_R_EMPTYWILD: 6115 empty_wild = ISC_TRUE; 6116 /* FALLTHROUGH */ 6117 6118 case DNS_R_NXDOMAIN: 6119 INSIST(is_zone); 6120 if (dns_rdataset_isassociated(rdataset)) { 6121 /* 6122 * If we've got a NSEC record, we need to save the 6123 * name now because we're going call query_addsoa() 6124 * below, and it needs to use the name buffer. 6125 */ 6126 query_keepname(client, fname, dbuf); 6127 } else if (fname != NULL) { 6128 /* 6129 * We're not going to use fname, and need to release 6130 * our hold on the name buffer so query_addsoa() 6131 * may use it. 6132 */ 6133 query_releasename(client, &fname); 6134 } 6135 6136 /* 6137 * Add SOA. If the query was for a SOA record force the 6138 * ttl to zero so that it is possible for clients to find 6139 * the containing zone of an arbitrary name with a stub 6140 * resolver and not have it cached. 6141 */ 6142 if (qtype == dns_rdatatype_soa && 6143 zone != NULL && 6144 dns_zone_getzeronosoattl(zone)) 6145 result = query_addsoa(client, db, version, 0, 6146 dns_rdataset_isassociated(rdataset)); 6147 else 6148 result = query_addsoa(client, db, version, 6149 ISC_UINT32_MAX, 6150 dns_rdataset_isassociated(rdataset)); 6151 if (result != ISC_R_SUCCESS) { 6152 QUERY_ERROR(result); 6153 goto cleanup; 6154 } 6155 6156 if (WANTDNSSEC(client)) { 6157 /* 6158 * Add NSEC record if we found one. 6159 */ 6160 if (dns_rdataset_isassociated(rdataset)) 6161 query_addrrset(client, &fname, &rdataset, 6162 &sigrdataset, 6163 NULL, DNS_SECTION_AUTHORITY); 6164 query_addwildcardproof(client, db, version, 6165 client->query.qname, ISC_FALSE, 6166 ISC_FALSE); 6167 } 6168 6169 /* 6170 * Set message rcode. 6171 */ 6172 if (empty_wild) 6173 client->message->rcode = dns_rcode_noerror; 6174 else 6175 client->message->rcode = dns_rcode_nxdomain; 6176 goto cleanup; 6177 6178 case DNS_R_NCACHENXDOMAIN: 6179 case DNS_R_NCACHENXRRSET: 6180 ncache_nxrrset: 6181 INSIST(!is_zone); 6182 authoritative = ISC_FALSE; 6183 /* 6184 * Set message rcode, if required. 6185 */ 6186 if (result == DNS_R_NCACHENXDOMAIN) 6187 client->message->rcode = dns_rcode_nxdomain; 6188 /* 6189 * Look for RFC 1918 leakage from Internet. 6190 */ 6191 if (result == DNS_R_NCACHENXDOMAIN && 6192 qtype == dns_rdatatype_ptr && 6193 client->message->rdclass == dns_rdataclass_in && 6194 dns_name_countlabels(fname) == 7) 6195 warn_rfc1918(client, fname, rdataset); 6196 6197#ifdef dns64_bis_return_excluded_addresses 6198 if (dns64) 6199#else 6200 if (dns64 && !dns64_exclude) 6201#endif 6202 { 6203 /* 6204 * Restore the answers from the previous AAAA lookup. 6205 */ 6206 if (rdataset != NULL) 6207 query_putrdataset(client, &rdataset); 6208 if (sigrdataset != NULL) 6209 query_putrdataset(client, &sigrdataset); 6210 rdataset = client->query.dns64_aaaa; 6211 sigrdataset = client->query.dns64_sigaaaa; 6212 client->query.dns64_aaaa = NULL; 6213 client->query.dns64_sigaaaa = NULL; 6214 if (fname == NULL) { 6215 dbuf = query_getnamebuf(client); 6216 if (dbuf == NULL) { 6217 QUERY_ERROR(DNS_R_SERVFAIL); 6218 goto cleanup; 6219 } 6220 fname = query_newname(client, dbuf, &b); 6221 if (fname == NULL) { 6222 QUERY_ERROR(DNS_R_SERVFAIL); 6223 goto cleanup; 6224 } 6225 } 6226 dns_name_copy(client->query.qname, fname, NULL); 6227 dns64 = ISC_FALSE; 6228#ifdef dns64_bis_return_excluded_addresses 6229 if (dns64_excluded) 6230 break; 6231#endif 6232 } else if (result == DNS_R_NCACHENXRRSET && 6233 !ISC_LIST_EMPTY(client->view->dns64) && 6234 client->message->rdclass == dns_rdataclass_in && 6235 qtype == dns_rdatatype_aaaa) 6236 { 6237 /* 6238 * Look to see if there are A records for this 6239 * name. 6240 */ 6241 INSIST(client->query.dns64_aaaa == NULL); 6242 INSIST(client->query.dns64_sigaaaa == NULL); 6243 client->query.dns64_aaaa = rdataset; 6244 client->query.dns64_sigaaaa = sigrdataset; 6245 /* 6246 * If the ttl is zero we need to workout if we have just 6247 * decremented to zero or if there was no negative cache 6248 * ttl in the answer. 6249 */ 6250 if (rdataset->ttl != 0) 6251 client->query.dns64_ttl = rdataset->ttl; 6252 else if (dns_rdataset_first(rdataset) == ISC_R_SUCCESS) 6253 client->query.dns64_ttl = 0; 6254 query_releasename(client, &fname); 6255 dns_db_detachnode(db, &node); 6256 rdataset = NULL; 6257 sigrdataset = NULL; 6258 fname = NULL; 6259 type = qtype = dns_rdatatype_a; 6260 dns64 = ISC_TRUE; 6261 goto db_find; 6262 } 6263 6264 /* 6265 * We don't call query_addrrset() because we don't need any 6266 * of its extra features (and things would probably break!). 6267 */ 6268 query_keepname(client, fname, dbuf); 6269 dns_message_addname(client->message, fname, 6270 DNS_SECTION_AUTHORITY); 6271 ISC_LIST_APPEND(fname->list, rdataset, link); 6272 fname = NULL; 6273 rdataset = NULL; 6274 goto cleanup; 6275 6276 case DNS_R_CNAME: 6277 /* 6278 * Keep a copy of the rdataset. We have to do this because 6279 * query_addrrset may clear 'rdataset' (to prevent the 6280 * cleanup code from cleaning it up). 6281 */ 6282 trdataset = rdataset; 6283 /* 6284 * Add the CNAME to the answer section. 6285 */ 6286 if (sigrdataset != NULL) 6287 sigrdatasetp = &sigrdataset; 6288 else 6289 sigrdatasetp = NULL; 6290 if (WANTDNSSEC(client) && 6291 (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0) 6292 { 6293 dns_fixedname_init(&wildcardname); 6294 dns_name_copy(fname, dns_fixedname_name(&wildcardname), 6295 NULL); 6296 need_wildcardproof = ISC_TRUE; 6297 } 6298 if (NOQNAME(rdataset) && WANTDNSSEC(client)) 6299 noqname = rdataset; 6300 else 6301 noqname = NULL; 6302 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, 6303 DNS_SECTION_ANSWER); 6304 if (noqname != NULL) 6305 query_addnoqnameproof(client, noqname); 6306 /* 6307 * We set the PARTIALANSWER attribute so that if anything goes 6308 * wrong later on, we'll return what we've got so far. 6309 */ 6310 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER; 6311 /* 6312 * Reset qname to be the target name of the CNAME and restart 6313 * the query. 6314 */ 6315 tname = NULL; 6316 result = dns_message_gettempname(client->message, &tname); 6317 if (result != ISC_R_SUCCESS) 6318 goto cleanup; 6319 result = dns_rdataset_first(trdataset); 6320 if (result != ISC_R_SUCCESS) { 6321 dns_message_puttempname(client->message, &tname); 6322 goto cleanup; 6323 } 6324 dns_rdataset_current(trdataset, &rdata); 6325 result = dns_rdata_tostruct(&rdata, &cname, NULL); 6326 dns_rdata_reset(&rdata); 6327 if (result != ISC_R_SUCCESS) { 6328 dns_message_puttempname(client->message, &tname); 6329 goto cleanup; 6330 } 6331 dns_name_init(tname, NULL); 6332 result = dns_name_dup(&cname.cname, client->mctx, tname); 6333 if (result != ISC_R_SUCCESS) { 6334 dns_message_puttempname(client->message, &tname); 6335 dns_rdata_freestruct(&cname); 6336 goto cleanup; 6337 } 6338 dns_rdata_freestruct(&cname); 6339 ns_client_qnamereplace(client, tname); 6340 want_restart = ISC_TRUE; 6341 if (!WANTRECURSION(client)) 6342 options |= DNS_GETDB_NOLOG; 6343 goto addauth; 6344 case DNS_R_DNAME: 6345 /* 6346 * Compare the current qname to the found name. We need 6347 * to know how many labels and bits are in common because 6348 * we're going to have to split qname later on. 6349 */ 6350 namereln = dns_name_fullcompare(client->query.qname, fname, 6351 &order, &nlabels); 6352 INSIST(namereln == dns_namereln_subdomain); 6353 /* 6354 * Keep a copy of the rdataset. We have to do this because 6355 * query_addrrset may clear 'rdataset' (to prevent the 6356 * cleanup code from cleaning it up). 6357 */ 6358 trdataset = rdataset; 6359 /* 6360 * Add the DNAME to the answer section. 6361 */ 6362 if (sigrdataset != NULL) 6363 sigrdatasetp = &sigrdataset; 6364 else 6365 sigrdatasetp = NULL; 6366 if (WANTDNSSEC(client) && 6367 (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0) 6368 { 6369 dns_fixedname_init(&wildcardname); 6370 dns_name_copy(fname, dns_fixedname_name(&wildcardname), 6371 NULL); 6372 need_wildcardproof = ISC_TRUE; 6373 } 6374 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, 6375 DNS_SECTION_ANSWER); 6376 /* 6377 * We set the PARTIALANSWER attribute so that if anything goes 6378 * wrong later on, we'll return what we've got so far. 6379 */ 6380 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER; 6381 /* 6382 * Get the target name of the DNAME. 6383 */ 6384 tname = NULL; 6385 result = dns_message_gettempname(client->message, &tname); 6386 if (result != ISC_R_SUCCESS) 6387 goto cleanup; 6388 result = dns_rdataset_first(trdataset); 6389 if (result != ISC_R_SUCCESS) { 6390 dns_message_puttempname(client->message, &tname); 6391 goto cleanup; 6392 } 6393 dns_rdataset_current(trdataset, &rdata); 6394 result = dns_rdata_tostruct(&rdata, &dname, NULL); 6395 dns_rdata_reset(&rdata); 6396 if (result != ISC_R_SUCCESS) { 6397 dns_message_puttempname(client->message, &tname); 6398 goto cleanup; 6399 } 6400 dns_name_clone(&dname.dname, tname); 6401 dns_rdata_freestruct(&dname); 6402 /* 6403 * Construct the new qname consisting of 6404 * <found name prefix>.<dname target> 6405 */ 6406 dns_fixedname_init(&fixed); 6407 prefix = dns_fixedname_name(&fixed); 6408 dns_name_split(client->query.qname, nlabels, prefix, NULL); 6409 INSIST(fname == NULL); 6410 dbuf = query_getnamebuf(client); 6411 if (dbuf == NULL) { 6412 dns_message_puttempname(client->message, &tname); 6413 goto cleanup; 6414 } 6415 fname = query_newname(client, dbuf, &b); 6416 if (fname == NULL) { 6417 dns_message_puttempname(client->message, &tname); 6418 goto cleanup; 6419 } 6420 result = dns_name_concatenate(prefix, tname, fname, NULL); 6421 dns_message_puttempname(client->message, &tname); 6422 6423 /* 6424 * RFC2672, section 4.1, subsection 3c says 6425 * we should return YXDOMAIN if the constructed 6426 * name would be too long. 6427 */ 6428 if (result == DNS_R_NAMETOOLONG) 6429 client->message->rcode = dns_rcode_yxdomain; 6430 if (result != ISC_R_SUCCESS) 6431 goto cleanup; 6432 6433 query_keepname(client, fname, dbuf); 6434 /* 6435 * Synthesize a CNAME consisting of 6436 * <old qname> <dname ttl> CNAME <new qname> 6437 * with <dname trust value> 6438 * 6439 * Synthesize a CNAME so old old clients that don't understand 6440 * DNAME can chain. 6441 * 6442 * We do not try to synthesize a signature because we hope 6443 * that security aware servers will understand DNAME. Also, 6444 * even if we had an online key, making a signature 6445 * on-the-fly is costly, and not really legitimate anyway 6446 * since the synthesized CNAME is NOT in the zone. 6447 */ 6448 result = query_add_cname(client, client->query.qname, fname, 6449 trdataset->trust, trdataset->ttl); 6450 if (result != ISC_R_SUCCESS) 6451 goto cleanup; 6452 /* 6453 * Switch to the new qname and restart. 6454 */ 6455 ns_client_qnamereplace(client, fname); 6456 fname = NULL; 6457 want_restart = ISC_TRUE; 6458 if (!WANTRECURSION(client)) 6459 options |= DNS_GETDB_NOLOG; 6460 goto addauth; 6461 default: 6462 /* 6463 * Something has gone wrong. 6464 */ 6465 QUERY_ERROR(DNS_R_SERVFAIL); 6466 goto cleanup; 6467 } 6468 6469 if (WANTDNSSEC(client) && 6470 (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0) 6471 { 6472 dns_fixedname_init(&wildcardname); 6473 dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL); 6474 need_wildcardproof = ISC_TRUE; 6475 } 6476 6477#ifdef ALLOW_FILTER_AAAA_ON_V4 6478 if (client->view->v4_aaaa != dns_v4_aaaa_ok && 6479 is_v4_client(client) && 6480 ns_client_checkaclsilent(client, NULL, 6481 client->view->v4_aaaa_acl, 6482 ISC_TRUE) == ISC_R_SUCCESS) 6483 client->filter_aaaa = client->view->v4_aaaa; 6484 else 6485 client->filter_aaaa = dns_v4_aaaa_ok; 6486 6487#endif 6488 6489 if (type == dns_rdatatype_any) { 6490#ifdef ALLOW_FILTER_AAAA_ON_V4 6491 isc_boolean_t have_aaaa, have_a, have_sig; 6492 6493 /* 6494 * The filter-aaaa-on-v4 option should 6495 * suppress AAAAs for IPv4 clients if there is an A. 6496 * If we are not authoritative, assume there is a A 6497 * even in if it is not in our cache. This assumption could 6498 * be wrong but it is a good bet. 6499 */ 6500 have_aaaa = ISC_FALSE; 6501 have_a = !authoritative; 6502 have_sig = ISC_FALSE; 6503#endif 6504 /* 6505 * XXXRTH Need to handle zonecuts with special case 6506 * code. 6507 */ 6508 n = 0; 6509 rdsiter = NULL; 6510 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter); 6511 if (result != ISC_R_SUCCESS) { 6512 QUERY_ERROR(DNS_R_SERVFAIL); 6513 goto cleanup; 6514 } 6515 6516 /* 6517 * Calling query_addrrset() with a non-NULL dbuf is going 6518 * to either keep or release the name. We don't want it to 6519 * release fname, since we may have to call query_addrrset() 6520 * more than once. That means we have to call query_keepname() 6521 * now, and pass a NULL dbuf to query_addrrset(). 6522 * 6523 * If we do a query_addrrset() below, we must set fname to 6524 * NULL before leaving this block, otherwise we might try to 6525 * cleanup fname even though we're using it! 6526 */ 6527 query_keepname(client, fname, dbuf); 6528 tname = fname; 6529 result = dns_rdatasetiter_first(rdsiter); 6530 while (result == ISC_R_SUCCESS) { 6531 dns_rdatasetiter_current(rdsiter, rdataset); 6532#ifdef ALLOW_FILTER_AAAA_ON_V4 6533 /* 6534 * Notice the presence of A and AAAAs so 6535 * that AAAAs can be hidden from IPv4 clients. 6536 */ 6537 if (client->filter_aaaa != dns_v4_aaaa_ok) { 6538 if (rdataset->type == dns_rdatatype_aaaa) 6539 have_aaaa = ISC_TRUE; 6540 else if (rdataset->type == dns_rdatatype_a) 6541 have_a = ISC_TRUE; 6542 } 6543#endif 6544 if (is_zone && qtype == dns_rdatatype_any && 6545 !dns_db_issecure(db) && 6546 dns_rdatatype_isdnssec(rdataset->type)) { 6547 /* 6548 * The zone is transitioning from insecure 6549 * to secure. Hide the dnssec records from 6550 * ANY queries. 6551 */ 6552 dns_rdataset_disassociate(rdataset); 6553 } else if ((qtype == dns_rdatatype_any || 6554 rdataset->type == qtype) && rdataset->type != 0) { 6555#ifdef ALLOW_FILTER_AAAA_ON_V4 6556 if (dns_rdatatype_isdnssec(rdataset->type)) 6557 have_sig = ISC_TRUE; 6558#endif 6559 if (NOQNAME(rdataset) && WANTDNSSEC(client)) 6560 noqname = rdataset; 6561 else 6562 noqname = NULL; 6563 query_addrrset(client, 6564 fname != NULL ? &fname : &tname, 6565 &rdataset, NULL, 6566 NULL, DNS_SECTION_ANSWER); 6567 if (noqname != NULL) 6568 query_addnoqnameproof(client, noqname); 6569 n++; 6570 INSIST(tname != NULL); 6571 /* 6572 * rdataset is non-NULL only in certain 6573 * pathological cases involving DNAMEs. 6574 */ 6575 if (rdataset != NULL) 6576 query_putrdataset(client, &rdataset); 6577 rdataset = query_newrdataset(client); 6578 if (rdataset == NULL) 6579 break; 6580 } else { 6581 /* 6582 * We're not interested in this rdataset. 6583 */ 6584 dns_rdataset_disassociate(rdataset); 6585 } 6586 result = dns_rdatasetiter_next(rdsiter); 6587 } 6588 6589#ifdef ALLOW_FILTER_AAAA_ON_V4 6590 /* 6591 * Filter AAAAs if there is an A and there is no signature 6592 * or we are supposed to break DNSSEC. 6593 */ 6594 if (client->filter_aaaa == dns_v4_aaaa_break_dnssec) 6595 client->attributes |= NS_CLIENTATTR_FILTER_AAAA; 6596 else if (client->filter_aaaa != dns_v4_aaaa_ok && 6597 have_aaaa && have_a && 6598 (!have_sig || !WANTDNSSEC(client))) 6599 client->attributes |= NS_CLIENTATTR_FILTER_AAAA; 6600#endif 6601 if (fname != NULL) 6602 dns_message_puttempname(client->message, &fname); 6603 6604 if (n == 0) { 6605 /* 6606 * No matching rdatasets found in cache. If we were 6607 * searching for RRSIG/SIG, that's probably okay; 6608 * otherwise this is an error condition. 6609 */ 6610 if ((qtype == dns_rdatatype_rrsig || 6611 qtype == dns_rdatatype_sig) && 6612 result == ISC_R_NOMORE) { 6613 if (!is_zone) { 6614 authoritative = ISC_FALSE; 6615 dns_rdatasetiter_destroy(&rdsiter); 6616 client->attributes &= ~NS_CLIENTATTR_RA; 6617 goto addauth; 6618 } 6619 6620 if (dns_db_issecure(db)) { 6621 char namebuf[DNS_NAME_FORMATSIZE]; 6622 dns_name_format(client->query.qname, 6623 namebuf, 6624 sizeof(namebuf)); 6625 ns_client_log(client, 6626 DNS_LOGCATEGORY_DNSSEC, 6627 NS_LOGMODULE_QUERY, 6628 ISC_LOG_WARNING, 6629 "missing signature " 6630 "for %s", namebuf); 6631 } 6632 6633 dns_rdatasetiter_destroy(&rdsiter); 6634 fname = query_newname(client, dbuf, &b); 6635 goto nxrrset_rrsig; 6636 } else 6637 result = DNS_R_SERVFAIL; 6638 } 6639 6640 dns_rdatasetiter_destroy(&rdsiter); 6641 if (result != ISC_R_NOMORE) { 6642 QUERY_ERROR(DNS_R_SERVFAIL); 6643 goto cleanup; 6644 } 6645 } else { 6646 /* 6647 * This is the "normal" case -- an ordinary question to which 6648 * we know the answer. 6649 */ 6650 6651#ifdef ALLOW_FILTER_AAAA_ON_V4 6652 /* 6653 * Optionally hide AAAAs from IPv4 clients if there is an A. 6654 * We add the AAAAs now, but might refuse to render them later 6655 * after DNSSEC is figured out. 6656 * This could be more efficient, but the whole idea is 6657 * so fundamentally wrong, unavoidably inaccurate, and 6658 * unneeded that it is best to keep it as short as possible. 6659 */ 6660 if (client->filter_aaaa == dns_v4_aaaa_break_dnssec || 6661 (client->filter_aaaa == dns_v4_aaaa_filter && 6662 (!WANTDNSSEC(client) || sigrdataset == NULL || 6663 !dns_rdataset_isassociated(sigrdataset)))) 6664 { 6665 if (qtype == dns_rdatatype_aaaa) { 6666 trdataset = query_newrdataset(client); 6667 result = dns_db_findrdataset(db, node, version, 6668 dns_rdatatype_a, 0, 6669 client->now, 6670 trdataset, NULL); 6671 if (dns_rdataset_isassociated(trdataset)) 6672 dns_rdataset_disassociate(trdataset); 6673 query_putrdataset(client, &trdataset); 6674 6675 /* 6676 * We have an AAAA but the A is not in our cache. 6677 * Assume any result other than DNS_R_DELEGATION 6678 * or ISC_R_NOTFOUND means there is no A and 6679 * so AAAAs are ok. 6680 * Assume there is no A if we can't recurse 6681 * for this client, although that could be 6682 * the wrong answer. What else can we do? 6683 * Besides, that we have the AAAA and are using 6684 * this mechanism suggests that we care more 6685 * about As than AAAAs and would have cached 6686 * the A if it existed. 6687 */ 6688 if (result == ISC_R_SUCCESS) { 6689 client->attributes |= 6690 NS_CLIENTATTR_FILTER_AAAA; 6691 6692 } else if (authoritative || 6693 !RECURSIONOK(client) || 6694 (result != DNS_R_DELEGATION && 6695 result != ISC_R_NOTFOUND)) { 6696 client->attributes &= 6697 ~NS_CLIENTATTR_FILTER_AAAA; 6698 } else { 6699 /* 6700 * This is an ugly kludge to recurse 6701 * for the A and discard the result. 6702 * 6703 * Continue to add the AAAA now. 6704 * We'll make a note to not render it 6705 * if the recursion for the A succeeds. 6706 */ 6707 result = query_recurse(client, 6708 dns_rdatatype_a, 6709 client->query.qname, 6710 NULL, NULL, resuming); 6711 if (result == ISC_R_SUCCESS) { 6712 client->attributes |= 6713 NS_CLIENTATTR_FILTER_AAAA_RC; 6714 client->query.attributes |= 6715 NS_QUERYATTR_RECURSING; 6716 } 6717 } 6718 6719 } else if (qtype == dns_rdatatype_a && 6720 (client->attributes & 6721 NS_CLIENTATTR_FILTER_AAAA_RC) != 0) { 6722 client->attributes &= 6723 ~NS_CLIENTATTR_FILTER_AAAA_RC; 6724 client->attributes |= 6725 NS_CLIENTATTR_FILTER_AAAA; 6726 dns_rdataset_disassociate(rdataset); 6727 if (sigrdataset != NULL && 6728 dns_rdataset_isassociated(sigrdataset)) 6729 dns_rdataset_disassociate(sigrdataset); 6730 goto cleanup; 6731 } 6732 } 6733#endif 6734 /* 6735 * Check to see if the AAAA RRset has non-excluded addresses 6736 * in it. If not look for a A RRset. 6737 */ 6738 INSIST(client->query.dns64_aaaaok == NULL); 6739 6740 if (qtype == dns_rdatatype_aaaa && !dns64_exclude && 6741 !ISC_LIST_EMPTY(client->view->dns64) && 6742 client->message->rdclass == dns_rdataclass_in && 6743 !dns64_aaaaok(client, rdataset, sigrdataset)) { 6744 /* 6745 * Look to see if there are A records for this 6746 * name. 6747 */ 6748 client->query.dns64_aaaa = rdataset; 6749 client->query.dns64_sigaaaa = sigrdataset; 6750 client->query.dns64_ttl = rdataset->ttl; 6751 query_releasename(client, &fname); 6752 dns_db_detachnode(db, &node); 6753 rdataset = NULL; 6754 sigrdataset = NULL; 6755 type = qtype = dns_rdatatype_a; 6756 dns64_exclude = dns64 = ISC_TRUE; 6757 goto db_find; 6758 } 6759 6760 if (sigrdataset != NULL) 6761 sigrdatasetp = &sigrdataset; 6762 else 6763 sigrdatasetp = NULL; 6764 if (NOQNAME(rdataset) && WANTDNSSEC(client)) 6765 noqname = rdataset; 6766 else 6767 noqname = NULL; 6768 /* 6769 * BIND 8 priming queries need the additional section. 6770 */ 6771 if (is_zone && qtype == dns_rdatatype_ns && 6772 dns_name_equal(client->query.qname, dns_rootname)) 6773 client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL; 6774 6775 if (dns64) { 6776 qtype = type = dns_rdatatype_aaaa; 6777 result = query_dns64(client, &fname, rdataset, 6778 sigrdataset, dbuf, 6779 DNS_SECTION_ANSWER); 6780 dns_rdataset_disassociate(rdataset); 6781 dns_message_puttemprdataset(client->message, &rdataset); 6782 if (result == ISC_R_NOMORE) { 6783#ifndef dns64_bis_return_excluded_addresses 6784 if (dns64_exclude) { 6785 if (!is_zone) 6786 goto cleanup; 6787 /* 6788 * Add a fake SOA record. 6789 */ 6790 (void)query_addsoa(client, db, version, 6791 600, ISC_FALSE); 6792 goto cleanup; 6793 } 6794#endif 6795 if (is_zone) 6796 goto iszone_nxrrset; 6797 else 6798 goto ncache_nxrrset; 6799 } else if (result != ISC_R_SUCCESS) { 6800 eresult = result; 6801 goto cleanup; 6802 } 6803 } else if (client->query.dns64_aaaaok != NULL) { 6804 query_filter64(client, &fname, rdataset, dbuf, 6805 DNS_SECTION_ANSWER); 6806 query_putrdataset(client, &rdataset); 6807 } else 6808 query_addrrset(client, &fname, &rdataset, 6809 sigrdatasetp, dbuf, DNS_SECTION_ANSWER); 6810 6811 if (noqname != NULL) 6812 query_addnoqnameproof(client, noqname); 6813 /* 6814 * We shouldn't ever fail to add 'rdataset' 6815 * because it's already in the answer. 6816 */ 6817 INSIST(rdataset == NULL); 6818 } 6819 6820 addauth: 6821 CTRACE("query_find: addauth"); 6822 /* 6823 * Add NS records to the authority section (if we haven't already 6824 * added them to the answer section). 6825 */ 6826 if (!want_restart && !NOAUTHORITY(client)) { 6827 if (is_zone) { 6828 if (!((qtype == dns_rdatatype_ns || 6829 qtype == dns_rdatatype_any) && 6830 dns_name_equal(client->query.qname, 6831 dns_db_origin(db)))) 6832 (void)query_addns(client, db, version); 6833 } else if (qtype != dns_rdatatype_ns) { 6834 if (fname != NULL) 6835 query_releasename(client, &fname); 6836 query_addbestns(client); 6837 } 6838 } 6839 6840 /* 6841 * Add NSEC records to the authority section if they're needed for 6842 * DNSSEC wildcard proofs. 6843 */ 6844 if (need_wildcardproof && dns_db_issecure(db)) 6845 query_addwildcardproof(client, db, version, 6846 dns_fixedname_name(&wildcardname), 6847 ISC_TRUE, ISC_FALSE); 6848 cleanup: 6849 CTRACE("query_find: cleanup"); 6850 /* 6851 * General cleanup. 6852 */ 6853 rpz_st = client->query.rpz_st; 6854 if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) { 6855 rpz_clean(&rpz_st->m.zone, &rpz_st->m.db, &rpz_st->m.node, 6856 &rpz_st->m.rdataset); 6857 rpz_st->state &= ~DNS_RPZ_DONE_QNAME; 6858 } 6859 if (rdataset != NULL) 6860 query_putrdataset(client, &rdataset); 6861 if (sigrdataset != NULL) 6862 query_putrdataset(client, &sigrdataset); 6863 if (fname != NULL) 6864 query_releasename(client, &fname); 6865 if (node != NULL) 6866 dns_db_detachnode(db, &node); 6867 if (db != NULL) 6868 dns_db_detach(&db); 6869 if (zone != NULL) 6870 dns_zone_detach(&zone); 6871 if (zdb != NULL) { 6872 query_putrdataset(client, &zrdataset); 6873 if (zsigrdataset != NULL) 6874 query_putrdataset(client, &zsigrdataset); 6875 if (zfname != NULL) 6876 query_releasename(client, &zfname); 6877 dns_db_detach(&zdb); 6878 } 6879 if (event != NULL) 6880 isc_event_free(ISC_EVENT_PTR(&event)); 6881 6882 /* 6883 * AA bit. 6884 */ 6885 if (client->query.restarts == 0 && !authoritative) { 6886 /* 6887 * We're not authoritative, so we must ensure the AA bit 6888 * isn't set. 6889 */ 6890 client->message->flags &= ~DNS_MESSAGEFLAG_AA; 6891 } 6892 6893 /* 6894 * Restart the query? 6895 */ 6896 if (want_restart && client->query.restarts < MAX_RESTARTS) { 6897 client->query.restarts++; 6898 goto restart; 6899 } 6900 6901 if (eresult != ISC_R_SUCCESS && 6902 (!PARTIALANSWER(client) || WANTRECURSION(client))) { 6903 if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) { 6904 /* 6905 * This was a duplicate query that we are 6906 * recursing on. Don't send a response now. 6907 * The original query will still cause a response. 6908 */ 6909 query_next(client, eresult); 6910 } else { 6911 /* 6912 * If we don't have any answer to give the client, 6913 * or if the client requested recursion and thus wanted 6914 * the complete answer, send an error response. 6915 */ 6916 INSIST(line >= 0); 6917 query_error(client, eresult, line); 6918 } 6919 ns_client_detach(&client); 6920 } else if (!RECURSING(client)) { 6921 /* 6922 * We are done. Set up sortlist data for the message 6923 * rendering code, make a final tweak to the AA bit if the 6924 * auth-nxdomain config option says so, then render and 6925 * send the response. 6926 */ 6927 setup_query_sortlist(client); 6928 6929 /* 6930 * If this is a referral and the answer to the question 6931 * is in the glue sort it to the start of the additional 6932 * section. 6933 */ 6934 if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) && 6935 client->message->rcode == dns_rcode_noerror && 6936 (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa)) 6937 answer_in_glue(client, qtype); 6938 6939 if (client->message->rcode == dns_rcode_nxdomain && 6940 client->view->auth_nxdomain == ISC_TRUE) 6941 client->message->flags |= DNS_MESSAGEFLAG_AA; 6942 6943 /* 6944 * If the response is somehow unexpected for the client and this 6945 * is a result of recursion, return an error to the caller 6946 * to indicate it may need to be logged. 6947 */ 6948 if (resuming && 6949 (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) || 6950 client->message->rcode != dns_rcode_noerror)) 6951 eresult = ISC_R_FAILURE; 6952 6953 query_send(client); 6954 ns_client_detach(&client); 6955 } 6956 CTRACE("query_find: done"); 6957 6958 return (eresult); 6959} 6960 6961static inline void 6962log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) { 6963 char namebuf[DNS_NAME_FORMATSIZE]; 6964 char typename[DNS_RDATATYPE_FORMATSIZE]; 6965 char classname[DNS_RDATACLASS_FORMATSIZE]; 6966 char onbuf[ISC_NETADDR_FORMATSIZE]; 6967 dns_rdataset_t *rdataset; 6968 int level = ISC_LOG_INFO; 6969 6970 if (! isc_log_wouldlog(ns_g_lctx, level)) 6971 return; 6972 6973 rdataset = ISC_LIST_HEAD(client->query.qname->list); 6974 INSIST(rdataset != NULL); 6975 dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); 6976 dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname)); 6977 dns_rdatatype_format(rdataset->type, typename, sizeof(typename)); 6978 isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf)); 6979 6980 ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, 6981 level, "query: %s %s %s %s%s%s%s%s%s (%s)", namebuf, 6982 classname, typename, WANTRECURSION(client) ? "+" : "-", 6983 (client->signer != NULL) ? "S": "", 6984 (client->opt != NULL) ? "E" : "", 6985 ((client->attributes & NS_CLIENTATTR_TCP) != 0) ? 6986 "T" : "", 6987 ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "", 6988 ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "", 6989 onbuf); 6990} 6991 6992static inline void 6993log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) { 6994 char namebuf[DNS_NAME_FORMATSIZE]; 6995 char typename[DNS_RDATATYPE_FORMATSIZE]; 6996 char classname[DNS_RDATACLASS_FORMATSIZE]; 6997 const char *namep, *typep, *classp, *sep1, *sep2; 6998 dns_rdataset_t *rdataset; 6999 7000 if (!isc_log_wouldlog(ns_g_lctx, level)) 7001 return; 7002 7003 namep = typep = classp = sep1 = sep2 = ""; 7004 7005 /* 7006 * Query errors can happen for various reasons. In some cases we cannot 7007 * even assume the query contains a valid question section, so we should 7008 * expect exceptional cases. 7009 */ 7010 if (client->query.origqname != NULL) { 7011 dns_name_format(client->query.origqname, namebuf, 7012 sizeof(namebuf)); 7013 namep = namebuf; 7014 sep1 = " for "; 7015 7016 rdataset = ISC_LIST_HEAD(client->query.origqname->list); 7017 if (rdataset != NULL) { 7018 dns_rdataclass_format(rdataset->rdclass, classname, 7019 sizeof(classname)); 7020 classp = classname; 7021 dns_rdatatype_format(rdataset->type, typename, 7022 sizeof(typename)); 7023 typep = typename; 7024 sep2 = "/"; 7025 } 7026 } 7027 7028 ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, NS_LOGMODULE_QUERY, 7029 level, "query failed (%s)%s%s%s%s%s%s at %s:%d", 7030 isc_result_totext(result), sep1, namep, sep2, 7031 classp, sep2, typep, __FILE__, line); 7032} 7033 7034void 7035ns_query_start(ns_client_t *client) { 7036 isc_result_t result; 7037 dns_message_t *message = client->message; 7038 dns_rdataset_t *rdataset; 7039 ns_client_t *qclient; 7040 dns_rdatatype_t qtype; 7041 unsigned int saved_extflags = client->extflags; 7042 unsigned int saved_flags = client->message->flags; 7043 isc_boolean_t want_ad; 7044 7045 CTRACE("ns_query_start"); 7046 7047 /* 7048 * Test only. 7049 */ 7050 if (ns_g_clienttest && (client->attributes & NS_CLIENTATTR_TCP) == 0) 7051 RUNTIME_CHECK(ns_client_replace(client) == ISC_R_SUCCESS); 7052 7053 /* 7054 * Ensure that appropriate cleanups occur. 7055 */ 7056 client->next = query_next_callback; 7057 7058 /* 7059 * Behave as if we don't support DNSSEC if not enabled. 7060 */ 7061 if (!client->view->enablednssec) { 7062 message->flags &= ~DNS_MESSAGEFLAG_CD; 7063 client->extflags &= ~DNS_MESSAGEEXTFLAG_DO; 7064 if (client->opt != NULL) 7065 client->opt->ttl &= ~DNS_MESSAGEEXTFLAG_DO; 7066 } 7067 7068 if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) 7069 client->query.attributes |= NS_QUERYATTR_WANTRECURSION; 7070 7071 if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0) 7072 client->attributes |= NS_CLIENTATTR_WANTDNSSEC; 7073 7074 if (client->view->minimalresponses) 7075 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | 7076 NS_QUERYATTR_NOADDITIONAL); 7077 7078 if ((client->view->cachedb == NULL) 7079 || (!client->view->additionalfromcache)) { 7080 /* 7081 * We don't have a cache. Turn off cache support and 7082 * recursion. 7083 */ 7084 client->query.attributes &= 7085 ~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK); 7086 } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 || 7087 (message->flags & DNS_MESSAGEFLAG_RD) == 0) { 7088 /* 7089 * If the client isn't allowed to recurse (due to 7090 * "recursion no", the allow-recursion ACL, or the 7091 * lack of a resolver in this view), or if it 7092 * doesn't want recursion, turn recursion off. 7093 */ 7094 client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK; 7095 } 7096 7097 /* 7098 * Get the question name. 7099 */ 7100 result = dns_message_firstname(message, DNS_SECTION_QUESTION); 7101 if (result != ISC_R_SUCCESS) { 7102 query_error(client, result, __LINE__); 7103 return; 7104 } 7105 dns_message_currentname(message, DNS_SECTION_QUESTION, 7106 &client->query.qname); 7107 client->query.origqname = client->query.qname; 7108 result = dns_message_nextname(message, DNS_SECTION_QUESTION); 7109 if (result != ISC_R_NOMORE) { 7110 if (result == ISC_R_SUCCESS) { 7111 /* 7112 * There's more than one QNAME in the question 7113 * section. 7114 */ 7115 query_error(client, DNS_R_FORMERR, __LINE__); 7116 } else 7117 query_error(client, result, __LINE__); 7118 return; 7119 } 7120 7121 if (ns_g_server->log_queries) 7122 log_query(client, saved_flags, saved_extflags); 7123 7124 /* 7125 * Check for multiple question queries, since edns1 is dead. 7126 */ 7127 if (message->counts[DNS_SECTION_QUESTION] > 1) { 7128 query_error(client, DNS_R_FORMERR, __LINE__); 7129 return; 7130 } 7131 7132 /* 7133 * Check for meta-queries like IXFR and AXFR. 7134 */ 7135 rdataset = ISC_LIST_HEAD(client->query.qname->list); 7136 INSIST(rdataset != NULL); 7137 qtype = rdataset->type; 7138 dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype); 7139 if (dns_rdatatype_ismeta(qtype)) { 7140 switch (qtype) { 7141 case dns_rdatatype_any: 7142 break; /* Let query_find handle it. */ 7143 case dns_rdatatype_ixfr: 7144 case dns_rdatatype_axfr: 7145 ns_xfr_start(client, rdataset->type); 7146 return; 7147 case dns_rdatatype_maila: 7148 case dns_rdatatype_mailb: 7149 query_error(client, DNS_R_NOTIMP, __LINE__); 7150 return; 7151 case dns_rdatatype_tkey: 7152 result = dns_tkey_processquery(client->message, 7153 ns_g_server->tkeyctx, 7154 client->view->dynamickeys); 7155 if (result == ISC_R_SUCCESS) 7156 query_send(client); 7157 else 7158 query_error(client, result, __LINE__); 7159 return; 7160 default: /* TSIG, etc. */ 7161 query_error(client, DNS_R_FORMERR, __LINE__); 7162 return; 7163 } 7164 } 7165 7166 /* 7167 * Turn on minimal response for DNSKEY and DS queries. 7168 */ 7169 if (qtype == dns_rdatatype_dnskey || qtype == dns_rdatatype_ds) 7170 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | 7171 NS_QUERYATTR_NOADDITIONAL); 7172 7173 /* 7174 * Turn on minimal responses for EDNS/UDP bufsize 512 queries. 7175 */ 7176 if (client->opt != NULL && client->udpsize <= 512U && 7177 (client->attributes & NS_CLIENTATTR_TCP) == 0) 7178 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | 7179 NS_QUERYATTR_NOADDITIONAL); 7180 7181 /* 7182 * If the client has requested that DNSSEC checking be disabled, 7183 * allow lookups to return pending data and instruct the resolver 7184 * to return data before validation has completed. 7185 * 7186 * We don't need to set DNS_DBFIND_PENDINGOK when validation is 7187 * disabled as there will be no pending data. 7188 */ 7189 if (message->flags & DNS_MESSAGEFLAG_CD || 7190 qtype == dns_rdatatype_rrsig) 7191 { 7192 client->query.dboptions |= DNS_DBFIND_PENDINGOK; 7193 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE; 7194 } else if (!client->view->enablevalidation) 7195 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE; 7196 7197 /* 7198 * Allow glue NS records to be added to the authority section 7199 * if the answer is secure. 7200 */ 7201 if (message->flags & DNS_MESSAGEFLAG_CD) 7202 client->query.attributes &= ~NS_QUERYATTR_SECURE; 7203 7204 /* 7205 * Set 'want_ad' if the client has set AD in the query. 7206 * This allows AD to be returned on queries without DO set. 7207 */ 7208 if ((message->flags & DNS_MESSAGEFLAG_AD) != 0) 7209 want_ad = ISC_TRUE; 7210 else 7211 want_ad = ISC_FALSE; 7212 7213 /* 7214 * This is an ordinary query. 7215 */ 7216 result = dns_message_reply(message, ISC_TRUE); 7217 if (result != ISC_R_SUCCESS) { 7218 query_next(client, result); 7219 return; 7220 } 7221 7222 /* 7223 * Assume authoritative response until it is known to be 7224 * otherwise. 7225 * 7226 * If "-T noaa" has been set on the command line don't set 7227 * AA on authoritative answers. 7228 */ 7229 if (!ns_g_noaa) 7230 message->flags |= DNS_MESSAGEFLAG_AA; 7231 7232 /* 7233 * Set AD. We must clear it if we add non-validated data to a 7234 * response. 7235 */ 7236 if (WANTDNSSEC(client) || want_ad) 7237 message->flags |= DNS_MESSAGEFLAG_AD; 7238 7239 qclient = NULL; 7240 ns_client_attach(client, &qclient); 7241 (void)query_find(qclient, NULL, qtype); 7242} 7243