2 * Copyright (C) 2004-2016 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.
26 #include <isc/print.h>
27 #include <isc/serial.h>
28 #include <isc/stats.h>
29 #include <isc/thread.h>
33 #include <dns/byaddr.h>
36 #include <dns/dns64.h>
37 #include <dns/dnssec.h>
38 #include <dns/events.h>
39 #include <dns/message.h>
40 #include <dns/ncache.h>
41 #include <dns/nsec3.h>
42 #include <dns/order.h>
43 #include <dns/rdata.h>
44 #include <dns/rdataclass.h>
45 #include <dns/rdatalist.h>
46 #include <dns/rdataset.h>
47 #include <dns/rdatasetiter.h>
48 #include <dns/rdatastruct.h>
49 #include <dns/rdatatype.h>
50 #include <dns/resolver.h>
51 #include <dns/result.h>
52 #include <dns/stats.h>
58 #include <named/client.h>
59 #include <named/globals.h>
60 #include <named/log.h>
61 #include <named/server.h>
62 #include <named/sortlist.h>
63 #include <named/xfrout.h>
67 * It has been recommended that DNS64 be changed to return excluded
68 * AAAA addresses if DNS64 synthesis does not occur. This minimises
69 * the impact on the lookup results. While most DNS AAAA lookups are
70 * done to send IP packets to a host, not all of them are and filtering
71 * excluded addresses has a negative impact on those uses.
73 #define dns64_bis_return_excluded_addresses 1
76 /*% Partial answer? */
77 #define PARTIALANSWER(c) (((c)->query.attributes & \
78 NS_QUERYATTR_PARTIALANSWER) != 0)
80 #define USECACHE(c) (((c)->query.attributes & \
81 NS_QUERYATTR_CACHEOK) != 0)
83 #define RECURSIONOK(c) (((c)->query.attributes & \
84 NS_QUERYATTR_RECURSIONOK) != 0)
86 #define RECURSING(c) (((c)->query.attributes & \
87 NS_QUERYATTR_RECURSING) != 0)
89 #define CACHEGLUEOK(c) (((c)->query.attributes & \
90 NS_QUERYATTR_CACHEGLUEOK) != 0)
91 /*% Want Recursion? */
92 #define WANTRECURSION(c) (((c)->query.attributes & \
93 NS_QUERYATTR_WANTRECURSION) != 0)
95 #define TCP(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
98 #define WANTDNSSEC(c) (((c)->attributes & \
99 NS_CLIENTATTR_WANTDNSSEC) != 0)
101 #define WANTAD(c) (((c)->attributes & \
102 NS_CLIENTATTR_WANTAD) != 0)
105 #define NOAUTHORITY(c) (((c)->query.attributes & \
106 NS_QUERYATTR_NOAUTHORITY) != 0)
107 /*% No additional? */
108 #define NOADDITIONAL(c) (((c)->query.attributes & \
109 NS_QUERYATTR_NOADDITIONAL) != 0)
111 #define SECURE(c) (((c)->query.attributes & \
112 NS_QUERYATTR_SECURE) != 0)
113 /*% DNS64 A lookup? */
114 #define DNS64(c) (((c)->query.attributes & \
115 NS_QUERYATTR_DNS64) != 0)
117 #define DNS64EXCLUDE(c) (((c)->query.attributes & \
118 NS_QUERYATTR_DNS64EXCLUDE) != 0)
120 /*% No QNAME Proof? */
121 #define NOQNAME(r) (((r)->attributes & \
122 DNS_RDATASETATTR_NOQNAME) != 0)
124 #ifdef WANT_QUERYTRACE
126 client_trace(ns_client_t *client, int level, const char *message) {
127 if (client != NULL && client->query.qname != NULL) {
128 if (isc_log_wouldlog(ns_g_lctx, level)) {
129 char qbuf[DNS_NAME_FORMATSIZE];
130 char tbuf[DNS_RDATATYPE_FORMATSIZE];
131 dns_name_format(client->query.qname,
133 dns_rdatatype_format(client->query.qtype,
135 isc_log_write(ns_g_lctx,
136 NS_LOGCATEGORY_CLIENT,
137 NS_LOGMODULE_QUERY, level,
138 "query client=%p thread=0x%lx "
141 (unsigned long) isc_thread_self(),
142 qbuf, tbuf, message);
145 isc_log_write(ns_g_lctx,
146 NS_LOGCATEGORY_CLIENT,
147 NS_LOGMODULE_QUERY, level,
148 "query client=%p thread=0x%lx "
149 "(<unknown-query>): %s",
151 (unsigned long) isc_thread_self(),
155 #define CTRACE(l,m) client_trace(client, l, m)
157 #define CTRACE(l,m) ((void)m)
158 #endif /* WANT_QUERYTRACE */
161 #define DNS_GETDB_NOEXACT 0x01U
162 #define DNS_GETDB_NOLOG 0x02U
163 #define DNS_GETDB_PARTIAL 0x04U
164 #define DNS_GETDB_IGNOREACL 0x08U
166 #define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0)
168 typedef struct client_additionalctx {
170 dns_rdataset_t *rdataset;
171 } client_additionalctx_t;
174 query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
177 validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
178 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
181 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
182 dns_dbversion_t *version, ns_client_t *client,
183 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
184 dns_name_t *fname, isc_boolean_t exact,
188 log_queryerror(ns_client_t *client, isc_result_t result, int line, int level);
191 rpz_st_clear(ns_client_t *client);
194 * Increment query statistics counters.
197 inc_stats(ns_client_t *client, isc_statscounter_t counter) {
198 dns_zone_t *zone = client->query.authzone;
199 isc_stats_t *zonestats;
201 dns_rdatatype_t qtype;
202 dns_rdataset_t *rdataset;
203 dns_stats_t *querystats = NULL;
206 isc_stats_increment(ns_g_server->nsstats, counter);
211 /* Do regular response type stats */
212 zonestats = dns_zone_getrequeststats(zone);
214 if (zonestats != NULL)
215 isc_stats_increment(zonestats, counter);
218 /* Do query type statistics
220 * We only increment per-type if we're using the authoritative
221 * answer counter, preventing double-counting.
223 if (counter == dns_nsstatscounter_authans) {
224 querystats = dns_zone_getrcvquerystats(zone);
225 if (querystats != NULL) {
226 rdataset = ISC_LIST_HEAD(client->query.qname->list);
227 if (rdataset != NULL) {
228 qtype = rdataset->type;
229 dns_rdatatypestats_increment(querystats, qtype);
237 query_send(ns_client_t *client) {
238 isc_statscounter_t counter;
240 if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0)
241 inc_stats(client, dns_nsstatscounter_nonauthans);
243 inc_stats(client, dns_nsstatscounter_authans);
245 if (client->message->rcode == dns_rcode_noerror) {
246 dns_section_t answer = DNS_SECTION_ANSWER;
247 if (ISC_LIST_EMPTY(client->message->sections[answer])) {
248 if (client->query.isreferral)
249 counter = dns_nsstatscounter_referral;
251 counter = dns_nsstatscounter_nxrrset;
253 counter = dns_nsstatscounter_success;
254 } else if (client->message->rcode == dns_rcode_nxdomain)
255 counter = dns_nsstatscounter_nxdomain;
256 else /* We end up here in case of YXDOMAIN, and maybe others */
257 counter = dns_nsstatscounter_failure;
259 inc_stats(client, counter);
260 ns_client_send(client);
264 query_error(ns_client_t *client, isc_result_t result, int line) {
265 int loglevel = ISC_LOG_DEBUG(3);
269 loglevel = ISC_LOG_DEBUG(1);
270 inc_stats(client, dns_nsstatscounter_servfail);
273 inc_stats(client, dns_nsstatscounter_formerr);
276 inc_stats(client, dns_nsstatscounter_failure);
280 log_queryerror(client, result, line, loglevel);
282 ns_client_error(client, result);
286 query_next(ns_client_t *client, isc_result_t result) {
287 if (result == DNS_R_DUPLICATE)
288 inc_stats(client, dns_nsstatscounter_duplicate);
289 else if (result == DNS_R_DROP)
290 inc_stats(client, dns_nsstatscounter_dropped);
292 inc_stats(client, dns_nsstatscounter_failure);
293 ns_client_next(client, result);
297 query_freefreeversions(ns_client_t *client, isc_boolean_t everything) {
298 ns_dbversion_t *dbversion, *dbversion_next;
301 for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
303 dbversion = dbversion_next, i++)
305 dbversion_next = ISC_LIST_NEXT(dbversion, link);
307 * If we're not freeing everything, we keep the first three
308 * dbversions structures around.
310 if (i > 3 || everything) {
311 ISC_LIST_UNLINK(client->query.freeversions, dbversion,
313 isc_mem_put(client->mctx, dbversion,
320 ns_query_cancel(ns_client_t *client) {
321 LOCK(&client->query.fetchlock);
322 if (client->query.fetch != NULL) {
323 dns_resolver_cancelfetch(client->query.fetch);
325 client->query.fetch = NULL;
327 UNLOCK(&client->query.fetchlock);
331 query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
332 dns_rdataset_t *rdataset = *rdatasetp;
334 CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset");
335 if (rdataset != NULL) {
336 if (dns_rdataset_isassociated(rdataset))
337 dns_rdataset_disassociate(rdataset);
338 dns_message_puttemprdataset(client->message, rdatasetp);
340 CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset: done");
344 query_reset(ns_client_t *client, isc_boolean_t everything) {
345 isc_buffer_t *dbuf, *dbuf_next;
346 ns_dbversion_t *dbversion, *dbversion_next;
348 CTRACE(ISC_LOG_DEBUG(3), "query_reset");
351 * Reset the query state of a client to its default state.
355 * Cancel the fetch if it's running.
357 ns_query_cancel(client);
360 * Cleanup any active versions.
362 for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
364 dbversion = dbversion_next) {
365 dbversion_next = ISC_LIST_NEXT(dbversion, link);
366 dns_db_closeversion(dbversion->db, &dbversion->version,
368 dns_db_detach(&dbversion->db);
369 ISC_LIST_INITANDAPPEND(client->query.freeversions,
372 ISC_LIST_INIT(client->query.activeversions);
374 if (client->query.authdb != NULL)
375 dns_db_detach(&client->query.authdb);
376 if (client->query.authzone != NULL)
377 dns_zone_detach(&client->query.authzone);
379 if (client->query.dns64_aaaa != NULL)
380 query_putrdataset(client, &client->query.dns64_aaaa);
381 if (client->query.dns64_sigaaaa != NULL)
382 query_putrdataset(client, &client->query.dns64_sigaaaa);
383 if (client->query.dns64_aaaaok != NULL) {
384 isc_mem_put(client->mctx, client->query.dns64_aaaaok,
385 client->query.dns64_aaaaoklen *
386 sizeof(isc_boolean_t));
387 client->query.dns64_aaaaok = NULL;
388 client->query.dns64_aaaaoklen = 0;
391 query_freefreeversions(client, everything);
393 for (dbuf = ISC_LIST_HEAD(client->query.namebufs);
396 dbuf_next = ISC_LIST_NEXT(dbuf, link);
397 if (dbuf_next != NULL || everything) {
398 ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
399 isc_buffer_free(&dbuf);
403 if (client->query.restarts > 0) {
405 * client->query.qname was dynamically allocated.
407 dns_message_puttempname(client->message,
408 &client->query.qname);
410 client->query.qname = NULL;
411 client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
412 NS_QUERYATTR_CACHEOK |
413 NS_QUERYATTR_SECURE);
414 client->query.restarts = 0;
415 client->query.timerset = ISC_FALSE;
416 if (client->query.rpz_st != NULL) {
417 rpz_st_clear(client);
419 isc_mem_put(client->mctx, client->query.rpz_st,
420 sizeof(*client->query.rpz_st));
421 client->query.rpz_st = NULL;
424 client->query.origqname = NULL;
425 client->query.dboptions = 0;
426 client->query.fetchoptions = 0;
427 client->query.gluedb = NULL;
428 client->query.authdbset = ISC_FALSE;
429 client->query.isreferral = ISC_FALSE;
430 client->query.dns64_options = 0;
431 client->query.dns64_ttl = ISC_UINT32_MAX;
435 query_next_callback(ns_client_t *client) {
436 query_reset(client, ISC_FALSE);
440 ns_query_free(ns_client_t *client) {
441 query_reset(client, ISC_TRUE);
444 static inline isc_result_t
445 query_newnamebuf(ns_client_t *client) {
449 CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf");
451 * Allocate a name buffer.
455 result = isc_buffer_allocate(client->mctx, &dbuf, 1024);
456 if (result != ISC_R_SUCCESS) {
457 CTRACE(ISC_LOG_DEBUG(3),
458 "query_newnamebuf: isc_buffer_allocate failed: done");
461 ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
463 CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf: done");
464 return (ISC_R_SUCCESS);
467 static inline isc_buffer_t *
468 query_getnamebuf(ns_client_t *client) {
473 CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf");
475 * Return a name buffer with space for a maximal name, allocating
476 * a new one if necessary.
479 if (ISC_LIST_EMPTY(client->query.namebufs)) {
480 result = query_newnamebuf(client);
481 if (result != ISC_R_SUCCESS) {
482 CTRACE(ISC_LOG_DEBUG(3),
483 "query_getnamebuf: query_newnamebuf failed: done");
488 dbuf = ISC_LIST_TAIL(client->query.namebufs);
489 INSIST(dbuf != NULL);
490 isc_buffer_availableregion(dbuf, &r);
491 if (r.length < DNS_NAME_MAXWIRE) {
492 result = query_newnamebuf(client);
493 if (result != ISC_R_SUCCESS) {
494 CTRACE(ISC_LOG_DEBUG(3),
495 "query_getnamebuf: query_newnamebuf failed: done");
499 dbuf = ISC_LIST_TAIL(client->query.namebufs);
500 isc_buffer_availableregion(dbuf, &r);
501 INSIST(r.length >= 255);
503 CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf: done");
508 query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
511 CTRACE(ISC_LOG_DEBUG(3), "query_keepname");
513 * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
514 * adjusted to take account of that. We do the adjustment.
517 REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
519 dns_name_toregion(name, &r);
520 isc_buffer_add(dbuf, r.length);
521 dns_name_setbuffer(name, NULL);
522 client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
526 query_releasename(ns_client_t *client, dns_name_t **namep) {
527 dns_name_t *name = *namep;
530 * 'name' is no longer needed. Return it to our pool of temporary
531 * names. If it is using a name buffer, relinquish its exclusive
532 * rights on the buffer.
535 CTRACE(ISC_LOG_DEBUG(3), "query_releasename");
536 if (dns_name_hasbuffer(name)) {
537 INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
539 client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
541 dns_message_puttempname(client->message, namep);
542 CTRACE(ISC_LOG_DEBUG(3), "query_releasename: done");
545 static inline dns_name_t *
546 query_newname(ns_client_t *client, isc_buffer_t *dbuf,
553 REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
555 CTRACE(ISC_LOG_DEBUG(3), "query_newname");
557 result = dns_message_gettempname(client->message, &name);
558 if (result != ISC_R_SUCCESS) {
559 CTRACE(ISC_LOG_DEBUG(3),
560 "query_newname: dns_message_gettempname failed: done");
563 isc_buffer_availableregion(dbuf, &r);
564 isc_buffer_init(nbuf, r.base, r.length);
565 dns_name_init(name, NULL);
566 dns_name_setbuffer(name, nbuf);
567 client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
569 CTRACE(ISC_LOG_DEBUG(3), "query_newname: done");
573 static inline dns_rdataset_t *
574 query_newrdataset(ns_client_t *client) {
575 dns_rdataset_t *rdataset;
578 CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset");
580 result = dns_message_gettemprdataset(client->message, &rdataset);
581 if (result != ISC_R_SUCCESS) {
582 CTRACE(ISC_LOG_DEBUG(3),
583 "query_newrdataset: "
584 "dns_message_gettemprdataset failed: done");
587 dns_rdataset_init(rdataset);
589 CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset: done");
593 static inline isc_result_t
594 query_newdbversion(ns_client_t *client, unsigned int n) {
596 ns_dbversion_t *dbversion;
598 for (i = 0; i < n; i++) {
599 dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
600 if (dbversion != NULL) {
601 dbversion->db = NULL;
602 dbversion->version = NULL;
603 ISC_LIST_INITANDAPPEND(client->query.freeversions,
607 * We only return ISC_R_NOMEMORY if we couldn't
611 return (ISC_R_NOMEMORY);
613 return (ISC_R_SUCCESS);
617 return (ISC_R_SUCCESS);
620 static inline ns_dbversion_t *
621 query_getdbversion(ns_client_t *client) {
623 ns_dbversion_t *dbversion;
625 if (ISC_LIST_EMPTY(client->query.freeversions)) {
626 result = query_newdbversion(client, 1);
627 if (result != ISC_R_SUCCESS)
630 dbversion = ISC_LIST_HEAD(client->query.freeversions);
631 INSIST(dbversion != NULL);
632 ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
638 ns_query_init(ns_client_t *client) {
641 ISC_LIST_INIT(client->query.namebufs);
642 ISC_LIST_INIT(client->query.activeversions);
643 ISC_LIST_INIT(client->query.freeversions);
644 client->query.restarts = 0;
645 client->query.timerset = ISC_FALSE;
646 client->query.rpz_st = NULL;
647 client->query.qname = NULL;
649 * This mutex is destroyed when the client is destroyed in
652 result = isc_mutex_init(&client->query.fetchlock);
653 if (result != ISC_R_SUCCESS)
655 client->query.fetch = NULL;
656 client->query.authdb = NULL;
657 client->query.authzone = NULL;
658 client->query.authdbset = ISC_FALSE;
659 client->query.isreferral = ISC_FALSE;
660 client->query.dns64_aaaa = NULL;
661 client->query.dns64_sigaaaa = NULL;
662 client->query.dns64_aaaaok = NULL;
663 client->query.dns64_aaaaoklen = 0;
664 query_reset(client, ISC_FALSE);
665 result = query_newdbversion(client, 3);
666 if (result != ISC_R_SUCCESS) {
667 DESTROYLOCK(&client->query.fetchlock);
670 result = query_newnamebuf(client);
671 if (result != ISC_R_SUCCESS) {
672 query_freefreeversions(client, ISC_TRUE);
673 DESTROYLOCK(&client->query.fetchlock);
679 static inline ns_dbversion_t *
680 query_findversion(ns_client_t *client, dns_db_t *db)
682 ns_dbversion_t *dbversion;
685 * We may already have done a query related to this
686 * database. If so, we must be sure to make subsequent
687 * queries from the same version.
689 for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
691 dbversion = ISC_LIST_NEXT(dbversion, link)) {
692 if (dbversion->db == db)
696 if (dbversion == NULL) {
698 * This is a new zone for this query. Add it to
701 dbversion = query_getdbversion(client);
702 if (dbversion == NULL)
704 dns_db_attach(db, &dbversion->db);
705 dns_db_currentversion(db, &dbversion->version);
706 dbversion->acl_checked = ISC_FALSE;
707 dbversion->queryok = ISC_FALSE;
708 ISC_LIST_APPEND(client->query.activeversions,
715 static inline isc_result_t
716 query_validatezonedb(ns_client_t *client, dns_name_t *name,
717 dns_rdatatype_t qtype, unsigned int options,
718 dns_zone_t *zone, dns_db_t *db,
719 dns_dbversion_t **versionp)
722 dns_acl_t *queryacl, *queryonacl;
723 ns_dbversion_t *dbversion;
725 REQUIRE(zone != NULL);
729 * This limits our searching to the zone where the first name
730 * (the query target) was looked for. This prevents following
731 * CNAMES or DNAMES into other zones and prevents returning
732 * additional data from other zones.
734 if (!client->view->additionalfromauth &&
735 client->query.authdbset &&
736 db != client->query.authdb)
737 return (DNS_R_REFUSED);
740 * Non recursive query to a static-stub zone is prohibited; its
741 * zone content is not public data, but a part of local configuration
742 * and should not be disclosed.
744 if (dns_zone_gettype(zone) == dns_zone_staticstub &&
745 !RECURSIONOK(client)) {
746 return (DNS_R_REFUSED);
750 * If the zone has an ACL, we'll check it, otherwise
751 * we use the view's "allow-query" ACL. Each ACL is only checked
754 * Also, get the database version to use.
758 * Get the current version of this database.
760 dbversion = query_findversion(client, db);
761 if (dbversion == NULL) {
762 CTRACE(ISC_LOG_ERROR, "unable to get db version");
763 return (DNS_R_SERVFAIL);
766 if ((options & DNS_GETDB_IGNOREACL) != 0)
768 if (dbversion->acl_checked) {
769 if (!dbversion->queryok)
770 return (DNS_R_REFUSED);
774 queryacl = dns_zone_getqueryacl(zone);
775 if (queryacl == NULL) {
776 queryacl = client->view->queryacl;
777 if ((client->query.attributes &
778 NS_QUERYATTR_QUERYOKVALID) != 0) {
780 * We've evaluated the view's queryacl already. If
781 * NS_QUERYATTR_QUERYOK is set, then the client is
782 * allowed to make queries, otherwise the query should
785 dbversion->acl_checked = ISC_TRUE;
786 if ((client->query.attributes &
787 NS_QUERYATTR_QUERYOK) == 0) {
788 dbversion->queryok = ISC_FALSE;
789 return (DNS_R_REFUSED);
791 dbversion->queryok = ISC_TRUE;
796 result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE);
797 if ((options & DNS_GETDB_NOLOG) == 0) {
798 char msg[NS_CLIENT_ACLMSGSIZE("query")];
799 if (result == ISC_R_SUCCESS) {
800 if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) {
801 ns_client_aclmsg("query", name, qtype,
802 client->view->rdclass,
804 ns_client_log(client,
805 DNS_LOGCATEGORY_SECURITY,
811 ns_client_aclmsg("query", name, qtype,
812 client->view->rdclass,
814 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
815 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
820 if (queryacl == client->view->queryacl) {
821 if (result == ISC_R_SUCCESS) {
823 * We were allowed by the default
824 * "allow-query" ACL. Remember this so we
825 * don't have to check again.
827 client->query.attributes |= NS_QUERYATTR_QUERYOK;
830 * We've now evaluated the view's query ACL, and
831 * the NS_QUERYATTR_QUERYOK attribute is now valid.
833 client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
836 /* If and only if we've gotten this far, check allow-query-on too */
837 if (result == ISC_R_SUCCESS) {
838 queryonacl = dns_zone_getqueryonacl(zone);
839 if (queryonacl == NULL)
840 queryonacl = client->view->queryonacl;
842 result = ns_client_checkaclsilent(client, &client->destaddr,
843 queryonacl, ISC_TRUE);
844 if ((options & DNS_GETDB_NOLOG) == 0 &&
845 result != ISC_R_SUCCESS)
846 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
847 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
851 dbversion->acl_checked = ISC_TRUE;
852 if (result != ISC_R_SUCCESS) {
853 dbversion->queryok = ISC_FALSE;
854 return (DNS_R_REFUSED);
856 dbversion->queryok = ISC_TRUE;
859 /* Transfer ownership, if necessary. */
860 if (versionp != NULL)
861 *versionp = dbversion->version;
862 return (ISC_R_SUCCESS);
865 static inline isc_result_t
866 query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
867 unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
868 dns_dbversion_t **versionp)
871 unsigned int ztoptions;
872 dns_zone_t *zone = NULL;
874 isc_boolean_t partial = ISC_FALSE;
876 REQUIRE(zonep != NULL && *zonep == NULL);
877 REQUIRE(dbp != NULL && *dbp == NULL);
880 * Find a zone database to answer the query.
882 ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?
883 DNS_ZTFIND_NOEXACT : 0;
885 result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
887 if (result == DNS_R_PARTIALMATCH)
889 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
890 result = dns_zone_getdb(zone, &db);
892 if (result != ISC_R_SUCCESS)
895 result = query_validatezonedb(client, name, qtype, options, zone, db,
898 if (result != ISC_R_SUCCESS)
901 /* Transfer ownership. */
905 if (partial && (options & DNS_GETDB_PARTIAL) != 0)
906 return (DNS_R_PARTIALMATCH);
907 return (ISC_R_SUCCESS);
911 dns_zone_detach(&zone);
919 rpz_log_rewrite(ns_client_t *client, isc_boolean_t disabled,
920 dns_rpz_policy_t policy, dns_rpz_type_t type,
921 dns_zone_t *zone, dns_name_t *rpz_qname)
923 isc_stats_t *zonestats;
924 char qname_buf[DNS_NAME_FORMATSIZE];
925 char rpz_qname_buf[DNS_NAME_FORMATSIZE];
928 * Count enabled rewrites in the global counter.
929 * Count both enabled and disabled rewrites for each zone.
931 if (!disabled && policy != DNS_RPZ_POLICY_PASSTHRU) {
932 isc_stats_increment(ns_g_server->nsstats,
933 dns_nsstatscounter_rpz_rewrites);
936 zonestats = dns_zone_getrequeststats(zone);
937 if (zonestats != NULL)
938 isc_stats_increment(zonestats,
939 dns_nsstatscounter_rpz_rewrites);
942 if (!isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL))
945 dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf));
946 dns_name_format(rpz_qname, rpz_qname_buf, sizeof(rpz_qname_buf));
948 ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY,
949 DNS_RPZ_INFO_LEVEL, "%srpz %s %s rewrite %s via %s",
950 disabled ? "disabled " : "",
951 dns_rpz_type2str(type), dns_rpz_policy2str(policy),
952 qname_buf, rpz_qname_buf);
956 rpz_log_fail(ns_client_t *client, int level,
957 dns_rpz_type_t rpz_type, dns_name_t *name,
958 const char *str, isc_result_t result)
960 char namebuf1[DNS_NAME_FORMATSIZE];
961 char namebuf2[DNS_NAME_FORMATSIZE];
963 if (!isc_log_wouldlog(ns_g_lctx, level))
967 * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
969 dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1));
970 dns_name_format(name, namebuf2, sizeof(namebuf2));
971 ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS,
972 NS_LOGMODULE_QUERY, level,
973 "rpz %s rewrite %s via %s %sfailed: %s",
974 dns_rpz_type2str(rpz_type),
975 namebuf1, namebuf2, str, isc_result_totext(result));
979 * Get a policy rewrite zone database.
982 rpz_getdb(ns_client_t *client, dns_rpz_type_t rpz_type, dns_name_t *rpz_qname,
983 dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp)
985 char namebuf1[DNS_NAME_FORMATSIZE];
986 char namebuf2[DNS_NAME_FORMATSIZE];
987 dns_dbversion_t *rpz_version = NULL;
990 result = query_getzonedb(client, rpz_qname, dns_rdatatype_any,
991 DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version);
992 if (result == ISC_R_SUCCESS) {
993 if (isc_log_wouldlog(ns_g_lctx, DNS_RPZ_DEBUG_LEVEL2)) {
994 dns_name_format(client->query.qname, namebuf1,
996 dns_name_format(rpz_qname, namebuf2, sizeof(namebuf2));
997 ns_client_log(client, DNS_LOGCATEGORY_RPZ,
998 NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2,
999 "try rpz %s rewrite %s via %s",
1000 dns_rpz_type2str(rpz_type),
1001 namebuf1, namebuf2);
1003 *versionp = rpz_version;
1004 return (ISC_R_SUCCESS);
1006 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, rpz_qname,
1007 "query_getzonedb() ", result);
1011 static inline isc_result_t
1012 query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
1013 dns_db_t **dbp, unsigned int options)
1015 isc_result_t result;
1016 isc_boolean_t check_acl;
1017 dns_db_t *db = NULL;
1019 REQUIRE(dbp != NULL && *dbp == NULL);
1022 * Find a cache database to answer the query.
1023 * This may fail with DNS_R_REFUSED if the client
1024 * is not allowed to use the cache.
1027 if (!USECACHE(client))
1028 return (DNS_R_REFUSED);
1029 dns_db_attach(client->view->cachedb, &db);
1031 if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) != 0) {
1033 * We've evaluated the view's cacheacl already. If
1034 * NS_QUERYATTR_CACHEACLOK is set, then the client is
1035 * allowed to make queries, otherwise the query should
1038 check_acl = ISC_FALSE;
1039 if ((client->query.attributes & NS_QUERYATTR_CACHEACLOK) == 0)
1043 * We haven't evaluated the view's queryacl yet.
1045 check_acl = ISC_TRUE;
1049 isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);
1050 char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
1052 result = ns_client_checkaclsilent(client, NULL,
1053 client->view->cacheacl,
1055 if (result == ISC_R_SUCCESS) {
1057 * We were allowed by the "allow-query-cache" ACL.
1058 * Remember this so we don't have to check again.
1060 client->query.attributes |=
1061 NS_QUERYATTR_CACHEACLOK;
1062 if (log && isc_log_wouldlog(ns_g_lctx,
1065 ns_client_aclmsg("query (cache)", name, qtype,
1066 client->view->rdclass,
1068 ns_client_log(client,
1069 DNS_LOGCATEGORY_SECURITY,
1072 "%s approved", msg);
1075 ns_client_aclmsg("query (cache)", name, qtype,
1076 client->view->rdclass, msg,
1078 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1079 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
1083 * We've now evaluated the view's query ACL, and
1084 * the NS_QUERYATTR_CACHEACLOKVALID attribute is now valid.
1086 client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID;
1088 if (result != ISC_R_SUCCESS)
1094 /* Transfer ownership. */
1097 return (ISC_R_SUCCESS);
1100 result = DNS_R_REFUSED;
1109 static inline isc_result_t
1110 query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
1111 unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
1112 dns_dbversion_t **versionp, isc_boolean_t *is_zonep)
1114 isc_result_t result;
1116 isc_result_t tresult;
1117 unsigned int namelabels;
1118 unsigned int zonelabels;
1119 dns_zone_t *zone = NULL;
1122 REQUIRE(zonep != NULL && *zonep == NULL);
1126 /* Calculate how many labels are in name. */
1127 namelabels = dns_name_countlabels(name);
1130 /* Try to find name in bind's standard database. */
1131 result = query_getzonedb(client, name, qtype, options, &zone,
1134 /* See how many labels are in the zone's name. */
1135 if (result == ISC_R_SUCCESS && zone != NULL)
1136 zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));
1138 * If # zone labels < # name labels, try to find an even better match
1139 * Only try if a DLZ driver is loaded for this view
1141 if (zonelabels < namelabels && client->view->dlzdatabase != NULL) {
1142 tresult = dns_dlzfindzone(client->view, name,
1144 /* If we successful, we found a better match. */
1145 if (tresult == ISC_R_SUCCESS) {
1147 * If the previous search returned a zone, detach it.
1150 dns_zone_detach(&zone);
1153 * If the previous search returned a database,
1160 * If the previous search returned a version, clear it.
1165 * Get our database version.
1167 dns_db_currentversion(tdbp, versionp);
1170 * Be sure to return our database.
1175 * We return a null zone, No stats for DLZ zones.
1182 /* If successful, Transfer ownership of zone. */
1183 if (result == ISC_R_SUCCESS) {
1186 * If neither attempt above succeeded, return the cache instead
1188 *is_zonep = ISC_TRUE;
1189 } else if (result == ISC_R_NOTFOUND) {
1190 result = query_getcachedb(client, name, qtype, dbp, options);
1191 *is_zonep = ISC_FALSE;
1196 static inline isc_boolean_t
1197 query_isduplicate(ns_client_t *client, dns_name_t *name,
1198 dns_rdatatype_t type, dns_name_t **mnamep)
1200 dns_section_t section;
1201 dns_name_t *mname = NULL;
1202 isc_result_t result;
1204 CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate");
1206 for (section = DNS_SECTION_ANSWER;
1207 section <= DNS_SECTION_ADDITIONAL;
1209 result = dns_message_findname(client->message, section,
1210 name, type, 0, &mname, NULL);
1211 if (result == ISC_R_SUCCESS) {
1213 * We've already got this RRset in the response.
1215 CTRACE(ISC_LOG_DEBUG(3),
1216 "query_isduplicate: true: done");
1218 } else if (result == DNS_R_NXRRSET) {
1220 * The name exists, but the rdataset does not.
1222 if (section == DNS_SECTION_ADDITIONAL)
1225 RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
1232 CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: false: done");
1237 query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
1238 ns_client_t *client = arg;
1239 isc_result_t result, eresult;
1242 dns_name_t *fname, *mname;
1243 dns_rdataset_t *rdataset, *sigrdataset, *trdataset;
1246 dns_dbversion_t *version;
1247 isc_boolean_t added_something, need_addname;
1249 dns_rdatatype_t type;
1250 dns_clientinfomethods_t cm;
1251 dns_clientinfo_t ci;
1253 REQUIRE(NS_CLIENT_VALID(client));
1254 REQUIRE(qtype != dns_rdatatype_any);
1256 if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))
1257 return (ISC_R_SUCCESS);
1259 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional");
1264 eresult = ISC_R_SUCCESS;
1272 added_something = ISC_FALSE;
1273 need_addname = ISC_FALSE;
1276 dns_clientinfomethods_init(&cm, ns_client_sourceip);
1277 dns_clientinfo_init(&ci, client);
1280 * We treat type A additional section processing as if it
1281 * were "any address type" additional section processing.
1282 * To avoid multiple lookups, we do an 'any' database
1283 * lookup and iterate over the node.
1285 if (qtype == dns_rdatatype_a)
1286 type = dns_rdatatype_any;
1291 * Get some resources.
1293 dbuf = query_getnamebuf(client);
1296 fname = query_newname(client, dbuf, &b);
1297 rdataset = query_newrdataset(client);
1298 if (fname == NULL || rdataset == NULL)
1300 if (WANTDNSSEC(client)) {
1301 sigrdataset = query_newrdataset(client);
1302 if (sigrdataset == NULL)
1307 * Look for a zone database that might contain authoritative
1310 result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
1311 &zone, &db, &version);
1312 if (result != ISC_R_SUCCESS)
1315 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: db_find");
1318 * Since we are looking for authoritative data, we do not set
1319 * the GLUEOK flag. Glue will be looked for later, but not
1320 * necessarily in the same database.
1323 result = dns_db_findext(db, name, version, type,
1324 client->query.dboptions,
1325 client->now, &node, fname, &cm, &ci,
1326 rdataset, sigrdataset);
1327 if (result == ISC_R_SUCCESS) {
1328 if (sigrdataset != NULL && !dns_db_issecure(db) &&
1329 dns_rdataset_isassociated(sigrdataset))
1330 dns_rdataset_disassociate(sigrdataset);
1334 if (dns_rdataset_isassociated(rdataset))
1335 dns_rdataset_disassociate(rdataset);
1336 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
1337 dns_rdataset_disassociate(sigrdataset);
1339 dns_db_detachnode(db, &node);
1344 * No authoritative data was found. The cache is our next best bet.
1348 result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
1349 if (result != ISC_R_SUCCESS)
1351 * Most likely the client isn't allowed to query the cache.
1355 * Attempt to validate glue.
1357 if (sigrdataset == NULL) {
1358 sigrdataset = query_newrdataset(client);
1359 if (sigrdataset == NULL)
1362 result = dns_db_findext(db, name, version, type,
1363 client->query.dboptions |
1364 DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
1365 client->now, &node, fname, &cm, &ci,
1366 rdataset, sigrdataset);
1367 if (result == DNS_R_GLUE &&
1368 validate(client, db, fname, rdataset, sigrdataset))
1369 result = ISC_R_SUCCESS;
1370 if (!WANTDNSSEC(client))
1371 query_putrdataset(client, &sigrdataset);
1372 if (result == ISC_R_SUCCESS)
1375 if (dns_rdataset_isassociated(rdataset))
1376 dns_rdataset_disassociate(rdataset);
1377 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
1378 dns_rdataset_disassociate(sigrdataset);
1380 dns_db_detachnode(db, &node);
1385 * No cached data was found. Glue is our last chance.
1388 * NS records cause both the usual additional section
1389 * processing to locate a type A record, and, when used
1390 * in a referral, a special search of the zone in which
1391 * they reside for glue information.
1393 * This is the "special search". Note that we must search
1394 * the zone where the NS record resides, not the zone it
1395 * points to, and that we only do the search in the delegation
1396 * case (identified by client->query.gluedb being set).
1399 if (client->query.gluedb == NULL)
1403 * Don't poison caches using the bailiwick protection model.
1405 if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
1408 dns_db_attach(client->query.gluedb, &db);
1409 result = dns_db_findext(db, name, version, type,
1410 client->query.dboptions | DNS_DBFIND_GLUEOK,
1411 client->now, &node, fname, &cm, &ci,
1412 rdataset, sigrdataset);
1413 if (!(result == ISC_R_SUCCESS ||
1414 result == DNS_R_ZONECUT ||
1415 result == DNS_R_GLUE))
1420 * We have found a potential additional data rdataset, or
1421 * at least a node to iterate over.
1423 query_keepname(client, fname, dbuf);
1426 * If we have an rdataset, add it to the additional data
1430 if (dns_rdataset_isassociated(rdataset) &&
1431 !query_isduplicate(client, fname, type, &mname)) {
1432 if (mname != NULL) {
1433 INSIST(mname != fname);
1434 query_releasename(client, &fname);
1437 need_addname = ISC_TRUE;
1438 ISC_LIST_APPEND(fname->list, rdataset, link);
1439 trdataset = rdataset;
1441 added_something = ISC_TRUE;
1443 * Note: we only add SIGs if we've added the type they cover,
1444 * so we do not need to check if the SIG rdataset is already
1447 if (sigrdataset != NULL &&
1448 dns_rdataset_isassociated(sigrdataset))
1450 ISC_LIST_APPEND(fname->list, sigrdataset, link);
1455 if (qtype == dns_rdatatype_a) {
1456 #ifdef ALLOW_FILTER_AAAA_ON_V4
1457 isc_boolean_t have_a = ISC_FALSE;
1461 * We now go looking for A and AAAA records, along with
1464 * XXXRTH This code could be more efficient.
1466 if (rdataset != NULL) {
1467 if (dns_rdataset_isassociated(rdataset))
1468 dns_rdataset_disassociate(rdataset);
1470 rdataset = query_newrdataset(client);
1471 if (rdataset == NULL)
1474 if (sigrdataset != NULL) {
1475 if (dns_rdataset_isassociated(sigrdataset))
1476 dns_rdataset_disassociate(sigrdataset);
1477 } else if (WANTDNSSEC(client)) {
1478 sigrdataset = query_newrdataset(client);
1479 if (sigrdataset == NULL)
1482 if (query_isduplicate(client, fname, dns_rdatatype_a, NULL))
1484 result = dns_db_findrdataset(db, node, version,
1487 rdataset, sigrdataset);
1488 if (result == DNS_R_NCACHENXDOMAIN)
1490 if (result == DNS_R_NCACHENXRRSET) {
1491 dns_rdataset_disassociate(rdataset);
1492 if (sigrdataset != NULL &&
1493 dns_rdataset_isassociated(sigrdataset))
1494 dns_rdataset_disassociate(sigrdataset);
1496 if (result == ISC_R_SUCCESS) {
1498 #ifdef ALLOW_FILTER_AAAA_ON_V4
1501 if (!query_isduplicate(client, fname,
1502 dns_rdatatype_a, &mname)) {
1503 if (mname != fname) {
1504 if (mname != NULL) {
1505 query_releasename(client, &fname);
1508 need_addname = ISC_TRUE;
1510 ISC_LIST_APPEND(fname->list, rdataset, link);
1511 added_something = ISC_TRUE;
1512 if (sigrdataset != NULL &&
1513 dns_rdataset_isassociated(sigrdataset))
1515 ISC_LIST_APPEND(fname->list,
1518 query_newrdataset(client);
1520 rdataset = query_newrdataset(client);
1521 if (rdataset == NULL)
1523 if (WANTDNSSEC(client) && sigrdataset == NULL)
1526 dns_rdataset_disassociate(rdataset);
1527 if (sigrdataset != NULL &&
1528 dns_rdataset_isassociated(sigrdataset))
1529 dns_rdataset_disassociate(sigrdataset);
1533 if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
1535 result = dns_db_findrdataset(db, node, version,
1536 dns_rdatatype_aaaa, 0,
1538 rdataset, sigrdataset);
1539 if (result == DNS_R_NCACHENXDOMAIN)
1541 if (result == DNS_R_NCACHENXRRSET) {
1542 dns_rdataset_disassociate(rdataset);
1543 if (sigrdataset != NULL &&
1544 dns_rdataset_isassociated(sigrdataset))
1545 dns_rdataset_disassociate(sigrdataset);
1547 if (result == ISC_R_SUCCESS) {
1550 * There's an A; check whether we're filtering AAAA
1552 #ifdef ALLOW_FILTER_AAAA_ON_V4
1554 (client->filter_aaaa == dns_v4_aaaa_break_dnssec ||
1555 (client->filter_aaaa == dns_v4_aaaa_filter &&
1556 (!WANTDNSSEC(client) || sigrdataset == NULL ||
1557 !dns_rdataset_isassociated(sigrdataset)))))
1560 if (!query_isduplicate(client, fname,
1561 dns_rdatatype_aaaa, &mname)) {
1562 if (mname != fname) {
1563 if (mname != NULL) {
1564 query_releasename(client, &fname);
1567 need_addname = ISC_TRUE;
1569 ISC_LIST_APPEND(fname->list, rdataset, link);
1570 added_something = ISC_TRUE;
1571 if (sigrdataset != NULL &&
1572 dns_rdataset_isassociated(sigrdataset))
1574 ISC_LIST_APPEND(fname->list,
1584 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: addname");
1586 * If we haven't added anything, then we're done.
1588 if (!added_something)
1592 * We may have added our rdatasets to an existing name, if so, then
1593 * need_addname will be ISC_FALSE. Whether we used an existing name
1594 * or a new one, we must set fname to NULL to prevent cleanup.
1597 dns_message_addname(client->message, fname,
1598 DNS_SECTION_ADDITIONAL);
1602 * In a few cases, we want to add additional data for additional
1603 * data. It's simpler to just deal with special cases here than
1604 * to try to create a general purpose mechanism and allow the
1605 * rdata implementations to do it themselves.
1607 * This involves recursion, but the depth is limited. The
1608 * most complex case is adding a SRV rdataset, which involves
1609 * recursing to add address records, which in turn can cause
1610 * recursion to add KEYs.
1612 if (type == dns_rdatatype_srv && trdataset != NULL) {
1614 * If we're adding SRV records to the additional data
1615 * section, it's helpful if we add the SRV additional data
1618 eresult = dns_rdataset_additionaldata(trdataset,
1619 query_addadditional,
1624 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: cleanup");
1625 query_putrdataset(client, &rdataset);
1626 if (sigrdataset != NULL)
1627 query_putrdataset(client, &sigrdataset);
1629 query_releasename(client, &fname);
1631 dns_db_detachnode(db, &node);
1635 dns_zone_detach(&zone);
1637 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: done");
1642 query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base,
1643 dns_rdatasetadditional_t additionaltype,
1644 dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp,
1645 dns_dbversion_t **versionp, dns_dbnode_t **nodep,
1648 dns_rdataset_t *rdataset;
1650 while ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) {
1651 ISC_LIST_UNLINK(fname->list, rdataset, link);
1652 query_putrdataset(client, &rdataset);
1654 if (*versionp != NULL)
1655 dns_db_closeversion(*dbp, versionp, ISC_FALSE);
1657 dns_db_detachnode(*dbp, nodep);
1661 dns_zone_detach(zonep);
1662 (void)dns_rdataset_putadditional(client->view->acache, rdataset_base,
1663 additionaltype, type);
1666 static inline isc_result_t
1667 query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0,
1668 dns_dbversion_t *version)
1670 isc_result_t result = ISC_R_SUCCESS;
1671 dns_dbversion_t *version_current = NULL;
1672 dns_db_t *db_current = db0;
1674 if (db_current == NULL) {
1675 result = dns_zone_getdb(zone, &db_current);
1676 if (result != ISC_R_SUCCESS)
1679 dns_db_currentversion(db_current, &version_current);
1680 if (db_current != db || version_current != version) {
1681 result = ISC_R_FAILURE;
1686 dns_db_closeversion(db_current, &version_current, ISC_FALSE);
1687 if (db0 == NULL && db_current != NULL)
1688 dns_db_detach(&db_current);
1694 query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
1695 client_additionalctx_t *additionalctx = arg;
1696 dns_rdataset_t *rdataset_base;
1697 ns_client_t *client;
1698 isc_result_t result, eresult;
1699 dns_dbnode_t *node, *cnode;
1701 dns_name_t *fname, *mname0, cfname;
1702 dns_rdataset_t *rdataset, *sigrdataset;
1703 dns_rdataset_t *crdataset, *crdataset_next;
1706 dns_dbversion_t *version, *cversion;
1707 isc_boolean_t added_something, need_addname, needadditionalcache;
1708 isc_boolean_t need_sigrrset;
1710 dns_rdatatype_t type;
1711 dns_rdatasetadditional_t additionaltype;
1712 dns_clientinfomethods_t cm;
1713 dns_clientinfo_t ci;
1716 * If we don't have an additional cache call query_addadditional.
1718 client = additionalctx->client;
1719 REQUIRE(NS_CLIENT_VALID(client));
1721 if (qtype != dns_rdatatype_a || client->view->acache == NULL) {
1723 * This function is optimized for "address" types. For other
1724 * types, use a generic routine.
1725 * XXX: ideally, this function should be generic enough.
1727 return (query_addadditional(additionalctx->client,
1734 rdataset_base = additionalctx->rdataset;
1735 eresult = ISC_R_SUCCESS;
1745 added_something = ISC_FALSE;
1746 need_addname = ISC_FALSE;
1748 needadditionalcache = ISC_FALSE;
1749 POST(needadditionalcache);
1750 additionaltype = dns_rdatasetadditional_fromauth;
1751 dns_name_init(&cfname, NULL);
1752 dns_clientinfomethods_init(&cm, ns_client_sourceip);
1753 dns_clientinfo_init(&ci, client);
1755 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2");
1758 * We treat type A additional section processing as if it
1759 * were "any address type" additional section processing.
1760 * To avoid multiple lookups, we do an 'any' database
1761 * lookup and iterate over the node.
1762 * XXXJT: this approach can cause a suboptimal result when the cache
1763 * DB only has partial address types and the glue DB has remaining
1766 type = dns_rdatatype_any;
1769 * Get some resources.
1771 dbuf = query_getnamebuf(client);
1774 fname = query_newname(client, dbuf, &b);
1777 dns_name_setbuffer(&cfname, &b); /* share the buffer */
1779 /* Check additional cache */
1780 result = dns_rdataset_getadditional(rdataset_base, additionaltype,
1781 type, client->view->acache, &zone,
1782 &cdb, &cversion, &cnode, &cfname,
1783 client->message, client->now);
1784 if (result != ISC_R_SUCCESS)
1787 CTRACE(ISC_LOG_DEBUG(3),
1788 "query_addadditional2: auth zone not found");
1792 /* Is the cached DB up-to-date? */
1793 result = query_iscachevalid(zone, cdb, NULL, cversion);
1794 if (result != ISC_R_SUCCESS) {
1795 CTRACE(ISC_LOG_DEBUG(3),
1796 "query_addadditional2: old auth additional cache");
1797 query_discardcache(client, rdataset_base, additionaltype,
1798 type, &zone, &cdb, &cversion, &cnode,
1803 if (cnode == NULL) {
1805 * We have a negative cache. We don't have to check the zone
1806 * ACL, since the result (not using this zone) would be same
1807 * regardless of the result.
1809 CTRACE(ISC_LOG_DEBUG(3),
1810 "query_addadditional2: negative auth additional cache");
1811 dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1812 dns_db_detach(&cdb);
1813 dns_zone_detach(&zone);
1817 result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG,
1819 if (result != ISC_R_SUCCESS) {
1820 query_discardcache(client, rdataset_base, additionaltype,
1821 type, &zone, &cdb, &cversion, &cnode,
1826 /* We've got an active cache. */
1827 CTRACE(ISC_LOG_DEBUG(3),
1828 "query_addadditional2: auth additional cache");
1829 dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1832 dns_name_clone(&cfname, fname);
1833 query_keepname(client, fname, dbuf);
1837 * Look for a zone database that might contain authoritative
1841 result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
1842 &zone, &db, &version);
1843 if (result != ISC_R_SUCCESS) {
1844 /* Cache the negative result */
1845 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1846 type, client->view->acache,
1847 NULL, NULL, NULL, NULL,
1852 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: db_find");
1855 * Since we are looking for authoritative data, we do not set
1856 * the GLUEOK flag. Glue will be looked for later, but not
1857 * necessarily in the same database.
1860 result = dns_db_findext(db, name, version, type,
1861 client->query.dboptions,
1862 client->now, &node, fname, &cm, &ci,
1864 if (result == ISC_R_SUCCESS)
1867 /* Cache the negative result */
1868 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1869 type, client->view->acache, zone, db,
1870 version, NULL, fname);
1873 dns_db_detachnode(db, &node);
1878 * No authoritative data was found. The cache is our next best bet.
1882 additionaltype = dns_rdatasetadditional_fromcache;
1883 result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
1884 if (result != ISC_R_SUCCESS)
1886 * Most likely the client isn't allowed to query the cache.
1890 result = dns_db_findext(db, name, version, type,
1891 client->query.dboptions |
1892 DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
1893 client->now, &node, fname, &cm, &ci,
1895 if (result == ISC_R_SUCCESS)
1899 dns_db_detachnode(db, &node);
1904 * No cached data was found. Glue is our last chance.
1907 * NS records cause both the usual additional section
1908 * processing to locate a type A record, and, when used
1909 * in a referral, a special search of the zone in which
1910 * they reside for glue information.
1912 * This is the "special search". Note that we must search
1913 * the zone where the NS record resides, not the zone it
1914 * points to, and that we only do the search in the delegation
1915 * case (identified by client->query.gluedb being set).
1917 if (client->query.gluedb == NULL)
1921 * Don't poison caches using the bailiwick protection model.
1923 if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
1926 /* Check additional cache */
1927 additionaltype = dns_rdatasetadditional_fromglue;
1928 result = dns_rdataset_getadditional(rdataset_base, additionaltype,
1929 type, client->view->acache, NULL,
1930 &cdb, &cversion, &cnode, &cfname,
1931 client->message, client->now);
1932 if (result != ISC_R_SUCCESS)
1935 result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion);
1936 if (result != ISC_R_SUCCESS) {
1937 CTRACE(ISC_LOG_DEBUG(3),
1938 "query_addadditional2: old glue additional cache");
1939 query_discardcache(client, rdataset_base, additionaltype,
1940 type, &zone, &cdb, &cversion, &cnode,
1945 if (cnode == NULL) {
1946 /* We have a negative cache. */
1947 CTRACE(ISC_LOG_DEBUG(3),
1948 "query_addadditional2: negative glue additional cache");
1949 dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1950 dns_db_detach(&cdb);
1955 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: glue additional cache");
1956 dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1959 dns_name_clone(&cfname, fname);
1960 query_keepname(client, fname, dbuf);
1964 dns_db_attach(client->query.gluedb, &db);
1965 result = dns_db_findext(db, name, version, type,
1966 client->query.dboptions | DNS_DBFIND_GLUEOK,
1967 client->now, &node, fname, &cm, &ci,
1969 if (!(result == ISC_R_SUCCESS ||
1970 result == DNS_R_ZONECUT ||
1971 result == DNS_R_GLUE)) {
1972 /* cache the negative result */
1973 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1974 type, client->view->acache,
1975 NULL, db, version, NULL,
1982 * We have found a DB node to iterate over from a DB.
1983 * We are going to look for address RRsets (i.e., A and AAAA) in the DB
1984 * node we've just found. We'll then store the complete information
1985 * in the additional data cache.
1987 dns_name_clone(fname, &cfname);
1988 query_keepname(client, fname, dbuf);
1989 needadditionalcache = ISC_TRUE;
1991 rdataset = query_newrdataset(client);
1992 if (rdataset == NULL)
1995 sigrdataset = query_newrdataset(client);
1996 if (sigrdataset == NULL)
1999 if (additionaltype == dns_rdatasetadditional_fromcache &&
2000 query_isduplicate(client, fname, dns_rdatatype_a, NULL))
2003 * Find A RRset with sig RRset. Even if we don't find a sig RRset
2004 * for a client using DNSSEC, we'll continue the process to make a
2005 * complete list to be cached. However, we need to cancel the
2006 * caching when something unexpected happens, in order to avoid
2007 * caching incomplete information.
2009 result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0,
2010 client->now, rdataset, sigrdataset);
2012 * If we can't promote glue/pending from the cache to secure
2015 if (result == ISC_R_SUCCESS &&
2016 additionaltype == dns_rdatasetadditional_fromcache &&
2017 (DNS_TRUST_PENDING(rdataset->trust) ||
2018 DNS_TRUST_GLUE(rdataset->trust)) &&
2019 !validate(client, db, fname, rdataset, sigrdataset)) {
2020 dns_rdataset_disassociate(rdataset);
2021 if (dns_rdataset_isassociated(sigrdataset))
2022 dns_rdataset_disassociate(sigrdataset);
2023 result = ISC_R_NOTFOUND;
2025 if (result == DNS_R_NCACHENXDOMAIN)
2027 if (result == DNS_R_NCACHENXRRSET) {
2028 dns_rdataset_disassociate(rdataset);
2029 if (dns_rdataset_isassociated(sigrdataset))
2030 dns_rdataset_disassociate(sigrdataset);
2032 if (result == ISC_R_SUCCESS) {
2033 /* Remember the result as a cache */
2034 ISC_LIST_APPEND(cfname.list, rdataset, link);
2035 if (dns_rdataset_isassociated(sigrdataset)) {
2036 ISC_LIST_APPEND(cfname.list, sigrdataset, link);
2037 sigrdataset = query_newrdataset(client);
2039 rdataset = query_newrdataset(client);
2040 if (sigrdataset == NULL || rdataset == NULL) {
2041 /* do not cache incomplete information */
2047 if (additionaltype == dns_rdatasetadditional_fromcache &&
2048 query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
2050 /* Find AAAA RRset with sig RRset */
2051 result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa,
2052 0, client->now, rdataset, sigrdataset);
2054 * If we can't promote glue/pending from the cache to secure
2057 if (result == ISC_R_SUCCESS &&
2058 additionaltype == dns_rdatasetadditional_fromcache &&
2059 (DNS_TRUST_PENDING(rdataset->trust) ||
2060 DNS_TRUST_GLUE(rdataset->trust)) &&
2061 !validate(client, db, fname, rdataset, sigrdataset)) {
2062 dns_rdataset_disassociate(rdataset);
2063 if (dns_rdataset_isassociated(sigrdataset))
2064 dns_rdataset_disassociate(sigrdataset);
2065 result = ISC_R_NOTFOUND;
2067 if (result == ISC_R_SUCCESS) {
2068 ISC_LIST_APPEND(cfname.list, rdataset, link);
2070 if (dns_rdataset_isassociated(sigrdataset)) {
2071 ISC_LIST_APPEND(cfname.list, sigrdataset, link);
2078 * Set the new result in the cache if required. We do not support
2079 * caching additional data from a cache DB.
2081 if (needadditionalcache == ISC_TRUE &&
2082 (additionaltype == dns_rdatasetadditional_fromauth ||
2083 additionaltype == dns_rdatasetadditional_fromglue)) {
2084 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
2085 type, client->view->acache,
2086 zone, db, version, node,
2091 need_sigrrset = ISC_FALSE;
2093 for (crdataset = ISC_LIST_HEAD(cfname.list);
2095 crdataset = crdataset_next) {
2098 crdataset_next = ISC_LIST_NEXT(crdataset, link);
2101 if (crdataset->type == dns_rdatatype_a ||
2102 crdataset->type == dns_rdatatype_aaaa) {
2103 if (!query_isduplicate(client, fname, crdataset->type,
2105 if (mname != fname) {
2106 if (mname != NULL) {
2108 * A different type of this name is
2109 * already stored in the additional
2110 * section. We'll reuse the name.
2111 * Note that this should happen at most
2112 * once. Otherwise, fname->link could
2115 INSIST(mname0 == NULL);
2117 query_releasename(client, &fname);
2121 need_addname = ISC_TRUE;
2123 ISC_LIST_UNLINK(cfname.list, crdataset, link);
2124 ISC_LIST_APPEND(fname->list, crdataset, link);
2125 added_something = ISC_TRUE;
2126 need_sigrrset = ISC_TRUE;
2128 need_sigrrset = ISC_FALSE;
2129 } else if (crdataset->type == dns_rdatatype_rrsig &&
2130 need_sigrrset && WANTDNSSEC(client)) {
2131 ISC_LIST_UNLINK(cfname.list, crdataset, link);
2132 ISC_LIST_APPEND(fname->list, crdataset, link);
2133 added_something = ISC_TRUE; /* just in case */
2134 need_sigrrset = ISC_FALSE;
2138 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: addname");
2141 * If we haven't added anything, then we're done.
2143 if (!added_something)
2147 * We may have added our rdatasets to an existing name, if so, then
2148 * need_addname will be ISC_FALSE. Whether we used an existing name
2149 * or a new one, we must set fname to NULL to prevent cleanup.
2152 dns_message_addname(client->message, fname,
2153 DNS_SECTION_ADDITIONAL);
2157 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: cleanup");
2159 if (rdataset != NULL)
2160 query_putrdataset(client, &rdataset);
2161 if (sigrdataset != NULL)
2162 query_putrdataset(client, &sigrdataset);
2163 while ((crdataset = ISC_LIST_HEAD(cfname.list)) != NULL) {
2164 ISC_LIST_UNLINK(cfname.list, crdataset, link);
2165 query_putrdataset(client, &crdataset);
2168 query_releasename(client, &fname);
2170 dns_db_detachnode(db, &node);
2174 dns_zone_detach(&zone);
2176 CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: done");
2181 query_addrdataset(ns_client_t *client, dns_name_t *fname,
2182 dns_rdataset_t *rdataset)
2184 client_additionalctx_t additionalctx;
2187 * Add 'rdataset' and any pertinent additional data to
2188 * 'fname', a name in the response message for 'client'.
2191 CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset");
2193 ISC_LIST_APPEND(fname->list, rdataset, link);
2195 if (client->view->order != NULL)
2196 rdataset->attributes |= dns_order_find(client->view->order,
2197 fname, rdataset->type,
2199 rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
2201 if (NOADDITIONAL(client))
2205 * Add additional data.
2207 * We don't care if dns_rdataset_additionaldata() fails.
2209 additionalctx.client = client;
2210 additionalctx.rdataset = rdataset;
2211 (void)dns_rdataset_additionaldata(rdataset, query_addadditional2,
2213 CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset: done");
2217 query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
2218 dns_rdataset_t *sigrdataset, isc_buffer_t *dbuf,
2219 dns_section_t section)
2221 dns_name_t *name, *mname;
2222 dns_rdata_t *dns64_rdata;
2223 dns_rdata_t rdata = DNS_RDATA_INIT;
2224 dns_rdatalist_t *dns64_rdatalist;
2225 dns_rdataset_t *dns64_rdataset;
2226 dns_rdataset_t *mrdataset;
2227 isc_buffer_t *buffer;
2229 isc_result_t result;
2230 dns_view_t *view = client->view;
2231 isc_netaddr_t netaddr;
2233 unsigned int flags = 0;
2236 * To the current response for 'client', add the answer RRset
2237 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
2238 * owner name '*namep', to section 'section', unless they are
2239 * already there. Also add any pertinent additional data.
2241 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
2242 * stored in 'dbuf'. In this case, query_addrrset() guarantees that
2243 * when it returns the name will either have been kept or released.
2245 CTRACE(ISC_LOG_DEBUG(3), "query_dns64");
2251 dns64_rdataset = NULL;
2252 dns64_rdatalist = NULL;
2253 result = dns_message_findname(client->message, section,
2254 name, dns_rdatatype_aaaa,
2256 &mname, &mrdataset);
2257 if (result == ISC_R_SUCCESS) {
2259 * We've already got an RRset of the given name and type.
2260 * There's nothing else to do;
2262 CTRACE(ISC_LOG_DEBUG(3),
2263 "query_dns64: dns_message_findname succeeded: done");
2265 query_releasename(client, namep);
2266 return (ISC_R_SUCCESS);
2267 } else if (result == DNS_R_NXDOMAIN) {
2269 * The name doesn't exist.
2272 query_keepname(client, name, dbuf);
2273 dns_message_addname(client->message, name, section);
2277 RUNTIME_CHECK(result == DNS_R_NXRRSET);
2279 query_releasename(client, namep);
2282 if (rdataset->trust != dns_trust_secure &&
2283 (section == DNS_SECTION_ANSWER ||
2284 section == DNS_SECTION_AUTHORITY))
2285 client->query.attributes &= ~NS_QUERYATTR_SECURE;
2287 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2289 result = isc_buffer_allocate(client->mctx, &buffer, view->dns64cnt *
2290 16 * dns_rdataset_count(rdataset));
2291 if (result != ISC_R_SUCCESS)
2293 result = dns_message_gettemprdataset(client->message, &dns64_rdataset);
2294 if (result != ISC_R_SUCCESS)
2296 result = dns_message_gettemprdatalist(client->message,
2298 if (result != ISC_R_SUCCESS)
2301 dns_rdataset_init(dns64_rdataset);
2302 dns_rdatalist_init(dns64_rdatalist);
2303 dns64_rdatalist->rdclass = dns_rdataclass_in;
2304 dns64_rdatalist->type = dns_rdatatype_aaaa;
2305 if (client->query.dns64_ttl != ISC_UINT32_MAX)
2306 dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl,
2307 client->query.dns64_ttl);
2309 dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, 600);
2311 if (RECURSIONOK(client))
2312 flags |= DNS_DNS64_RECURSIVE;
2315 * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC
2316 * as this provides a easy way to see if the answer was signed.
2318 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
2319 flags |= DNS_DNS64_DNSSEC;
2321 for (result = dns_rdataset_first(rdataset);
2322 result == ISC_R_SUCCESS;
2323 result = dns_rdataset_next(rdataset)) {
2324 for (dns64 = ISC_LIST_HEAD(client->view->dns64);
2325 dns64 != NULL; dns64 = dns_dns64_next(dns64)) {
2327 dns_rdataset_current(rdataset, &rdata);
2328 isc_buffer_availableregion(buffer, &r);
2329 INSIST(r.length >= 16);
2330 result = dns_dns64_aaaafroma(dns64, &netaddr,
2332 &ns_g_server->aclenv,
2333 flags, rdata.data, r.base);
2334 if (result != ISC_R_SUCCESS) {
2335 dns_rdata_reset(&rdata);
2338 isc_buffer_add(buffer, 16);
2339 isc_buffer_remainingregion(buffer, &r);
2340 isc_buffer_forward(buffer, 16);
2341 result = dns_message_gettemprdata(client->message,
2343 if (result != ISC_R_SUCCESS)
2345 dns_rdata_init(dns64_rdata);
2346 dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in,
2347 dns_rdatatype_aaaa, &r);
2348 ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata,
2351 dns_rdata_reset(&rdata);
2354 if (result != ISC_R_NOMORE)
2357 if (ISC_LIST_EMPTY(dns64_rdatalist->rdata))
2360 result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset);
2361 if (result != ISC_R_SUCCESS)
2363 client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
2364 dns64_rdataset->trust = rdataset->trust;
2365 query_addrdataset(client, mname, dns64_rdataset);
2366 dns64_rdataset = NULL;
2367 dns64_rdatalist = NULL;
2368 dns_message_takebuffer(client->message, &buffer);
2369 result = ISC_R_SUCCESS;
2373 isc_buffer_free(&buffer);
2375 if (dns64_rdata != NULL)
2376 dns_message_puttemprdata(client->message, &dns64_rdata);
2378 if (dns64_rdataset != NULL)
2379 dns_message_puttemprdataset(client->message, &dns64_rdataset);
2381 if (dns64_rdatalist != NULL) {
2382 for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata);
2383 dns64_rdata != NULL;
2384 dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata))
2386 ISC_LIST_UNLINK(dns64_rdatalist->rdata,
2388 dns_message_puttemprdata(client->message, &dns64_rdata);
2390 dns_message_puttemprdatalist(client->message, &dns64_rdatalist);
2393 CTRACE(ISC_LOG_DEBUG(3), "query_dns64: done");
2398 query_filter64(ns_client_t *client, dns_name_t **namep,
2399 dns_rdataset_t *rdataset, isc_buffer_t *dbuf,
2400 dns_section_t section)
2402 dns_name_t *name, *mname;
2403 dns_rdata_t *myrdata;
2404 dns_rdata_t rdata = DNS_RDATA_INIT;
2405 dns_rdatalist_t *myrdatalist;
2406 dns_rdataset_t *myrdataset;
2407 isc_buffer_t *buffer;
2409 isc_result_t result;
2412 CTRACE(ISC_LOG_DEBUG(3), "query_filter64");
2414 INSIST(client->query.dns64_aaaaok != NULL);
2415 INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset));
2423 result = dns_message_findname(client->message, section,
2424 name, dns_rdatatype_aaaa,
2426 &mname, &myrdataset);
2427 if (result == ISC_R_SUCCESS) {
2429 * We've already got an RRset of the given name and type.
2430 * There's nothing else to do;
2432 CTRACE(ISC_LOG_DEBUG(3),
2433 "query_filter64: dns_message_findname succeeded: done");
2435 query_releasename(client, namep);
2437 } else if (result == DNS_R_NXDOMAIN) {
2441 RUNTIME_CHECK(result == DNS_R_NXRRSET);
2443 query_releasename(client, namep);
2447 if (rdataset->trust != dns_trust_secure &&
2448 (section == DNS_SECTION_ANSWER ||
2449 section == DNS_SECTION_AUTHORITY))
2450 client->query.attributes &= ~NS_QUERYATTR_SECURE;
2452 result = isc_buffer_allocate(client->mctx, &buffer,
2453 16 * dns_rdataset_count(rdataset));
2454 if (result != ISC_R_SUCCESS)
2456 result = dns_message_gettemprdataset(client->message, &myrdataset);
2457 if (result != ISC_R_SUCCESS)
2459 result = dns_message_gettemprdatalist(client->message, &myrdatalist);
2460 if (result != ISC_R_SUCCESS)
2463 dns_rdataset_init(myrdataset);
2464 dns_rdatalist_init(myrdatalist);
2465 myrdatalist->rdclass = dns_rdataclass_in;
2466 myrdatalist->type = dns_rdatatype_aaaa;
2467 myrdatalist->ttl = rdataset->ttl;
2470 for (result = dns_rdataset_first(rdataset);
2471 result == ISC_R_SUCCESS;
2472 result = dns_rdataset_next(rdataset)) {
2473 if (!client->query.dns64_aaaaok[i++])
2475 dns_rdataset_current(rdataset, &rdata);
2476 INSIST(rdata.length == 16);
2477 isc_buffer_putmem(buffer, rdata.data, rdata.length);
2478 isc_buffer_remainingregion(buffer, &r);
2479 isc_buffer_forward(buffer, rdata.length);
2480 result = dns_message_gettemprdata(client->message, &myrdata);
2481 if (result != ISC_R_SUCCESS)
2483 dns_rdata_init(myrdata);
2484 dns_rdata_fromregion(myrdata, dns_rdataclass_in,
2485 dns_rdatatype_aaaa, &r);
2486 ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link);
2488 dns_rdata_reset(&rdata);
2490 if (result != ISC_R_NOMORE)
2493 result = dns_rdatalist_tordataset(myrdatalist, myrdataset);
2494 if (result != ISC_R_SUCCESS)
2496 client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
2497 if (mname == name) {
2499 query_keepname(client, name, dbuf);
2500 dns_message_addname(client->message, name, section);
2503 myrdataset->trust = rdataset->trust;
2504 query_addrdataset(client, mname, myrdataset);
2507 dns_message_takebuffer(client->message, &buffer);
2511 isc_buffer_free(&buffer);
2513 if (myrdata != NULL)
2514 dns_message_puttemprdata(client->message, &myrdata);
2516 if (myrdataset != NULL)
2517 dns_message_puttemprdataset(client->message, &myrdataset);
2519 if (myrdatalist != NULL) {
2520 for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata);
2522 myrdata = ISC_LIST_HEAD(myrdatalist->rdata))
2524 ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link);
2525 dns_message_puttemprdata(client->message, &myrdata);
2527 dns_message_puttemprdatalist(client->message, &myrdatalist);
2530 query_releasename(client, &name);
2532 CTRACE(ISC_LOG_DEBUG(3), "query_filter64: done");
2536 query_addrrset(ns_client_t *client, dns_name_t **namep,
2537 dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
2538 isc_buffer_t *dbuf, dns_section_t section)
2540 dns_name_t *name, *mname;
2541 dns_rdataset_t *rdataset, *mrdataset, *sigrdataset;
2542 isc_result_t result;
2545 * To the current response for 'client', add the answer RRset
2546 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
2547 * owner name '*namep', to section 'section', unless they are
2548 * already there. Also add any pertinent additional data.
2550 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
2551 * stored in 'dbuf'. In this case, query_addrrset() guarantees that
2552 * when it returns the name will either have been kept or released.
2554 CTRACE(ISC_LOG_DEBUG(3), "query_addrrset");
2556 rdataset = *rdatasetp;
2557 if (sigrdatasetp != NULL)
2558 sigrdataset = *sigrdatasetp;
2563 result = dns_message_findname(client->message, section,
2564 name, rdataset->type, rdataset->covers,
2565 &mname, &mrdataset);
2566 if (result == ISC_R_SUCCESS) {
2568 * We've already got an RRset of the given name and type.
2570 CTRACE(ISC_LOG_DEBUG(3),
2571 "query_addrrset: dns_message_findname succeeded: done");
2573 query_releasename(client, namep);
2574 if ((rdataset->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
2575 mrdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
2577 } else if (result == DNS_R_NXDOMAIN) {
2579 * The name doesn't exist.
2582 query_keepname(client, name, dbuf);
2583 dns_message_addname(client->message, name, section);
2587 RUNTIME_CHECK(result == DNS_R_NXRRSET);
2589 query_releasename(client, namep);
2592 if (rdataset->trust != dns_trust_secure &&
2593 (section == DNS_SECTION_ANSWER ||
2594 section == DNS_SECTION_AUTHORITY))
2595 client->query.attributes &= ~NS_QUERYATTR_SECURE;
2597 * Note: we only add SIGs if we've added the type they cover, so
2598 * we do not need to check if the SIG rdataset is already in the
2601 query_addrdataset(client, mname, rdataset);
2603 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
2605 * We have a signature. Add it to the response.
2607 ISC_LIST_APPEND(mname->list, sigrdataset, link);
2608 *sigrdatasetp = NULL;
2610 CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: done");
2613 static inline isc_result_t
2614 query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
2615 unsigned int override_ttl, isc_boolean_t isassociated,
2616 dns_section_t section)
2620 isc_result_t result, eresult;
2621 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2622 dns_rdataset_t **sigrdatasetp = NULL;
2623 dns_clientinfomethods_t cm;
2624 dns_clientinfo_t ci;
2626 CTRACE(ISC_LOG_DEBUG(3), "query_addsoa");
2630 eresult = ISC_R_SUCCESS;
2635 dns_clientinfomethods_init(&cm, ns_client_sourceip);
2636 dns_clientinfo_init(&ci, client);
2639 * Don't add the SOA record for test which set "-T nosoa".
2641 if (ns_g_nosoa && (!WANTDNSSEC(client) || !isassociated))
2642 return (ISC_R_SUCCESS);
2645 * Get resources and make 'name' be the database origin.
2647 result = dns_message_gettempname(client->message, &name);
2648 if (result != ISC_R_SUCCESS)
2650 dns_name_init(name, NULL);
2651 dns_name_clone(dns_db_origin(db), name);
2652 rdataset = query_newrdataset(client);
2653 if (rdataset == NULL) {
2654 CTRACE(ISC_LOG_ERROR, "unable to allocate rdataset");
2655 eresult = DNS_R_SERVFAIL;
2658 if (WANTDNSSEC(client) && dns_db_issecure(db)) {
2659 sigrdataset = query_newrdataset(client);
2660 if (sigrdataset == NULL) {
2661 CTRACE(ISC_LOG_ERROR, "unable to allocate sigrdataset");
2662 eresult = DNS_R_SERVFAIL;
2670 result = dns_db_getoriginnode(db, &node);
2671 if (result == ISC_R_SUCCESS) {
2672 result = dns_db_findrdataset(db, node, version,
2673 dns_rdatatype_soa, 0, client->now,
2674 rdataset, sigrdataset);
2676 dns_fixedname_t foundname;
2679 dns_fixedname_init(&foundname);
2680 fname = dns_fixedname_name(&foundname);
2682 result = dns_db_findext(db, name, version, dns_rdatatype_soa,
2683 client->query.dboptions, 0, &node,
2684 fname, &cm, &ci, rdataset, sigrdataset);
2686 if (result != ISC_R_SUCCESS) {
2688 * This is bad. We tried to get the SOA RR at the zone top
2689 * and it didn't work!
2691 CTRACE(ISC_LOG_ERROR, "unable to find SOA RR at zone apex");
2692 eresult = DNS_R_SERVFAIL;
2695 * Extract the SOA MINIMUM.
2697 dns_rdata_soa_t soa;
2698 dns_rdata_t rdata = DNS_RDATA_INIT;
2699 result = dns_rdataset_first(rdataset);
2700 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2701 dns_rdataset_current(rdataset, &rdata);
2702 result = dns_rdata_tostruct(&rdata, &soa, NULL);
2703 if (result != ISC_R_SUCCESS)
2706 if (override_ttl != ISC_UINT32_MAX &&
2707 override_ttl < rdataset->ttl) {
2708 rdataset->ttl = override_ttl;
2709 if (sigrdataset != NULL)
2710 sigrdataset->ttl = override_ttl;
2714 * Add the SOA and its SIG to the response, with the
2715 * TTLs adjusted per RFC2308 section 3.
2717 if (rdataset->ttl > soa.minimum)
2718 rdataset->ttl = soa.minimum;
2719 if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum)
2720 sigrdataset->ttl = soa.minimum;
2722 if (sigrdataset != NULL)
2723 sigrdatasetp = &sigrdataset;
2725 sigrdatasetp = NULL;
2727 if (section == DNS_SECTION_ADDITIONAL)
2728 rdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
2729 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
2734 query_putrdataset(client, &rdataset);
2735 if (sigrdataset != NULL)
2736 query_putrdataset(client, &sigrdataset);
2738 query_releasename(client, &name);
2740 dns_db_detachnode(db, &node);
2745 static inline isc_result_t
2746 query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
2747 dns_name_t *name, *fname;
2749 isc_result_t result, eresult;
2750 dns_fixedname_t foundname;
2751 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2752 dns_rdataset_t **sigrdatasetp = NULL;
2753 dns_clientinfomethods_t cm;
2754 dns_clientinfo_t ci;
2756 CTRACE(ISC_LOG_DEBUG(3), "query_addns");
2760 eresult = ISC_R_SUCCESS;
2764 dns_fixedname_init(&foundname);
2765 fname = dns_fixedname_name(&foundname);
2766 dns_clientinfomethods_init(&cm, ns_client_sourceip);
2767 dns_clientinfo_init(&ci, client);
2770 * Get resources and make 'name' be the database origin.
2772 result = dns_message_gettempname(client->message, &name);
2773 if (result != ISC_R_SUCCESS) {
2774 CTRACE(ISC_LOG_DEBUG(3),
2775 "query_addns: dns_message_gettempname failed: done");
2778 dns_name_init(name, NULL);
2779 dns_name_clone(dns_db_origin(db), name);
2780 rdataset = query_newrdataset(client);
2781 if (rdataset == NULL) {
2782 CTRACE(ISC_LOG_ERROR,
2783 "query_addns: query_newrdataset failed");
2784 eresult = DNS_R_SERVFAIL;
2787 if (WANTDNSSEC(client) && dns_db_issecure(db)) {
2788 sigrdataset = query_newrdataset(client);
2789 if (sigrdataset == NULL) {
2790 CTRACE(ISC_LOG_ERROR,
2791 "query_addns: query_newrdataset failed");
2792 eresult = DNS_R_SERVFAIL;
2798 * Find the NS rdataset.
2800 result = dns_db_getoriginnode(db, &node);
2801 if (result == ISC_R_SUCCESS) {
2802 result = dns_db_findrdataset(db, node, version,
2803 dns_rdatatype_ns, 0, client->now,
2804 rdataset, sigrdataset);
2806 CTRACE(ISC_LOG_DEBUG(3), "query_addns: calling dns_db_find");
2807 result = dns_db_findext(db, name, NULL, dns_rdatatype_ns,
2808 client->query.dboptions, 0, &node,
2809 fname, &cm, &ci, rdataset, sigrdataset);
2810 CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_db_find complete");
2812 if (result != ISC_R_SUCCESS) {
2813 CTRACE(ISC_LOG_ERROR,
2815 "dns_db_findrdataset or dns_db_find failed");
2817 * This is bad. We tried to get the NS rdataset at the zone
2818 * top and it didn't work!
2820 eresult = DNS_R_SERVFAIL;
2822 if (sigrdataset != NULL)
2823 sigrdatasetp = &sigrdataset;
2825 sigrdatasetp = NULL;
2826 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
2827 DNS_SECTION_AUTHORITY);
2831 CTRACE(ISC_LOG_DEBUG(3), "query_addns: cleanup");
2832 query_putrdataset(client, &rdataset);
2833 if (sigrdataset != NULL)
2834 query_putrdataset(client, &sigrdataset);
2836 query_releasename(client, &name);
2838 dns_db_detachnode(db, &node);
2840 CTRACE(ISC_LOG_DEBUG(3), "query_addns: done");
2845 query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
2846 dns_trust_t trust, dns_ttl_t ttl)
2848 dns_rdataset_t *rdataset;
2849 dns_rdatalist_t *rdatalist;
2853 isc_result_t result;
2856 * We assume the name data referred to by tname won't go away.
2860 result = dns_message_gettempname(client->message, &aname);
2861 if (result != ISC_R_SUCCESS)
2863 result = dns_name_dup(qname, client->mctx, aname);
2864 if (result != ISC_R_SUCCESS) {
2865 dns_message_puttempname(client->message, &aname);
2870 result = dns_message_gettemprdatalist(client->message, &rdatalist);
2871 if (result != ISC_R_SUCCESS) {
2872 dns_message_puttempname(client->message, &aname);
2876 result = dns_message_gettemprdata(client->message, &rdata);
2877 if (result != ISC_R_SUCCESS) {
2878 dns_message_puttempname(client->message, &aname);
2879 dns_message_puttemprdatalist(client->message, &rdatalist);
2883 result = dns_message_gettemprdataset(client->message, &rdataset);
2884 if (result != ISC_R_SUCCESS) {
2885 dns_message_puttempname(client->message, &aname);
2886 dns_message_puttemprdatalist(client->message, &rdatalist);
2887 dns_message_puttemprdata(client->message, &rdata);
2890 dns_rdataset_init(rdataset);
2891 rdatalist->type = dns_rdatatype_cname;
2892 rdatalist->rdclass = client->message->rdclass;
2893 rdatalist->ttl = ttl;
2895 dns_name_toregion(tname, &r);
2896 rdata->data = r.base;
2897 rdata->length = r.length;
2898 rdata->rdclass = client->message->rdclass;
2899 rdata->type = dns_rdatatype_cname;
2901 ISC_LIST_INIT(rdatalist->rdata);
2902 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2903 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
2905 rdataset->trust = trust;
2907 query_addrrset(client, &aname, &rdataset, NULL, NULL,
2908 DNS_SECTION_ANSWER);
2909 if (rdataset != NULL) {
2910 if (dns_rdataset_isassociated(rdataset))
2911 dns_rdataset_disassociate(rdataset);
2912 dns_message_puttemprdataset(client->message, &rdataset);
2915 dns_message_puttempname(client->message, &aname);
2917 return (ISC_R_SUCCESS);
2921 * Mark the RRsets as secure. Update the cache (db) to reflect the
2922 * change in trust level.
2925 mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
2926 dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset,
2927 dns_rdataset_t *sigrdataset)
2929 isc_result_t result;
2930 dns_dbnode_t *node = NULL;
2931 dns_clientinfomethods_t cm;
2932 dns_clientinfo_t ci;
2935 rdataset->trust = dns_trust_secure;
2936 sigrdataset->trust = dns_trust_secure;
2937 dns_clientinfomethods_init(&cm, ns_client_sourceip);
2938 dns_clientinfo_init(&ci, client);
2941 * Save the updated secure state. Ignore failures.
2943 result = dns_db_findnodeext(db, name, ISC_TRUE, &cm, &ci, &node);
2944 if (result != ISC_R_SUCCESS)
2947 isc_stdtime_get(&now);
2948 dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now,
2949 client->view->acceptexpired);
2951 (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset,
2953 (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset,
2955 dns_db_detachnode(db, &node);
2959 * Find the secure key that corresponds to rrsig.
2960 * Note: 'keyrdataset' maintains state between successive calls,
2961 * there may be multiple keys with the same keyid.
2962 * Return ISC_FALSE if we have exhausted all the possible keys.
2964 static isc_boolean_t
2965 get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
2966 dns_rdataset_t *keyrdataset, dst_key_t **keyp)
2968 isc_result_t result;
2969 dns_dbnode_t *node = NULL;
2970 isc_boolean_t secure = ISC_FALSE;
2971 dns_clientinfomethods_t cm;
2972 dns_clientinfo_t ci;
2974 dns_clientinfomethods_init(&cm, ns_client_sourceip);
2975 dns_clientinfo_init(&ci, client);
2977 if (!dns_rdataset_isassociated(keyrdataset)) {
2978 result = dns_db_findnodeext(db, &rrsig->signer, ISC_FALSE,
2980 if (result != ISC_R_SUCCESS)
2983 result = dns_db_findrdataset(db, node, NULL,
2984 dns_rdatatype_dnskey, 0,
2985 client->now, keyrdataset, NULL);
2986 dns_db_detachnode(db, &node);
2987 if (result != ISC_R_SUCCESS)
2990 if (keyrdataset->trust != dns_trust_secure)
2993 result = dns_rdataset_first(keyrdataset);
2995 result = dns_rdataset_next(keyrdataset);
2997 for ( ; result == ISC_R_SUCCESS;
2998 result = dns_rdataset_next(keyrdataset)) {
2999 dns_rdata_t rdata = DNS_RDATA_INIT;
3002 dns_rdataset_current(keyrdataset, &rdata);
3003 isc_buffer_init(&b, rdata.data, rdata.length);
3004 isc_buffer_add(&b, rdata.length);
3005 result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
3006 client->mctx, keyp);
3007 if (result != ISC_R_SUCCESS)
3009 if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
3010 rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
3011 dst_key_iszonekey(*keyp)) {
3020 static isc_boolean_t
3021 verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,
3022 dns_rdata_t *rdata, ns_client_t *client)
3024 isc_result_t result;
3025 dns_fixedname_t fixed;
3026 isc_boolean_t ignore = ISC_FALSE;
3028 dns_fixedname_init(&fixed);
3031 result = dns_dnssec_verify3(name, rdataset, key, ignore,
3032 client->view->maxbits, client->mctx,
3034 if (result == DNS_R_SIGEXPIRED && client->view->acceptexpired) {
3038 if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD)
3044 * Validate the rdataset if possible with available records.
3046 static isc_boolean_t
3047 validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
3048 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
3050 isc_result_t result;
3051 dns_rdata_t rdata = DNS_RDATA_INIT;
3052 dns_rdata_rrsig_t rrsig;
3053 dst_key_t *key = NULL;
3054 dns_rdataset_t keyrdataset;
3056 if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
3059 for (result = dns_rdataset_first(sigrdataset);
3060 result == ISC_R_SUCCESS;
3061 result = dns_rdataset_next(sigrdataset)) {
3063 dns_rdata_reset(&rdata);
3064 dns_rdataset_current(sigrdataset, &rdata);
3065 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
3066 if (result != ISC_R_SUCCESS)
3068 if (!dns_resolver_algorithm_supported(client->view->resolver,
3069 name, rrsig.algorithm))
3071 if (!dns_name_issubdomain(name, &rrsig.signer))
3073 dns_rdataset_init(&keyrdataset);
3075 if (!get_key(client, db, &rrsig, &keyrdataset, &key))
3077 if (verify(key, name, rdataset, &rdata, client)) {
3079 dns_rdataset_disassociate(&keyrdataset);
3080 mark_secure(client, db, name, &rrsig,
3081 rdataset, sigrdataset);
3086 if (dns_rdataset_isassociated(&keyrdataset))
3087 dns_rdataset_disassociate(&keyrdataset);
3093 query_addbestns(ns_client_t *client) {
3096 dns_name_t *fname, *zfname;
3097 dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset;
3098 isc_boolean_t is_zone, use_zone;
3100 isc_result_t result;
3101 dns_dbversion_t *version;
3104 dns_clientinfomethods_t cm;
3105 dns_clientinfo_t ci;
3107 CTRACE(ISC_LOG_DEBUG(3), "query_addbestns");
3113 zsigrdataset = NULL;
3119 is_zone = ISC_FALSE;
3120 use_zone = ISC_FALSE;
3122 dns_clientinfomethods_init(&cm, ns_client_sourceip);
3123 dns_clientinfo_init(&ci, client);
3126 * Find the right database.
3128 result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0,
3129 &zone, &db, &version, &is_zone);
3130 if (result != ISC_R_SUCCESS)
3135 * We'll need some resources...
3137 dbuf = query_getnamebuf(client);
3140 fname = query_newname(client, dbuf, &b);
3141 rdataset = query_newrdataset(client);
3142 if (fname == NULL || rdataset == NULL)
3145 * Get the RRSIGs if the client requested them or if we may
3146 * need to validate answers from the cache.
3148 if (WANTDNSSEC(client) || !is_zone) {
3149 sigrdataset = query_newrdataset(client);
3150 if (sigrdataset == NULL)
3155 * Now look for the zonecut.
3158 result = dns_db_findext(db, client->query.qname, version,
3160 client->query.dboptions,
3161 client->now, &node, fname,
3162 &cm, &ci, rdataset, sigrdataset);
3163 if (result != DNS_R_DELEGATION)
3165 if (USECACHE(client)) {
3166 query_keepname(client, fname, dbuf);
3170 zrdataset = rdataset;
3172 zsigrdataset = sigrdataset;
3174 dns_db_detachnode(db, &node);
3177 dns_db_attach(client->view->cachedb, &db);
3178 is_zone = ISC_FALSE;
3182 result = dns_db_findzonecut(db, client->query.qname,
3183 client->query.dboptions,
3184 client->now, &node, fname,
3185 rdataset, sigrdataset);
3186 if (result == ISC_R_SUCCESS) {
3187 if (zfname != NULL &&
3188 !dns_name_issubdomain(fname, zfname)) {
3190 * We found a zonecut in the cache, but our
3191 * zone delegation is better.
3193 use_zone = ISC_TRUE;
3195 } else if (result == ISC_R_NOTFOUND && zfname != NULL) {
3197 * We didn't find anything in the cache, but we
3198 * have a zone delegation, so use it.
3200 use_zone = ISC_TRUE;
3206 query_releasename(client, &fname);
3210 * We've already done query_keepname() on
3211 * zfname, so we must set dbuf to NULL to
3212 * prevent query_addrrset() from trying to
3213 * call query_keepname() again.
3216 query_putrdataset(client, &rdataset);
3217 if (sigrdataset != NULL)
3218 query_putrdataset(client, &sigrdataset);
3219 rdataset = zrdataset;
3221 sigrdataset = zsigrdataset;
3222 zsigrdataset = NULL;
3226 * Attempt to validate RRsets that are pending or that are glue.
3228 if ((DNS_TRUST_PENDING(rdataset->trust) ||
3229 (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust)))
3230 && !validate(client, db, fname, rdataset, sigrdataset) &&
3231 !PENDINGOK(client->query.dboptions))
3234 if ((DNS_TRUST_GLUE(rdataset->trust) ||
3235 (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
3236 !validate(client, db, fname, rdataset, sigrdataset) &&
3237 SECURE(client) && WANTDNSSEC(client))
3241 * If the answer is secure only add NS records if they are secure
3242 * when the client may be looking for AD in the response.
3244 if (SECURE(client) && (WANTDNSSEC(client) || WANTAD(client)) &&
3245 ((rdataset->trust != dns_trust_secure) ||
3246 (sigrdataset != NULL && sigrdataset->trust != dns_trust_secure)))
3250 * If the client doesn't want DNSSEC we can discard the sigrdataset
3253 if (!WANTDNSSEC(client))
3254 query_putrdataset(client, &sigrdataset);
3255 query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
3256 DNS_SECTION_AUTHORITY);
3259 if (rdataset != NULL)
3260 query_putrdataset(client, &rdataset);
3261 if (sigrdataset != NULL)
3262 query_putrdataset(client, &sigrdataset);
3264 query_releasename(client, &fname);
3266 dns_db_detachnode(db, &node);
3270 dns_zone_detach(&zone);
3272 query_putrdataset(client, &zrdataset);
3273 if (zsigrdataset != NULL)
3274 query_putrdataset(client, &zsigrdataset);
3276 query_releasename(client, &zfname);
3277 dns_db_detach(&zdb);
3282 fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) {
3283 if (*rdataset == NULL)
3284 *rdataset = query_newrdataset(client);
3285 else if (dns_rdataset_isassociated(*rdataset))
3286 dns_rdataset_disassociate(*rdataset);
3290 fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf,
3293 if (*fname == NULL) {
3294 *dbuf = query_getnamebuf(client);
3297 *fname = query_newname(client, *dbuf, nbuf);
3302 query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node,
3303 dns_dbversion_t *version, dns_name_t *name)
3305 dns_fixedname_t fixed;
3306 dns_name_t *fname = NULL;
3308 dns_rdataset_t *rdataset, *sigrdataset;
3309 isc_buffer_t *dbuf, b;
3310 isc_result_t result;
3313 CTRACE(ISC_LOG_DEBUG(3), "query_addds");
3319 * We'll need some resources...
3321 rdataset = query_newrdataset(client);
3322 sigrdataset = query_newrdataset(client);
3323 if (rdataset == NULL || sigrdataset == NULL)
3327 * Look for the DS record, which may or may not be present.
3329 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ds, 0,
3330 client->now, rdataset, sigrdataset);
3332 * If we didn't find it, look for an NSEC.
3334 if (result == ISC_R_NOTFOUND)
3335 result = dns_db_findrdataset(db, node, version,
3336 dns_rdatatype_nsec, 0, client->now,
3337 rdataset, sigrdataset);
3338 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
3340 if (!dns_rdataset_isassociated(rdataset) ||
3341 !dns_rdataset_isassociated(sigrdataset))
3345 * We've already added the NS record, so if the name's not there,
3346 * we have other problems. Use this name rather than calling
3349 result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
3350 if (result != ISC_R_SUCCESS)
3354 dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
3356 result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
3357 if (result != ISC_R_SUCCESS)
3360 ISC_LIST_APPEND(rname->list, rdataset, link);
3361 ISC_LIST_APPEND(rname->list, sigrdataset, link);
3367 if (!dns_db_iszone(db))
3370 * Add the NSEC3 which proves the DS does not exist.
3372 dbuf = query_getnamebuf(client);
3375 fname = query_newname(client, dbuf, &b);
3376 dns_fixedname_init(&fixed);
3377 if (dns_rdataset_isassociated(rdataset))
3378 dns_rdataset_disassociate(rdataset);
3379 if (dns_rdataset_isassociated(sigrdataset))
3380 dns_rdataset_disassociate(sigrdataset);
3381 query_findclosestnsec3(name, db, version, client, rdataset,
3382 sigrdataset, fname, ISC_TRUE,
3383 dns_fixedname_name(&fixed));
3384 if (!dns_rdataset_isassociated(rdataset))
3386 query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
3387 DNS_SECTION_AUTHORITY);
3389 * Did we find the closest provable encloser instead?
3390 * If so add the nearest to the closest provable encloser.
3392 if (!dns_name_equal(name, dns_fixedname_name(&fixed))) {
3393 count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1;
3394 dns_name_getlabelsequence(name,
3395 dns_name_countlabels(name) - count,
3396 count, dns_fixedname_name(&fixed));
3397 fixfname(client, &fname, &dbuf, &b);
3398 fixrdataset(client, &rdataset);
3399 fixrdataset(client, &sigrdataset);
3400 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
3402 query_findclosestnsec3(dns_fixedname_name(&fixed), db, version,
3403 client, rdataset, sigrdataset, fname,
3405 if (!dns_rdataset_isassociated(rdataset))
3407 query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
3408 DNS_SECTION_AUTHORITY);
3412 if (rdataset != NULL)
3413 query_putrdataset(client, &rdataset);
3414 if (sigrdataset != NULL)
3415 query_putrdataset(client, &sigrdataset);
3417 query_releasename(client, &fname);
3421 query_addwildcardproof(ns_client_t *client, dns_db_t *db,
3422 dns_dbversion_t *version, dns_name_t *name,
3423 isc_boolean_t ispositive, isc_boolean_t nodata)
3425 isc_buffer_t *dbuf, b;
3427 dns_rdataset_t *rdataset, *sigrdataset;
3428 dns_fixedname_t wfixed;
3431 unsigned int options;
3432 unsigned int olabels, nlabels, labels;
3433 isc_result_t result;
3434 dns_rdata_t rdata = DNS_RDATA_INIT;
3435 dns_rdata_nsec_t nsec;
3436 isc_boolean_t have_wname;
3438 dns_fixedname_t cfixed;
3440 dns_clientinfomethods_t cm;
3441 dns_clientinfo_t ci;
3443 CTRACE(ISC_LOG_DEBUG(3), "query_addwildcardproof");
3449 dns_clientinfomethods_init(&cm, ns_client_sourceip);
3450 dns_clientinfo_init(&ci, client);
3453 * Get the NOQNAME proof then if !ispositive
3454 * get the NOWILDCARD proof.
3456 * DNS_DBFIND_NOWILD finds the NSEC records that covers the
3457 * name ignoring any wildcard. From the owner and next names
3458 * of this record you can compute which wildcard (if it exists)
3459 * will match by finding the longest common suffix of the
3460 * owner name and next names with the qname and prefixing that
3461 * with the wildcard label.
3466 * example NSEC b.example
3468 * b.example NSEC a.d.example
3470 * a.d.example NSEC g.f.example
3472 * g.f.example NSEC z.i.example
3474 * z.i.example NSEC example
3477 * a.example -> example NSEC b.example
3478 * owner common example
3479 * next common example
3481 * d.b.example -> b.example NSEC a.d.example
3482 * owner common b.example
3483 * next common example
3485 * a.f.example -> a.d.example NSEC g.f.example
3486 * owner common example
3487 * next common f.example
3489 * j.example -> z.i.example NSEC example
3490 * owner common example
3491 * next common example
3494 options = client->query.dboptions | DNS_DBFIND_NOWILD;
3495 dns_fixedname_init(&wfixed);
3496 wname = dns_fixedname_name(&wfixed);
3498 have_wname = ISC_FALSE;
3500 * We'll need some resources...
3502 dbuf = query_getnamebuf(client);
3505 fname = query_newname(client, dbuf, &b);
3506 rdataset = query_newrdataset(client);
3507 sigrdataset = query_newrdataset(client);
3508 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
3511 result = dns_db_findext(db, name, version, dns_rdatatype_nsec,
3512 options, 0, &node, fname, &cm, &ci,
3513 rdataset, sigrdataset);
3515 dns_db_detachnode(db, &node);
3517 if (!dns_rdataset_isassociated(rdataset)) {
3519 * No NSEC proof available, return NSEC3 proofs instead.
3521 dns_fixedname_init(&cfixed);
3522 cname = dns_fixedname_name(&cfixed);
3524 * Find the closest encloser.
3526 dns_name_copy(name, cname, NULL);
3527 while (result == DNS_R_NXDOMAIN) {
3528 labels = dns_name_countlabels(cname) - 1;
3534 dns_name_split(cname, labels, NULL, cname);
3535 result = dns_db_findext(db, cname, version,
3537 options, 0, NULL, fname,
3538 &cm, &ci, NULL, NULL);
3541 * Add closest (provable) encloser NSEC3.
3543 query_findclosestnsec3(cname, db, NULL, client, rdataset,
3544 sigrdataset, fname, ISC_TRUE, cname);
3545 if (!dns_rdataset_isassociated(rdataset))
3548 query_addrrset(client, &fname, &rdataset, &sigrdataset,
3549 dbuf, DNS_SECTION_AUTHORITY);
3552 * Replace resources which were consumed by query_addrrset.
3554 if (fname == NULL) {
3555 dbuf = query_getnamebuf(client);
3558 fname = query_newname(client, dbuf, &b);
3561 if (rdataset == NULL)
3562 rdataset = query_newrdataset(client);
3563 else if (dns_rdataset_isassociated(rdataset))
3564 dns_rdataset_disassociate(rdataset);
3566 if (sigrdataset == NULL)
3567 sigrdataset = query_newrdataset(client);
3568 else if (dns_rdataset_isassociated(sigrdataset))
3569 dns_rdataset_disassociate(sigrdataset);
3571 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
3574 * Add no qname proof.
3576 labels = dns_name_countlabels(cname) + 1;
3577 if (dns_name_countlabels(name) == labels)
3578 dns_name_copy(name, wname, NULL);
3580 dns_name_split(name, labels, NULL, wname);
3582 query_findclosestnsec3(wname, db, NULL, client, rdataset,
3583 sigrdataset, fname, ISC_FALSE, NULL);
3584 if (!dns_rdataset_isassociated(rdataset))
3586 query_addrrset(client, &fname, &rdataset, &sigrdataset,
3587 dbuf, DNS_SECTION_AUTHORITY);
3593 * Replace resources which were consumed by query_addrrset.
3595 if (fname == NULL) {
3596 dbuf = query_getnamebuf(client);
3599 fname = query_newname(client, dbuf, &b);
3602 if (rdataset == NULL)
3603 rdataset = query_newrdataset(client);
3604 else if (dns_rdataset_isassociated(rdataset))
3605 dns_rdataset_disassociate(rdataset);
3607 if (sigrdataset == NULL)
3608 sigrdataset = query_newrdataset(client);
3609 else if (dns_rdataset_isassociated(sigrdataset))
3610 dns_rdataset_disassociate(sigrdataset);
3612 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
3615 * Add the no wildcard proof.
3617 result = dns_name_concatenate(dns_wildcardname,
3618 cname, wname, NULL);
3619 if (result != ISC_R_SUCCESS)
3622 query_findclosestnsec3(wname, db, NULL, client, rdataset,
3623 sigrdataset, fname, nodata, NULL);
3624 if (!dns_rdataset_isassociated(rdataset))
3626 query_addrrset(client, &fname, &rdataset, &sigrdataset,
3627 dbuf, DNS_SECTION_AUTHORITY);
3630 } else if (result == DNS_R_NXDOMAIN) {
3632 result = dns_rdataset_first(rdataset);
3633 if (result == ISC_R_SUCCESS) {
3634 dns_rdataset_current(rdataset, &rdata);
3635 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
3637 if (result == ISC_R_SUCCESS) {
3638 (void)dns_name_fullcompare(name, fname, &order,
3640 (void)dns_name_fullcompare(name, &nsec.next, &order,
3643 * Check for a pathological condition created when
3644 * serving some malformed signed zones and bail out.
3646 if (dns_name_countlabels(name) == nlabels)
3649 if (olabels > nlabels)
3650 dns_name_split(name, olabels, NULL, wname);
3652 dns_name_split(name, nlabels, NULL, wname);
3653 result = dns_name_concatenate(dns_wildcardname,
3654 wname, wname, NULL);
3655 if (result == ISC_R_SUCCESS)
3656 have_wname = ISC_TRUE;
3657 dns_rdata_freestruct(&nsec);
3659 query_addrrset(client, &fname, &rdataset, &sigrdataset,
3660 dbuf, DNS_SECTION_AUTHORITY);
3662 if (rdataset != NULL)
3663 query_putrdataset(client, &rdataset);
3664 if (sigrdataset != NULL)
3665 query_putrdataset(client, &sigrdataset);
3667 query_releasename(client, &fname);
3669 ispositive = ISC_TRUE; /* prevent loop */
3670 if (!dns_name_equal(name, wname)) {
3676 if (rdataset != NULL)
3677 query_putrdataset(client, &rdataset);
3678 if (sigrdataset != NULL)
3679 query_putrdataset(client, &sigrdataset);
3681 query_releasename(client, &fname);
3685 query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db,
3686 dns_dbversion_t *version, dns_name_t **namep,
3687 dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp)
3690 dns_rdataset_t *sigrdataset;
3691 dns_rdata_t sigrdata;
3692 dns_rdata_rrsig_t sig;
3693 unsigned int labels;
3694 isc_buffer_t *dbuf, b;
3696 isc_result_t result;
3699 if ((name->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
3700 query_addrrset(client, namep, rdatasetp, sigrdatasetp,
3701 NULL, DNS_SECTION_AUTHORITY);
3705 if (sigrdatasetp == NULL)
3708 sigrdataset = *sigrdatasetp;
3709 if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
3711 result = dns_rdataset_first(sigrdataset);
3712 if (result != ISC_R_SUCCESS)
3714 dns_rdata_init(&sigrdata);
3715 dns_rdataset_current(sigrdataset, &sigrdata);
3716 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
3717 if (result != ISC_R_SUCCESS)
3720 labels = dns_name_countlabels(name);
3721 if ((unsigned int)sig.labels + 1 >= labels)
3725 query_addwildcardproof(client, db, version, client->query.qname,
3726 ISC_TRUE, ISC_FALSE);
3729 * We'll need some resources...
3731 dbuf = query_getnamebuf(client);
3734 fname = query_newname(client, dbuf, &b);
3737 dns_name_split(name, sig.labels + 1, NULL, fname);
3738 /* This will succeed, since we've stripped labels. */
3739 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,
3740 NULL) == ISC_R_SUCCESS);
3741 query_addrrset(client, &fname, rdatasetp, sigrdatasetp,
3742 dbuf, DNS_SECTION_AUTHORITY);
3746 query_resume(isc_task_t *task, isc_event_t *event) {
3747 dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
3749 ns_client_t *client;
3750 isc_boolean_t fetch_canceled, client_shuttingdown;
3751 isc_result_t result;
3752 isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_ERRORS;
3756 * Resume a query after recursion.
3761 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
3762 client = devent->ev_arg;
3763 REQUIRE(NS_CLIENT_VALID(client));
3764 REQUIRE(task == client->task);
3765 REQUIRE(RECURSING(client));
3767 LOCK(&client->query.fetchlock);
3768 if (client->query.fetch != NULL) {
3770 * This is the fetch we've been waiting for.
3772 INSIST(devent->fetch == client->query.fetch);
3773 client->query.fetch = NULL;
3774 fetch_canceled = ISC_FALSE;
3776 * Update client->now.
3778 isc_stdtime_get(&client->now);
3781 * This is a fetch completion event for a canceled fetch.
3782 * Clean up and don't resume the find.
3784 fetch_canceled = ISC_TRUE;
3786 UNLOCK(&client->query.fetchlock);
3787 INSIST(client->query.fetch == NULL);
3789 client->query.attributes &= ~NS_QUERYATTR_RECURSING;
3790 fetch = devent->fetch;
3791 devent->fetch = NULL;
3794 * If this client is shutting down, or this transaction
3795 * has timed out, do not resume the find.
3797 client_shuttingdown = ns_client_shuttingdown(client);
3798 if (fetch_canceled || client_shuttingdown) {
3799 if (devent->node != NULL)
3800 dns_db_detachnode(devent->db, &devent->node);
3801 if (devent->db != NULL)
3802 dns_db_detach(&devent->db);
3803 query_putrdataset(client, &devent->rdataset);
3804 if (devent->sigrdataset != NULL)
3805 query_putrdataset(client, &devent->sigrdataset);
3806 isc_event_free(&event);
3807 if (fetch_canceled) {
3808 CTRACE(ISC_LOG_ERROR, "fetch cancelled");
3809 query_error(client, DNS_R_SERVFAIL, __LINE__);
3811 query_next(client, ISC_R_CANCELED);
3813 * This may destroy the client.
3815 ns_client_detach(&client);
3817 result = query_find(client, devent, 0);
3818 if (result != ISC_R_SUCCESS) {
3819 if (result == DNS_R_SERVFAIL)
3820 errorloglevel = ISC_LOG_DEBUG(2);
3822 errorloglevel = ISC_LOG_DEBUG(4);
3823 if (isc_log_wouldlog(ns_g_lctx, errorloglevel)) {
3824 dns_resolver_logfetch(fetch, ns_g_lctx,
3827 errorloglevel, ISC_FALSE);
3832 dns_resolver_destroyfetch(&fetch);
3836 query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
3837 dns_name_t *qdomain, dns_rdataset_t *nameservers,
3838 isc_boolean_t resuming)
3840 isc_result_t result;
3841 dns_rdataset_t *rdataset, *sigrdataset;
3842 isc_sockaddr_t *peeraddr;
3845 inc_stats(client, dns_nsstatscounter_recursion);
3848 * We are about to recurse, which means that this client will
3849 * be unavailable for serving new requests for an indeterminate
3850 * amount of time. If this client is currently responsible
3851 * for handling incoming queries, set up a new client
3852 * object to handle them while we are waiting for a
3853 * response. There is no need to replace TCP clients
3854 * because those have already been replaced when the
3855 * connection was accepted (if allowed by the TCP quota).
3857 if (client->recursionquota == NULL) {
3858 result = isc_quota_attach(&ns_g_server->recursionquota,
3859 &client->recursionquota);
3860 if (result == ISC_R_SOFTQUOTA) {
3861 static isc_stdtime_t last = 0;
3863 isc_stdtime_get(&now);
3866 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3869 "recursive-clients soft limit "
3870 "exceeded (%d/%d/%d), "
3871 "aborting oldest query",
3872 client->recursionquota->used,
3873 client->recursionquota->soft,
3874 client->recursionquota->max);
3876 ns_client_killoldestquery(client);
3877 result = ISC_R_SUCCESS;
3878 } else if (result == ISC_R_QUOTA) {
3879 static isc_stdtime_t last = 0;
3881 isc_stdtime_get(&now);
3884 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3887 "no more recursive clients "
3889 ns_g_server->recursionquota.used,
3890 ns_g_server->recursionquota.soft,
3891 ns_g_server->recursionquota.max,
3892 isc_result_totext(result));
3894 ns_client_killoldestquery(client);
3896 if (result == ISC_R_SUCCESS && !client->mortal &&
3897 (client->attributes & NS_CLIENTATTR_TCP) == 0) {
3898 result = ns_client_replace(client);
3899 if (result != ISC_R_SUCCESS) {
3900 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3903 "ns_client_replace() failed: %s",
3904 isc_result_totext(result));
3905 isc_quota_detach(&client->recursionquota);
3908 if (result != ISC_R_SUCCESS)
3910 ns_client_recursing(client);
3914 * Invoke the resolver.
3916 REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
3917 REQUIRE(client->query.fetch == NULL);
3919 rdataset = query_newrdataset(client);
3920 if (rdataset == NULL)
3921 return (ISC_R_NOMEMORY);
3922 if (WANTDNSSEC(client)) {
3923 sigrdataset = query_newrdataset(client);
3924 if (sigrdataset == NULL) {
3925 query_putrdataset(client, &rdataset);
3926 return (ISC_R_NOMEMORY);
3931 if (client->query.timerset == ISC_FALSE)
3932 ns_client_settimeout(client, 60);
3933 if ((client->attributes & NS_CLIENTATTR_TCP) == 0)
3934 peeraddr = &client->peeraddr;
3937 result = dns_resolver_createfetch3(client->view->resolver,
3938 qname, qtype, qdomain, nameservers,
3939 NULL, peeraddr, client->message->id,
3940 client->query.fetchoptions, 0, NULL,
3941 client->task, query_resume, client,
3942 rdataset, sigrdataset,
3943 &client->query.fetch);
3945 if (result == ISC_R_SUCCESS) {
3947 * Record that we're waiting for an event. A client which
3948 * is shutting down will not be destroyed until all the
3949 * events have been received.
3952 query_putrdataset(client, &rdataset);
3953 if (sigrdataset != NULL)
3954 query_putrdataset(client, &sigrdataset);
3961 rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
3962 dns_rdataset_t **rdatasetp)
3964 if (nodep != NULL && *nodep != NULL) {
3965 REQUIRE(dbp != NULL && *dbp != NULL);
3966 dns_db_detachnode(*dbp, nodep);
3968 if (dbp != NULL && *dbp != NULL)
3970 if (zonep != NULL && *zonep != NULL)
3971 dns_zone_detach(zonep);
3972 if (rdatasetp != NULL && *rdatasetp != NULL &&
3973 dns_rdataset_isassociated(*rdatasetp))
3974 dns_rdataset_disassociate(*rdatasetp);
3978 rpz_match_clear(dns_rpz_st_t *st)
3980 rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
3981 st->m.version = NULL;
3984 static inline isc_result_t
3985 rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp,
3986 dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp)
3988 REQUIRE(rdatasetp != NULL);
3990 rpz_clean(zonep, dbp, nodep, rdatasetp);
3991 if (*rdatasetp == NULL) {
3992 *rdatasetp = query_newrdataset(client);
3993 if (*rdatasetp == NULL) {
3994 CTRACE(ISC_LOG_ERROR,
3995 "rpz_ready: query_newrdataset failed");
3996 return (DNS_R_SERVFAIL);
3999 return (ISC_R_SUCCESS);
4003 rpz_st_clear(ns_client_t *client) {
4004 dns_rpz_st_t *st = client->query.rpz_st;
4006 if (st->m.rdataset != NULL)
4007 query_putrdataset(client, &st->m.rdataset);
4008 rpz_match_clear(st);
4010 rpz_clean(NULL, &st->r.db, NULL, NULL);
4011 if (st->r.ns_rdataset != NULL)
4012 query_putrdataset(client, &st->r.ns_rdataset);
4013 if (st->r.r_rdataset != NULL)
4014 query_putrdataset(client, &st->r.r_rdataset);
4016 rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL);
4017 if (st->q.rdataset != NULL)
4018 query_putrdataset(client, &st->q.rdataset);
4019 if (st->q.sigrdataset != NULL)
4020 query_putrdataset(client, &st->q.sigrdataset);
4022 st->m.type = DNS_RPZ_TYPE_BAD;
4023 st->m.policy = DNS_RPZ_POLICY_MISS;
4027 * Get NS, A, or AAAA rrset for response policy zone checks.
4030 rpz_rrset_find(ns_client_t *client, dns_rpz_type_t rpz_type,
4031 dns_name_t *name, dns_rdatatype_t type,
4032 dns_db_t **dbp, dns_dbversion_t *version,
4033 dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
4036 isc_boolean_t is_zone;
4038 dns_fixedname_t fixed;
4040 isc_result_t result;
4041 dns_clientinfomethods_t cm;
4042 dns_clientinfo_t ci;
4044 dns_clientinfomethods_init(&cm, ns_client_sourceip);
4045 dns_clientinfo_init(&ci, client);
4047 st = client->query.rpz_st;
4048 if ((st->state & DNS_RPZ_RECURSING) != 0) {
4049 INSIST(st->r.r_type == type);
4050 INSIST(dns_name_equal(name, st->r_name));
4051 INSIST(*rdatasetp == NULL ||
4052 !dns_rdataset_isassociated(*rdatasetp));
4053 st->state &= ~DNS_RPZ_RECURSING;
4056 if (*rdatasetp != NULL)
4057 query_putrdataset(client, rdatasetp);
4058 *rdatasetp = st->r.r_rdataset;
4059 st->r.r_rdataset = NULL;
4060 result = st->r.r_result;
4061 if (result == DNS_R_DELEGATION) {
4062 CTRACE(ISC_LOG_ERROR, "RPZ recursing");
4063 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4065 "rpz_rrset_find(1) ", result);
4066 st->m.policy = DNS_RPZ_POLICY_ERROR;
4067 result = DNS_R_SERVFAIL;
4072 result = rpz_ready(client, NULL, NULL, NULL, rdatasetp);
4073 if (result != ISC_R_SUCCESS) {
4074 st->m.policy = DNS_RPZ_POLICY_ERROR;
4078 is_zone = ISC_FALSE;
4084 result = query_getdb(client, name, type, 0, &zone, dbp,
4085 &version, &is_zone);
4086 if (result != ISC_R_SUCCESS) {
4087 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4089 "rpz_rrset_find(2) ", result);
4090 st->m.policy = DNS_RPZ_POLICY_ERROR;
4092 dns_zone_detach(&zone);
4096 dns_zone_detach(&zone);
4100 dns_fixedname_init(&fixed);
4101 found = dns_fixedname_name(&fixed);
4102 result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK,
4103 client->now, &node, found,
4104 &cm, &ci, *rdatasetp, NULL);
4105 if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) {
4107 * Try the cache if we're authoritative for an
4108 * ancestor but not the domain itself.
4110 rpz_clean(NULL, dbp, &node, rdatasetp);
4112 dns_db_attach(client->view->cachedb, dbp);
4113 result = dns_db_findext(*dbp, name, version, dns_rdatatype_ns,
4114 0, client->now, &node, found,
4115 &cm, &ci, *rdatasetp, NULL);
4117 rpz_clean(NULL, dbp, &node, NULL);
4118 if (result == DNS_R_DELEGATION) {
4119 rpz_clean(NULL, NULL, NULL, rdatasetp);
4121 * Recurse for NS rrset or A or AAAA rrset for an NS.
4122 * Do not recurse for addresses for the query name.
4124 if (rpz_type == DNS_RPZ_TYPE_IP) {
4125 result = DNS_R_NXRRSET;
4127 dns_name_copy(name, st->r_name, NULL);
4128 result = query_recurse(client, type, st->r_name,
4129 NULL, NULL, resuming);
4130 if (result == ISC_R_SUCCESS) {
4131 st->state |= DNS_RPZ_RECURSING;
4132 result = DNS_R_DELEGATION;
4140 * Check the IP address in an A or AAAA rdataset against
4141 * the IP or NSIP response policy rules of a view.
4144 rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset,
4145 dns_rpz_type_t rpz_type)
4148 dns_dbversion_t *version;
4151 dns_rpz_zone_t *rpz;
4152 isc_result_t result;
4154 st = client->query.rpz_st;
4155 if (st->m.rdataset == NULL) {
4156 st->m.rdataset = query_newrdataset(client);
4157 if (st->m.rdataset == NULL)
4158 return (DNS_R_SERVFAIL);
4162 for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
4164 rpz = ISC_LIST_NEXT(rpz, link)) {
4165 if (!RECURSIONOK(client) && rpz->recursive_only)
4169 * Do not check policy zones that cannot replace a policy
4170 * already known to match.
4172 if (st->m.policy != DNS_RPZ_POLICY_MISS) {
4173 if (st->m.rpz->num < rpz->num)
4175 if (st->m.rpz->num == rpz->num &&
4176 st->m.type < rpz_type)
4181 * Find the database for this policy zone to get its radix tree.
4184 result = rpz_getdb(client, rpz_type, &rpz->origin,
4185 &zone, &db, &version);
4186 if (result != ISC_R_SUCCESS) {
4187 rpz_clean(&zone, &db, NULL, NULL);
4191 * Look for a better (e.g. longer prefix) hit for an IP address
4192 * in this rdataset in this radix tree than than the previous
4193 * hit, if any. Note the domain name and quality of the
4196 dns_db_rpz_findips(rpz, rpz_type, zone, db, version,
4197 rdataset, st, client->query.rpz_st->qname);
4198 rpz_clean(&zone, &db, NULL, NULL);
4200 return (ISC_R_SUCCESS);
4204 * Look for an A or AAAA rdataset
4205 * and check for IP or NSIP rewrite policy rules.
4208 rpz_rewrite_rrset(ns_client_t *client, dns_rpz_type_t rpz_type,
4209 dns_rdatatype_t type, dns_name_t *name,
4210 dns_db_t **dbp, dns_dbversion_t *version,
4211 dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
4213 isc_result_t result;
4215 result = rpz_rrset_find(client, rpz_type, name, type, dbp, version,
4216 rdatasetp, resuming);
4221 result = rpz_rewrite_ip(client, *rdatasetp, rpz_type);
4223 case DNS_R_EMPTYNAME:
4224 case DNS_R_EMPTYWILD:
4225 case DNS_R_NXDOMAIN:
4226 case DNS_R_NCACHENXDOMAIN:
4228 case DNS_R_NCACHENXRRSET:
4229 case ISC_R_NOTFOUND:
4230 result = ISC_R_SUCCESS;
4232 case DNS_R_DELEGATION:
4233 case DNS_R_DUPLICATE:
4238 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, rpz_type,
4239 name, "NS address rewrite rrset ", result);
4240 result = ISC_R_SUCCESS;
4243 if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
4244 client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR;
4245 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
4246 name, "NS address rewrite rrset ", result);
4254 * Look for both A and AAAA rdatasets
4255 * and check for IP or NSIP rewrite policy rules.
4256 * Look only for addresses that will be in the ANSWER section
4257 * when checking for IP rules.
4260 rpz_rewrite_rrsets(ns_client_t *client, dns_rpz_type_t rpz_type,
4261 dns_name_t *name, dns_rdatatype_t type,
4262 dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
4265 dns_dbversion_t *version;
4267 isc_result_t result;
4269 st = client->query.rpz_st;
4272 if ((st->state & DNS_RPZ_DONE_IPv4) == 0 &&
4273 ((rpz_type == DNS_RPZ_TYPE_NSIP) ?
4274 (st->state & DNS_RPZ_HAVE_NSIPv4) :
4275 (st->state & DNS_RPZ_HAVE_IP)) != 0 &&
4276 (type == dns_rdatatype_any || type == dns_rdatatype_a)) {
4277 result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_a,
4278 name, &ipdb, version, rdatasetp,
4280 if (result == ISC_R_SUCCESS)
4281 st->state |= DNS_RPZ_DONE_IPv4;
4283 result = ISC_R_SUCCESS;
4285 if (result == ISC_R_SUCCESS &&
4286 ((rpz_type == DNS_RPZ_TYPE_NSIP) ?
4287 (st->state & DNS_RPZ_HAVE_NSIPv6) :
4288 (st->state & DNS_RPZ_HAVE_IP)) != 0 &&
4289 (type == dns_rdatatype_any || type == dns_rdatatype_aaaa)) {
4290 result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_aaaa,
4291 name, &ipdb, version, rdatasetp,
4295 dns_db_detach(&ipdb);
4300 * Get the rrset from a response policy zone.
4303 rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
4304 dns_name_t *sname, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
4305 dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
4306 dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
4307 dns_rpz_policy_t *policyp)
4309 dns_rpz_policy_t policy;
4310 dns_fixedname_t fixed;
4312 isc_result_t result;
4313 dns_clientinfomethods_t cm;
4314 dns_clientinfo_t ci;
4316 REQUIRE(nodep != NULL);
4318 dns_clientinfomethods_init(&cm, ns_client_sourceip);
4319 dns_clientinfo_init(&ci, client);
4321 result = rpz_ready(client, zonep, dbp, nodep, rdatasetp);
4322 if (result != ISC_R_SUCCESS) {
4323 *policyp = DNS_RPZ_POLICY_ERROR;
4328 * Try to get either a CNAME or the type of record demanded by the
4329 * request from the policy zone.
4332 result = rpz_getdb(client, rpz_type, qnamef, zonep, dbp, versionp);
4333 if (result != ISC_R_SUCCESS) {
4334 *policyp = DNS_RPZ_POLICY_MISS;
4335 return (DNS_R_NXDOMAIN);
4338 dns_fixedname_init(&fixed);
4339 found = dns_fixedname_name(&fixed);
4340 result = dns_db_findext(*dbp, qnamef, *versionp, dns_rdatatype_any, 0,
4341 client->now, nodep, found, &cm, &ci,
4343 if (result == ISC_R_SUCCESS) {
4344 dns_rdatasetiter_t *rdsiter;
4347 result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0,
4349 if (result != ISC_R_SUCCESS) {
4350 dns_db_detachnode(*dbp, nodep);
4351 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
4352 qnamef, "allrdatasets() ", result);
4353 CTRACE(ISC_LOG_ERROR,
4354 "rpz_find_p: allrdatasets failed");
4355 *policyp = DNS_RPZ_POLICY_ERROR;
4356 return (DNS_R_SERVFAIL);
4358 for (result = dns_rdatasetiter_first(rdsiter);
4359 result == ISC_R_SUCCESS;
4360 result = dns_rdatasetiter_next(rdsiter)) {
4361 dns_rdatasetiter_current(rdsiter, *rdatasetp);
4362 if ((*rdatasetp)->type == dns_rdatatype_cname ||
4363 (*rdatasetp)->type == qtype)
4365 dns_rdataset_disassociate(*rdatasetp);
4367 dns_rdatasetiter_destroy(&rdsiter);
4368 if (result != ISC_R_SUCCESS) {
4369 if (result != ISC_R_NOMORE) {
4370 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4371 rpz_type, qnamef, "rdatasetiter ",
4373 CTRACE(ISC_LOG_ERROR,
4374 "rpz_find_p: rdatasetiter_destroy "
4376 *policyp = DNS_RPZ_POLICY_ERROR;
4377 return (DNS_R_SERVFAIL);
4380 * Ask again to get the right DNS_R_DNAME/NXRRSET/...
4381 * result if there is neither a CNAME nor target type.
4383 if (dns_rdataset_isassociated(*rdatasetp))
4384 dns_rdataset_disassociate(*rdatasetp);
4385 dns_db_detachnode(*dbp, nodep);
4387 if (qtype == dns_rdatatype_rrsig ||
4388 qtype == dns_rdatatype_sig)
4389 result = DNS_R_NXRRSET;
4391 result = dns_db_findext(*dbp, qnamef, *versionp,
4392 qtype, 0, client->now,
4393 nodep, found, &cm, &ci,
4399 if ((*rdatasetp)->type != dns_rdatatype_cname) {
4400 policy = DNS_RPZ_POLICY_RECORD;
4402 policy = dns_rpz_decode_cname(rpz, *rdatasetp, sname);
4403 if ((policy == DNS_RPZ_POLICY_RECORD ||
4404 policy == DNS_RPZ_POLICY_WILDCNAME) &&
4405 qtype != dns_rdatatype_cname &&
4406 qtype != dns_rdatatype_any)
4407 result = DNS_R_CNAME;
4411 policy = DNS_RPZ_POLICY_NODATA;
4415 * DNAME policy RRs have very few if any uses that are not
4416 * better served with simple wildcards. Making the work would
4417 * require complications to get the number of labels matched
4418 * in the name or the found name to the main DNS_R_DNAME case
4421 dns_rdataset_disassociate(*rdatasetp);
4422 dns_db_detachnode(*dbp, nodep);
4424 * Fall through to treat it as a miss.
4426 case DNS_R_NXDOMAIN:
4427 case DNS_R_EMPTYNAME:
4429 * If we don't get a qname hit,
4430 * see if it is worth looking for other types.
4432 (void)dns_db_rpz_enabled(*dbp, client->query.rpz_st);
4434 dns_zone_detach(zonep);
4435 result = DNS_R_NXDOMAIN;
4436 policy = DNS_RPZ_POLICY_MISS;
4439 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, qnamef,
4441 CTRACE(ISC_LOG_ERROR,
4442 "rpz_find_p: unexpected result");
4443 return (DNS_R_SERVFAIL);
4451 * Build and look for a QNAME or NSDNAME owner name in a response policy zone.
4454 rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
4455 dns_rpz_type_t rpz_type, dns_rdataset_t **rdatasetp)
4458 dns_rpz_zone_t *rpz;
4459 dns_fixedname_t prefixf, rpz_qnamef;
4460 dns_name_t *prefix, *suffix, *rpz_qname;
4463 dns_dbversion_t *version;
4465 dns_rpz_policy_t policy;
4466 unsigned int labels;
4467 isc_result_t result;
4469 st = client->query.rpz_st;
4474 for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
4476 rpz = ISC_LIST_NEXT(rpz, link)) {
4477 if (!RECURSIONOK(client) && rpz->recursive_only)
4481 * Do not check policy zones that cannot replace a policy
4482 * already known to match.
4484 if (st->m.policy != DNS_RPZ_POLICY_MISS) {
4485 if (st->m.rpz->num < rpz->num)
4487 if (st->m.rpz->num == rpz->num &&
4488 st->m.type < rpz_type)
4492 * Construct the policy's owner name.
4494 dns_fixedname_init(&prefixf);
4495 prefix = dns_fixedname_name(&prefixf);
4496 dns_name_split(qname, 1, prefix, NULL);
4497 if (rpz_type == DNS_RPZ_TYPE_NSDNAME)
4498 suffix = &rpz->nsdname;
4500 suffix = &rpz->origin;
4501 dns_fixedname_init(&rpz_qnamef);
4502 rpz_qname = dns_fixedname_name(&rpz_qnamef);
4504 result = dns_name_concatenate(prefix, suffix,
4506 if (result == ISC_R_SUCCESS)
4508 INSIST(result == DNS_R_NAMETOOLONG);
4510 * Trim the name until it is not too long.
4512 labels = dns_name_countlabels(prefix);
4514 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4516 "concatentate() ", result);
4517 return (ISC_R_SUCCESS);
4519 if (labels+1 == dns_name_countlabels(qname)) {
4520 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1,
4522 "concatentate() ", result);
4524 dns_name_split(prefix, labels - 1, NULL, prefix);
4528 * See if the policy record exists and get its policy.
4530 result = rpz_find(client, qtype, rpz_qname, qname, rpz,
4531 rpz_type, &zone, &db, &version, &node,
4532 rdatasetp, &policy);
4534 case DNS_R_NXDOMAIN:
4536 case DNS_R_SERVFAIL:
4537 rpz_clean(&zone, &db, &node, rdatasetp);
4538 st->m.policy = DNS_RPZ_POLICY_ERROR;
4539 return (DNS_R_SERVFAIL);
4542 * We are dealing with names here.
4543 * With more than one applicable policy, prefer
4544 * the earliest configured policy,
4545 * QNAME over IP over NSDNAME over NSIP,
4546 * and the smallest name.
4547 * Because of the testing above,
4548 * we known st->m.rpz->num >= rpz->num and either
4549 * st->m.rpz->num > rpz->num or st->m.type >= rpz_type
4551 if (st->m.policy != DNS_RPZ_POLICY_MISS &&
4552 rpz->num == st->m.rpz->num &&
4553 (st->m.type < rpz_type ||
4554 (st->m.type == rpz_type &&
4555 0 >= dns_name_compare(rpz_qname, st->qname))))
4559 * This code would block a customer reported information
4560 * leak of rpz rules by rewriting requests in the
4561 * rpz-ip, rpz-nsip, rpz-nsdname,and rpz-passthru TLDs.
4562 * Without this code, a bad guy could request
4563 * 24.0.3.2.10.rpz-ip. to find the policy rule for
4564 * 10.2.3.0/14. It is an insignificant leak and this
4565 * code is not worth its cost, because the bad guy
4566 * could publish "evil.com A 10.2.3.4" and request
4567 * evil.com to get the same information.
4568 * Keep code with "#if 0" in case customer demand
4571 * We have the less frequent case of a triggered
4572 * policy. Check that we have not trigger on one
4573 * of the pretend RPZ TLDs.
4574 * This test would make it impossible to rewrite
4575 * names in TLDs that start with "rpz-" should
4576 * ICANN ever allow such TLDs.
4578 labels = dns_name_countlabels(qname);
4582 dns_name_getlabel(qname, labels-2, &label);
4583 if (label.length >= sizeof(DNS_RPZ_PREFIX)-1 &&
4584 strncasecmp((const char *)label.base+1,
4586 sizeof(DNS_RPZ_PREFIX)-1) == 0)
4591 * Merely log DNS_RPZ_POLICY_DISABLED hits.
4593 if (rpz->policy == DNS_RPZ_POLICY_DISABLED) {
4594 rpz_log_rewrite(client, ISC_TRUE, policy,
4595 rpz_type, zone, rpz_qname);
4599 rpz_match_clear(st);
4601 st->m.type = rpz_type;
4603 st->m.policy = policy;
4604 st->m.result = result;
4605 dns_name_copy(rpz_qname, st->qname, NULL);
4606 if (*rdatasetp != NULL &&
4607 dns_rdataset_isassociated(*rdatasetp)) {
4608 dns_rdataset_t *trdataset;
4610 trdataset = st->m.rdataset;
4611 st->m.rdataset = *rdatasetp;
4612 *rdatasetp = trdataset;
4613 st->m.ttl = ISC_MIN(st->m.rdataset->ttl,
4614 rpz->max_policy_ttl);
4616 st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT,
4617 rpz->max_policy_ttl);
4623 st->m.version = version;
4629 rpz_clean(&zone, &db, &node, rdatasetp);
4630 return (ISC_R_SUCCESS);
4634 rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname,
4635 isc_result_t result, int level, const char *str)
4639 st = client->query.rpz_st;
4642 rpz_log_fail(client, level, DNS_RPZ_TYPE_NSIP, nsname,
4644 if (st->r.ns_rdataset != NULL &&
4645 dns_rdataset_isassociated(st->r.ns_rdataset))
4646 dns_rdataset_disassociate(st->r.ns_rdataset);
4652 * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting.
4655 rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult,
4656 isc_boolean_t resuming)
4659 dns_rdataset_t *rdataset;
4660 dns_fixedname_t nsnamef;
4662 isc_boolean_t ck_ip;
4663 isc_result_t result;
4665 st = client->query.rpz_st;
4667 st = isc_mem_get(client->mctx, sizeof(*st));
4669 return (ISC_R_NOMEMORY);
4671 memset(&st->m, 0, sizeof(st->m));
4672 st->m.type = DNS_RPZ_TYPE_BAD;
4673 st->m.policy = DNS_RPZ_POLICY_MISS;
4675 memset(&st->r, 0, sizeof(st->r));
4676 memset(&st->q, 0, sizeof(st->q));
4677 dns_fixedname_init(&st->_qnamef);
4678 dns_fixedname_init(&st->_r_namef);
4679 dns_fixedname_init(&st->_fnamef);
4680 st->qname = dns_fixedname_name(&st->_qnamef);
4681 st->r_name = dns_fixedname_name(&st->_r_namef);
4682 st->fname = dns_fixedname_name(&st->_fnamef);
4683 client->query.rpz_st = st;
4687 * There is nothing to rewrite if the main query failed.
4695 case DNS_R_EMPTYNAME:
4697 case DNS_R_NXDOMAIN:
4698 case DNS_R_EMPTYWILD:
4699 case DNS_R_NCACHENXDOMAIN:
4700 case DNS_R_NCACHENXRRSET:
4705 case DNS_R_DELEGATION:
4706 case ISC_R_NOTFOUND:
4707 return (ISC_R_SUCCESS);
4709 case ISC_R_TIMEDOUT:
4710 case DNS_R_BROKENCHAIN:
4711 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, DNS_RPZ_TYPE_QNAME,
4712 client->query.qname,
4713 "stop on qresult in rpz_rewrite() ",
4715 return (ISC_R_SUCCESS);
4717 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, DNS_RPZ_TYPE_QNAME,
4718 client->query.qname,
4719 "stop on unrecognized qresult in rpz_rewrite() ",
4721 return (ISC_R_SUCCESS);
4725 if ((st->state & DNS_RPZ_DONE_QNAME) == 0) {
4727 * Check rules for the query name if this is the first time
4728 * for the current qname, i.e. we've not been recursing.
4729 * There is a first time for each name in a CNAME chain.
4731 result = rpz_rewrite_name(client, qtype, client->query.qname,
4732 DNS_RPZ_TYPE_QNAME, &rdataset);
4733 if (result != ISC_R_SUCCESS)
4736 st->r.label = dns_name_countlabels(client->query.qname);
4738 st->state &= ~(DNS_RPZ_DONE_QNAME_IP | DNS_RPZ_DONE_IPv4);
4739 st->state |= DNS_RPZ_DONE_QNAME;
4743 * Check known IP addresses for the query name.
4744 * Any recursion required for the query has already happened.
4745 * Do not check addresses that will not be in the ANSWER section.
4747 if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 &&
4748 (st->state & DNS_RPZ_HAVE_IP) != 0 && ck_ip) {
4749 result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_IP,
4750 client->query.qname, qtype,
4751 &rdataset, resuming);
4752 if (result != ISC_R_SUCCESS)
4754 st->state &= ~DNS_RPZ_DONE_IPv4;
4755 st->state |= DNS_RPZ_DONE_QNAME_IP;
4759 * Stop looking for rules if there are none of the other kinds.
4761 if ((st->state & (DNS_RPZ_HAVE_NSIPv4 | DNS_RPZ_HAVE_NSIPv6 |
4762 DNS_RPZ_HAVE_NSDNAME)) == 0) {
4763 result = ISC_R_SUCCESS;
4767 dns_fixedname_init(&nsnamef);
4768 dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef));
4769 while (st->r.label > client->view->rpz_min_ns_labels) {
4771 * Get NS rrset for each domain in the current qname.
4773 if (st->r.label == dns_name_countlabels(client->query.qname)) {
4774 nsname = client->query.qname;
4776 nsname = dns_fixedname_name(&nsnamef);
4777 dns_name_split(client->query.qname, st->r.label,
4780 if (st->r.ns_rdataset == NULL ||
4781 !dns_rdataset_isassociated(st->r.ns_rdataset)) {
4782 dns_db_t *db = NULL;
4783 result = rpz_rrset_find(client, DNS_RPZ_TYPE_NSDNAME,
4784 nsname, dns_rdatatype_ns,
4785 &db, NULL, &st->r.ns_rdataset,
4789 if (st->m.policy == DNS_RPZ_POLICY_ERROR)
4793 result = dns_rdataset_first(st->r.ns_rdataset);
4794 if (result != ISC_R_SUCCESS)
4796 st->state &= ~(DNS_RPZ_DONE_NSDNAME |
4799 case DNS_R_DELEGATION:
4800 case DNS_R_DUPLICATE:
4803 case DNS_R_EMPTYNAME:
4805 case DNS_R_EMPTYWILD:
4806 case DNS_R_NXDOMAIN:
4807 case DNS_R_NCACHENXDOMAIN:
4808 case DNS_R_NCACHENXRRSET:
4809 case ISC_R_NOTFOUND:
4812 rpz_rewrite_ns_skip(client, nsname, result,
4815 case ISC_R_TIMEDOUT:
4816 case DNS_R_BROKENCHAIN:
4818 rpz_rewrite_ns_skip(client, nsname, result,
4819 DNS_RPZ_DEBUG_LEVEL3,
4820 " NS rpz_rrset_find() ");
4823 rpz_rewrite_ns_skip(client, nsname, result,
4826 " rpz_rrset_find() ");
4831 * Check all NS names.
4835 dns_rdata_t nsrdata = DNS_RDATA_INIT;
4837 dns_rdataset_current(st->r.ns_rdataset, &nsrdata);
4838 result = dns_rdata_tostruct(&nsrdata, &ns, NULL);
4839 dns_rdata_reset(&nsrdata);
4840 if (result != ISC_R_SUCCESS) {
4841 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4842 DNS_RPZ_TYPE_NSIP, nsname,
4843 "rdata_tostruct() ", result);
4844 st->m.policy = DNS_RPZ_POLICY_ERROR;
4848 * Do nothing about "NS ."
4850 if (dns_name_equal(&ns.name, dns_rootname)) {
4851 dns_rdata_freestruct(&ns);
4852 result = dns_rdataset_next(st->r.ns_rdataset);
4856 * Check this NS name if we did not handle it
4857 * during a previous recursion.
4859 if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0 &&
4860 (st->state & DNS_RPZ_HAVE_NSDNAME) != 0) {
4861 result = rpz_rewrite_name(client, qtype,
4863 DNS_RPZ_TYPE_NSDNAME,
4865 if (result != ISC_R_SUCCESS) {
4866 dns_rdata_freestruct(&ns);
4869 st->state |= DNS_RPZ_DONE_NSDNAME;
4872 * Check all IP addresses for this NS name.
4874 result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_NSIP,
4875 &ns.name, dns_rdatatype_any,
4876 &rdataset, resuming);
4877 dns_rdata_freestruct(&ns);
4878 if (result != ISC_R_SUCCESS)
4880 st->state &= ~(DNS_RPZ_DONE_NSDNAME |
4882 result = dns_rdataset_next(st->r.ns_rdataset);
4883 } while (result == ISC_R_SUCCESS);
4884 dns_rdataset_disassociate(st->r.ns_rdataset);
4889 * Use the best, if any, hit.
4891 result = ISC_R_SUCCESS;
4894 if (st->m.policy != DNS_RPZ_POLICY_MISS &&
4895 st->m.policy != DNS_RPZ_POLICY_ERROR &&
4896 st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN)
4897 st->m.policy = st->m.rpz->policy;
4898 if (st->m.policy == DNS_RPZ_POLICY_MISS ||
4899 st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
4900 st->m.policy == DNS_RPZ_POLICY_ERROR) {
4901 if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
4902 result != DNS_R_DELEGATION)
4903 rpz_log_rewrite(client, ISC_FALSE, st->m.policy,
4904 st->m.type, st->m.zone, st->qname);
4905 rpz_match_clear(st);
4907 if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
4908 CTRACE(ISC_LOG_ERROR, "SERVFAIL due to RPZ policy");
4909 st->m.type = DNS_RPZ_TYPE_BAD;
4910 result = DNS_R_SERVFAIL;
4912 query_putrdataset(client, &rdataset);
4913 if ((st->state & DNS_RPZ_RECURSING) == 0)
4914 rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset);
4920 * See if response policy zone rewriting is allowed by a lack of interest
4921 * by the client in DNSSEC or a lack of signatures.
4923 static isc_boolean_t
4924 rpz_ck_dnssec(ns_client_t *client, isc_result_t result,
4925 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
4927 dns_fixedname_t fixed;
4929 dns_rdataset_t trdataset;
4930 dns_rdatatype_t type;
4932 if (client->view->rpz_break_dnssec)
4935 * sigrdataset == NULL if and only !WANTDNSSEC(client)
4937 if (sigrdataset == NULL)
4939 if (dns_rdataset_isassociated(sigrdataset))
4943 * We are happy to rewrite nothing.
4945 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset))
4948 * Do not rewrite if there is any sign of signatures.
4950 if (rdataset->type == dns_rdatatype_nsec ||
4951 rdataset->type == dns_rdatatype_nsec3 ||
4952 rdataset->type == dns_rdatatype_rrsig)
4956 * Look for a signature in a negative cache rdataset.
4958 if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0)
4960 dns_fixedname_init(&fixed);
4961 found = dns_fixedname_name(&fixed);
4962 dns_rdataset_init(&trdataset);
4963 for (result = dns_rdataset_first(rdataset);
4964 result == ISC_R_SUCCESS;
4965 result = dns_rdataset_next(rdataset)) {
4966 dns_ncache_current(rdataset, found, &trdataset);
4967 type = trdataset.type;
4968 dns_rdataset_disassociate(&trdataset);
4969 if (type == dns_rdatatype_nsec ||
4970 type == dns_rdatatype_nsec3 ||
4971 type == dns_rdatatype_rrsig)
4978 * Add a CNAME to the query response, including translating foo.evil.com and
4979 * *.evil.com CNAME *.example.com
4981 * foo.evil.com CNAME foo.evil.com.example.com
4984 rpz_add_cname(ns_client_t *client, dns_rpz_st_t *st,
4985 dns_name_t *cname, dns_name_t *fname, isc_buffer_t *dbuf)
4987 dns_fixedname_t prefix, suffix;
4988 unsigned int labels;
4989 isc_result_t result;
4991 labels = dns_name_countlabels(cname);
4992 if (labels > 2 && dns_name_iswildcard(cname)) {
4993 dns_fixedname_init(&prefix);
4994 dns_name_split(client->query.qname, 1,
4995 dns_fixedname_name(&prefix), NULL);
4996 dns_fixedname_init(&suffix);
4997 dns_name_split(cname, labels-1,
4998 NULL, dns_fixedname_name(&suffix));
4999 result = dns_name_concatenate(dns_fixedname_name(&prefix),
5000 dns_fixedname_name(&suffix),
5002 if (result == DNS_R_NAMETOOLONG)
5003 client->message->rcode = dns_rcode_yxdomain;
5005 result = dns_name_copy(cname, fname, NULL);
5006 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5008 if (result != ISC_R_SUCCESS)
5010 query_keepname(client, fname, dbuf);
5011 result = query_add_cname(client, client->query.qname,
5012 fname, dns_trust_authanswer, st->m.ttl);
5013 if (result != ISC_R_SUCCESS)
5015 rpz_log_rewrite(client, ISC_FALSE, st->m.policy,
5016 st->m.type, st->m.zone, st->qname);
5017 ns_client_qnamereplace(client, fname);
5019 * Turn off DNSSEC because the results of a
5020 * response policy zone cannot verify.
5022 client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
5023 NS_CLIENTATTR_WANTAD);
5024 return (ISC_R_SUCCESS);
5027 #define MAX_RESTARTS 16
5029 #define QUERY_ERROR(r) \
5032 want_restart = ISC_FALSE; \
5036 #define RECURSE_ERROR(r) \
5038 if ((r) == DNS_R_DUPLICATE || (r) == DNS_R_DROP) \
5041 QUERY_ERROR(DNS_R_SERVFAIL); \
5045 * Extract a network address from the RDATA of an A or AAAA
5050 * ISC_R_NOTIMPLEMENTED The rdata is not a known address type.
5053 rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
5055 struct in6_addr in6a;
5057 switch (rdata->type) {
5058 case dns_rdatatype_a:
5059 INSIST(rdata->length == 4);
5060 memmove(&ina.s_addr, rdata->data, 4);
5061 isc_netaddr_fromin(netaddr, &ina);
5062 return (ISC_R_SUCCESS);
5063 case dns_rdatatype_aaaa:
5064 INSIST(rdata->length == 16);
5065 memmove(in6a.s6_addr, rdata->data, 16);
5066 isc_netaddr_fromin6(netaddr, &in6a);
5067 return (ISC_R_SUCCESS);
5069 return (ISC_R_NOTIMPLEMENTED);
5074 * Find the sort order of 'rdata' in the topology-like
5075 * ACL forming the second element in a 2-element top-level
5076 * sortlist statement.
5079 query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) {
5080 isc_netaddr_t netaddr;
5082 if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
5084 return (ns_sortlist_addrorder2(&netaddr, arg));
5088 * Find the sort order of 'rdata' in the matching element
5089 * of a 1-element top-level sortlist statement.
5092 query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) {
5093 isc_netaddr_t netaddr;
5095 if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
5097 return (ns_sortlist_addrorder1(&netaddr, arg));
5101 * Find the sortlist statement that applies to 'client' and set up
5102 * the sortlist info in in client->message appropriately.
5105 setup_query_sortlist(ns_client_t *client) {
5106 isc_netaddr_t netaddr;
5107 dns_rdatasetorderfunc_t order = NULL;
5108 const void *order_arg = NULL;
5110 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
5111 switch (ns_sortlist_setup(client->view->sortlist,
5112 &netaddr, &order_arg)) {
5113 case NS_SORTLISTTYPE_1ELEMENT:
5114 order = query_sortlist_order_1element;
5116 case NS_SORTLISTTYPE_2ELEMENT:
5117 order = query_sortlist_order_2element;
5119 case NS_SORTLISTTYPE_NONE:
5126 dns_message_setsortorder(client->message, order, order_arg);
5130 query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
5131 isc_buffer_t *dbuf, b;
5133 dns_rdataset_t *neg, *negsig;
5134 isc_result_t result = ISC_R_NOMEMORY;
5136 CTRACE(ISC_LOG_DEBUG(3), "query_addnoqnameproof");
5142 dbuf = query_getnamebuf(client);
5145 fname = query_newname(client, dbuf, &b);
5146 neg = query_newrdataset(client);
5147 negsig = query_newrdataset(client);
5148 if (fname == NULL || neg == NULL || negsig == NULL)
5151 result = dns_rdataset_getnoqname(rdataset, fname, neg, negsig);
5152 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5154 query_addrrset(client, &fname, &neg, &negsig, dbuf,
5155 DNS_SECTION_AUTHORITY);
5157 if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) == 0)
5160 if (fname == NULL) {
5161 dbuf = query_getnamebuf(client);
5164 fname = query_newname(client, dbuf, &b);
5167 neg = query_newrdataset(client);
5168 else if (dns_rdataset_isassociated(neg))
5169 dns_rdataset_disassociate(neg);
5171 negsig = query_newrdataset(client);
5172 else if (dns_rdataset_isassociated(negsig))
5173 dns_rdataset_disassociate(negsig);
5174 if (fname == NULL || neg == NULL || negsig == NULL)
5176 result = dns_rdataset_getclosest(rdataset, fname, neg, negsig);
5177 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5179 query_addrrset(client, &fname, &neg, &negsig, dbuf,
5180 DNS_SECTION_AUTHORITY);
5184 query_putrdataset(client, &neg);
5186 query_putrdataset(client, &negsig);
5188 query_releasename(client, &fname);
5192 answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
5195 dns_section_t section = DNS_SECTION_ADDITIONAL;
5196 dns_rdataset_t *rdataset = NULL;
5198 msg = client->message;
5199 for (name = ISC_LIST_HEAD(msg->sections[section]);
5201 name = ISC_LIST_NEXT(name, link))
5202 if (dns_name_equal(name, client->query.qname)) {
5203 for (rdataset = ISC_LIST_HEAD(name->list);
5205 rdataset = ISC_LIST_NEXT(rdataset, link))
5206 if (rdataset->type == qtype)
5210 if (rdataset != NULL) {
5211 ISC_LIST_UNLINK(msg->sections[section], name, link);
5212 ISC_LIST_PREPEND(msg->sections[section], name, link);
5213 ISC_LIST_UNLINK(name->list, rdataset, link);
5214 ISC_LIST_PREPEND(name->list, rdataset, link);
5215 rdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
5219 #define NS_NAME_INIT(A,B) \
5222 A, sizeof(A), sizeof(B), \
5223 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
5224 B, NULL, { (void *)-1, (void *)-1}, \
5228 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
5229 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
5230 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
5232 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
5234 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
5235 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
5236 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
5237 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
5238 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
5239 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
5240 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
5241 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
5242 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
5243 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
5244 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
5245 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
5246 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
5247 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
5248 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
5249 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
5251 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
5253 static dns_name_t rfc1918names[] = {
5254 NS_NAME_INIT(inaddr10, inaddr10_offsets),
5255 NS_NAME_INIT(inaddr16172, inaddr172_offsets),
5256 NS_NAME_INIT(inaddr17172, inaddr172_offsets),
5257 NS_NAME_INIT(inaddr18172, inaddr172_offsets),
5258 NS_NAME_INIT(inaddr19172, inaddr172_offsets),
5259 NS_NAME_INIT(inaddr20172, inaddr172_offsets),
5260 NS_NAME_INIT(inaddr21172, inaddr172_offsets),
5261 NS_NAME_INIT(inaddr22172, inaddr172_offsets),
5262 NS_NAME_INIT(inaddr23172, inaddr172_offsets),
5263 NS_NAME_INIT(inaddr24172, inaddr172_offsets),
5264 NS_NAME_INIT(inaddr25172, inaddr172_offsets),
5265 NS_NAME_INIT(inaddr26172, inaddr172_offsets),
5266 NS_NAME_INIT(inaddr27172, inaddr172_offsets),
5267 NS_NAME_INIT(inaddr28172, inaddr172_offsets),
5268 NS_NAME_INIT(inaddr29172, inaddr172_offsets),
5269 NS_NAME_INIT(inaddr30172, inaddr172_offsets),
5270 NS_NAME_INIT(inaddr31172, inaddr172_offsets),
5271 NS_NAME_INIT(inaddr168192, inaddr192_offsets)
5275 static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
5276 static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org";
5278 static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
5279 static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
5281 static dns_name_t prisoner = NS_NAME_INIT(prisoner_data, prisoner_offsets);
5282 static dns_name_t hostmaster = NS_NAME_INIT(hostmaster_data, hostmaster_offsets);
5285 warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
5287 dns_rdata_t rdata = DNS_RDATA_INIT;
5288 dns_rdata_soa_t soa;
5289 dns_rdataset_t found;
5290 isc_result_t result;
5292 for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) {
5293 if (dns_name_issubdomain(fname, &rfc1918names[i])) {
5294 dns_rdataset_init(&found);
5295 result = dns_ncache_getrdataset(rdataset,
5299 if (result != ISC_R_SUCCESS)
5302 result = dns_rdataset_first(&found);
5303 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5304 dns_rdataset_current(&found, &rdata);
5305 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5306 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5307 if (dns_name_equal(&soa.origin, &prisoner) &&
5308 dns_name_equal(&soa.contact, &hostmaster)) {
5309 char buf[DNS_NAME_FORMATSIZE];
5310 dns_name_format(fname, buf, sizeof(buf));
5311 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
5314 "RFC 1918 response from "
5315 "Internet for %s", buf);
5317 dns_rdataset_disassociate(&found);
5324 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
5325 dns_dbversion_t *version, ns_client_t *client,
5326 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
5327 dns_name_t *fname, isc_boolean_t exact,
5330 unsigned char salt[256];
5332 isc_uint16_t iterations;
5333 isc_result_t result;
5334 unsigned int dboptions;
5335 dns_fixedname_t fixed;
5338 unsigned int skip = 0, labels;
5339 dns_rdata_nsec3_t nsec3;
5340 dns_rdata_t rdata = DNS_RDATA_INIT;
5341 isc_boolean_t optout;
5342 dns_clientinfomethods_t cm;
5343 dns_clientinfo_t ci;
5345 salt_length = sizeof(salt);
5346 result = dns_db_getnsec3parameters(db, version, &hash, NULL,
5347 &iterations, salt, &salt_length);
5348 if (result != ISC_R_SUCCESS)
5351 dns_name_init(&name, NULL);
5352 dns_name_clone(qname, &name);
5353 labels = dns_name_countlabels(&name);
5354 dns_clientinfomethods_init(&cm, ns_client_sourceip);
5355 dns_clientinfo_init(&ci, client);
5358 * Map unknown algorithm to known value.
5360 if (hash == DNS_NSEC3_UNKNOWNALG)
5364 dns_fixedname_init(&fixed);
5365 result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
5366 dns_db_origin(db), hash,
5367 iterations, salt, salt_length);
5368 if (result != ISC_R_SUCCESS)
5371 dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
5372 result = dns_db_findext(db, dns_fixedname_name(&fixed), version,
5373 dns_rdatatype_nsec3, dboptions, client->now,
5374 NULL, fname, &cm, &ci, rdataset, sigrdataset);
5376 if (result == DNS_R_NXDOMAIN) {
5377 if (!dns_rdataset_isassociated(rdataset)) {
5380 result = dns_rdataset_first(rdataset);
5381 INSIST(result == ISC_R_SUCCESS);
5382 dns_rdataset_current(rdataset, &rdata);
5383 dns_rdata_tostruct(&rdata, &nsec3, NULL);
5384 dns_rdata_reset(&rdata);
5385 optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
5386 if (found != NULL && optout &&
5387 dns_name_issubdomain(&name, dns_db_origin(db)))
5389 dns_rdataset_disassociate(rdataset);
5390 if (dns_rdataset_isassociated(sigrdataset))
5391 dns_rdataset_disassociate(sigrdataset);
5393 dns_name_getlabelsequence(qname, skip, labels - skip,
5395 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
5396 NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3),
5397 "looking for closest provable encloser");
5401 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
5402 NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
5403 "expected a exact match NSEC3, got "
5404 "a covering record");
5406 } else if (result != ISC_R_SUCCESS) {
5409 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
5410 NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
5411 "expected covering NSEC3, got an exact match");
5412 if (found == qname) {
5414 dns_name_getlabelsequence(qname, skip, labels - skip,
5416 } else if (found != NULL)
5417 dns_name_copy(&name, found, NULL);
5421 #ifdef ALLOW_FILTER_AAAA_ON_V4
5422 static isc_boolean_t
5423 is_v4_client(ns_client_t *client) {
5424 if (isc_sockaddr_pf(&client->peeraddr) == AF_INET)
5426 if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
5427 IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
5434 dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
5435 dns_dbnode_t *node = NULL;
5436 dns_rdata_soa_t soa;
5437 dns_rdata_t rdata = DNS_RDATA_INIT;
5438 dns_rdataset_t rdataset;
5439 isc_result_t result;
5440 isc_uint32_t ttl = ISC_UINT32_MAX;
5442 dns_rdataset_init(&rdataset);
5444 result = dns_db_getoriginnode(db, &node);
5445 if (result != ISC_R_SUCCESS)
5448 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5449 0, 0, &rdataset, NULL);
5450 if (result != ISC_R_SUCCESS)
5452 result = dns_rdataset_first(&rdataset);
5453 if (result != ISC_R_SUCCESS)
5456 dns_rdataset_current(&rdataset, &rdata);
5457 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5458 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5459 ttl = ISC_MIN(rdataset.ttl, soa.minimum);
5462 if (dns_rdataset_isassociated(&rdataset))
5463 dns_rdataset_disassociate(&rdataset);
5465 dns_db_detachnode(db, &node);
5469 static isc_boolean_t
5470 dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
5471 dns_rdataset_t *sigrdataset)
5473 isc_netaddr_t netaddr;
5474 dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
5475 unsigned int flags = 0;
5476 unsigned int i, count;
5477 isc_boolean_t *aaaaok;
5479 INSIST(client->query.dns64_aaaaok == NULL);
5480 INSIST(client->query.dns64_aaaaoklen == 0);
5481 INSIST(client->query.dns64_aaaa == NULL);
5482 INSIST(client->query.dns64_sigaaaa == NULL);
5487 if (RECURSIONOK(client))
5488 flags |= DNS_DNS64_RECURSIVE;
5490 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
5491 flags |= DNS_DNS64_DNSSEC;
5493 count = dns_rdataset_count(rdataset);
5494 aaaaok = isc_mem_get(client->mctx, sizeof(isc_boolean_t) * count);
5496 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
5497 if (dns_dns64_aaaaok(dns64, &netaddr, client->signer,
5498 &ns_g_server->aclenv, flags, rdataset,
5500 for (i = 0; i < count; i++) {
5501 if (aaaaok != NULL && !aaaaok[i]) {
5502 client->query.dns64_aaaaok = aaaaok;
5503 client->query.dns64_aaaaoklen = count;
5507 if (i == count && aaaaok != NULL)
5508 isc_mem_put(client->mctx, aaaaok,
5509 sizeof(isc_boolean_t) * count);
5513 isc_mem_put(client->mctx, aaaaok,
5514 sizeof(isc_boolean_t) * count);
5519 * Look for the name and type in the redirection zone. If found update
5520 * the arguments as appropriate. Return ISC_TRUE if a update was
5523 * Only perform the update if the client is in the allow query acl and
5524 * returning the update would not cause a DNSSEC validation failure.
5527 redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
5528 dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
5529 dns_rdatatype_t qtype)
5531 dns_db_t *db = NULL;
5532 dns_dbnode_t *node = NULL;
5533 dns_fixedname_t fixed;
5535 dns_rdataset_t trdataset;
5536 isc_result_t result;
5537 dns_rdatatype_t type;
5538 dns_clientinfomethods_t cm;
5539 dns_clientinfo_t ci;
5540 ns_dbversion_t *dbversion;
5542 CTRACE(ISC_LOG_DEBUG(3), "redirect");
5544 if (client->view->redirect == NULL)
5545 return (ISC_R_NOTFOUND);
5547 dns_fixedname_init(&fixed);
5548 found = dns_fixedname_name(&fixed);
5549 dns_rdataset_init(&trdataset);
5551 dns_clientinfomethods_init(&cm, ns_client_sourceip);
5552 dns_clientinfo_init(&ci, client);
5554 if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
5555 return (ISC_R_NOTFOUND);
5557 if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
5558 if (rdataset->trust == dns_trust_secure)
5559 return (ISC_R_NOTFOUND);
5560 if (rdataset->trust == dns_trust_ultimate &&
5561 (rdataset->type == dns_rdatatype_nsec ||
5562 rdataset->type == dns_rdatatype_nsec3))
5563 return (ISC_R_NOTFOUND);
5564 if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
5565 for (result = dns_rdataset_first(rdataset);
5566 result == ISC_R_SUCCESS;
5567 result = dns_rdataset_next(rdataset)) {
5568 dns_ncache_current(rdataset, found, &trdataset);
5569 type = trdataset.type;
5570 dns_rdataset_disassociate(&trdataset);
5571 if (type == dns_rdatatype_nsec ||
5572 type == dns_rdatatype_nsec3 ||
5573 type == dns_rdatatype_rrsig)
5574 return (ISC_R_NOTFOUND);
5579 result = ns_client_checkaclsilent(client, NULL,
5580 dns_zone_getqueryacl(client->view->redirect),
5582 if (result != ISC_R_SUCCESS)
5583 return (ISC_R_NOTFOUND);
5585 result = dns_zone_getdb(client->view->redirect, &db);
5586 if (result != ISC_R_SUCCESS)
5587 return (ISC_R_NOTFOUND);
5589 dbversion = query_findversion(client, db);
5590 if (dbversion == NULL) {
5592 return (ISC_R_NOTFOUND);
5596 * Lookup the requested data in the redirect zone.
5598 result = dns_db_findext(db, client->query.qname, dbversion->version,
5599 qtype, 0, client->now, &node, found, &cm, &ci,
5601 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
5602 if (dns_rdataset_isassociated(rdataset))
5603 dns_rdataset_disassociate(rdataset);
5604 if (dns_rdataset_isassociated(&trdataset))
5605 dns_rdataset_disassociate(&trdataset);
5607 } else if (result != ISC_R_SUCCESS) {
5608 if (dns_rdataset_isassociated(&trdataset))
5609 dns_rdataset_disassociate(&trdataset);
5611 dns_db_detachnode(db, &node);
5613 return (ISC_R_NOTFOUND);
5616 CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done");
5617 dns_name_copy(found, name, NULL);
5618 if (dns_rdataset_isassociated(rdataset))
5619 dns_rdataset_disassociate(rdataset);
5620 if (dns_rdataset_isassociated(&trdataset)) {
5621 dns_rdataset_clone(&trdataset, rdataset);
5622 dns_rdataset_disassociate(&trdataset);
5626 dns_db_detachnode(*dbp, nodep);
5628 dns_db_attachnode(db, node, nodep);
5629 dns_db_attach(db, dbp);
5630 dns_db_detachnode(db, &node);
5632 *versionp = dbversion->version;
5634 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
5635 NS_QUERYATTR_NOADDITIONAL);
5641 * Do the bulk of query processing for the current query of 'client'.
5642 * If 'event' is non-NULL, we are returning from recursion and 'qtype'
5643 * is ignored. Otherwise, 'qtype' is the query type.
5646 query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
5650 dns_rdatatype_t type;
5651 dns_name_t *fname, *zfname, *tname, *prefix;
5652 dns_rdataset_t *rdataset, *trdataset;
5653 dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset;
5654 dns_rdataset_t **sigrdatasetp;
5655 dns_rdata_t rdata = DNS_RDATA_INIT;
5656 dns_rdatasetiter_t *rdsiter;
5657 isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof;
5658 isc_boolean_t is_staticstub_zone;
5659 unsigned int n, nlabels;
5660 dns_namereln_t namereln;
5664 isc_result_t result, eresult, tresult;
5665 dns_fixedname_t fixed;
5666 dns_fixedname_t wildcardname;
5667 dns_dbversion_t *version, *zversion;
5669 dns_rdata_cname_t cname;
5670 dns_rdata_dname_t dname;
5671 unsigned int options;
5672 isc_boolean_t empty_wild;
5673 dns_rdataset_t *noqname;
5674 dns_rpz_st_t *rpz_st;
5675 isc_boolean_t resuming;
5677 isc_boolean_t dns64_exclude, dns64;
5678 isc_boolean_t nxrewrite = ISC_FALSE;
5679 isc_boolean_t redirected = ISC_FALSE;
5680 dns_clientinfomethods_t cm;
5681 dns_clientinfo_t ci;
5683 isc_boolean_t associated;
5684 dns_section_t section;
5686 #ifdef WANT_QUERYTRACE
5688 char qbuf[DNS_NAME_FORMATSIZE];
5691 CTRACE(ISC_LOG_DEBUG(3), "query_find");
5694 * One-time initialization.
5696 * It's especially important to initialize anything that the cleanup
5697 * code might cleanup.
5700 eresult = ISC_R_SUCCESS;
5706 zsigrdataset = NULL;
5713 need_wildcardproof = ISC_FALSE;
5714 empty_wild = ISC_FALSE;
5715 dns64_exclude = dns64 = ISC_FALSE;
5717 resuming = ISC_FALSE;
5718 is_zone = ISC_FALSE;
5719 is_staticstub_zone = ISC_FALSE;
5721 dns_clientinfomethods_init(&cm, ns_client_sourceip);
5722 dns_clientinfo_init(&ci, client);
5724 #ifdef WANT_QUERYTRACE
5725 if (client->query.origqname != NULL)
5726 dns_name_format(client->query.origqname, qbuf,
5729 snprintf(qbuf, sizeof(qbuf), "<unset>");
5731 snprintf(mbuf, sizeof(mbuf) - 1,
5732 "client attr:0x%x, query attr:0x%X, restarts:%d, "
5733 "origqname:%s, timer:%d, authdb:%d, referral:%d",
5735 client->query.attributes,
5736 client->query.restarts, qbuf,
5737 (int) client->query.timerset,
5738 (int) client->query.authdbset,
5739 (int) client->query.isreferral);
5740 CTRACE(ISC_LOG_DEBUG(3), mbuf);
5743 if (event != NULL) {
5745 * We're returning from recursion. Restore the query context
5748 want_restart = ISC_FALSE;
5750 rpz_st = client->query.rpz_st;
5751 if (rpz_st != NULL &&
5752 (rpz_st->state & DNS_RPZ_RECURSING) != 0)
5754 CTRACE(ISC_LOG_DEBUG(3), "resume from RPZ recursion");
5755 #ifdef WANT_QUERYTRACE
5757 char rbuf[DNS_NAME_FORMATSIZE] = "<unset>";
5758 char fbuf[DNS_NAME_FORMATSIZE] = "<unset>";
5759 if (rpz_st->qname != NULL)
5760 dns_name_format(rpz_st->qname,
5761 qbuf, sizeof(qbuf));
5763 snprintf(qbuf, sizeof(qbuf),
5765 if (rpz_st->r_name != NULL)
5766 dns_name_format(rpz_st->r_name,
5767 rbuf, sizeof(rbuf));
5768 if (rpz_st->fname != NULL)
5769 dns_name_format(rpz_st->fname,
5770 fbuf, sizeof(fbuf));
5772 snprintf(mbuf, sizeof(mbuf) - 1,
5773 "rpz qname %s, rname:%s, fname:%s",
5775 CTRACE(ISC_LOG_DEBUG(3), mbuf);
5779 is_zone = rpz_st->q.is_zone;
5780 authoritative = rpz_st->q.authoritative;
5781 zone = rpz_st->q.zone;
5782 rpz_st->q.zone = NULL;
5783 node = rpz_st->q.node;
5784 rpz_st->q.node = NULL;
5786 rpz_st->q.db = NULL;
5787 rdataset = rpz_st->q.rdataset;
5788 rpz_st->q.rdataset = NULL;
5789 sigrdataset = rpz_st->q.sigrdataset;
5790 rpz_st->q.sigrdataset = NULL;
5791 qtype = rpz_st->q.qtype;
5793 rpz_st->r.db = event->db;
5794 if (event->node != NULL)
5795 dns_db_detachnode(event->db, &event->node);
5796 rpz_st->r.r_type = event->qtype;
5797 rpz_st->r.r_rdataset = event->rdataset;
5798 query_putrdataset(client, &event->sigrdataset);
5800 authoritative = ISC_FALSE;
5802 qtype = event->qtype;
5805 rdataset = event->rdataset;
5806 sigrdataset = event->sigrdataset;
5808 INSIST(rdataset != NULL);
5810 if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
5811 type = dns_rdatatype_any;
5815 if (DNS64(client)) {
5816 client->query.attributes &= ~NS_QUERYATTR_DNS64;
5819 if (DNS64EXCLUDE(client)) {
5820 client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE;
5821 dns64_exclude = ISC_TRUE;
5825 * We'll need some resources...
5827 dbuf = query_getnamebuf(client);
5829 CTRACE(ISC_LOG_ERROR,
5830 "query_find: query_getnamebuf failed (1)");
5831 QUERY_ERROR(DNS_R_SERVFAIL);
5834 fname = query_newname(client, dbuf, &b);
5835 if (fname == NULL) {
5836 CTRACE(ISC_LOG_ERROR,
5837 "query_find: query_newname failed (1)");
5838 QUERY_ERROR(DNS_R_SERVFAIL);
5841 if (rpz_st != NULL &&
5842 (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
5843 tname = rpz_st->fname;
5845 tname = dns_fixedname_name(&event->foundname);
5847 result = dns_name_copy(tname, fname, NULL);
5848 if (result != ISC_R_SUCCESS) {
5849 CTRACE(ISC_LOG_ERROR,
5850 "query_find: dns_name_copy failed");
5851 QUERY_ERROR(DNS_R_SERVFAIL);
5854 if (rpz_st != NULL &&
5855 (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
5856 rpz_st->r.r_result = event->result;
5857 result = rpz_st->q.result;
5858 isc_event_free(ISC_EVENT_PTR(&event));
5860 result = event->result;
5862 resuming = ISC_TRUE;
5867 * Not returning from recursion.
5871 * If it's a SIG query, we'll iterate the node.
5873 if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
5874 type = dns_rdatatype_any;
5879 CTRACE(ISC_LOG_DEBUG(3), "query_find: restart");
5880 want_restart = ISC_FALSE;
5881 authoritative = ISC_FALSE;
5883 need_wildcardproof = ISC_FALSE;
5885 if (client->view->checknames &&
5886 !dns_rdata_checkowner(client->query.qname,
5887 client->message->rdclass,
5888 qtype, ISC_FALSE)) {
5889 char namebuf[DNS_NAME_FORMATSIZE];
5890 char typename[DNS_RDATATYPE_FORMATSIZE];
5891 char classname[DNS_RDATACLASS_FORMATSIZE];
5893 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
5894 dns_rdatatype_format(qtype, typename, sizeof(typename));
5895 dns_rdataclass_format(client->message->rdclass, classname,
5897 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
5898 NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
5899 "check-names failure %s/%s/%s", namebuf,
5900 typename, classname);
5901 QUERY_ERROR(DNS_R_REFUSED);
5906 * First we must find the right database.
5908 options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */
5909 if (dns_rdatatype_atparent(qtype) &&
5910 !dns_name_equal(client->query.qname, dns_rootname))
5911 options |= DNS_GETDB_NOEXACT;
5912 result = query_getdb(client, client->query.qname, qtype, options,
5913 &zone, &db, &version, &is_zone);
5914 if (ISC_UNLIKELY((result != ISC_R_SUCCESS || !is_zone) &&
5915 qtype == dns_rdatatype_ds &&
5916 !RECURSIONOK(client) &&
5917 (options & DNS_GETDB_NOEXACT) != 0))
5920 * If the query type is DS, look to see if we are
5921 * authoritative for the child zone.
5923 dns_db_t *tdb = NULL;
5924 dns_zone_t *tzone = NULL;
5925 dns_dbversion_t *tversion = NULL;
5927 tresult = query_getzonedb(client, client->query.qname, qtype,
5928 DNS_GETDB_PARTIAL, &tzone, &tdb,
5930 if (tresult == ISC_R_SUCCESS) {
5931 options &= ~DNS_GETDB_NOEXACT;
5932 query_putrdataset(client, &rdataset);
5936 dns_zone_detach(&zone);
5941 result = ISC_R_SUCCESS;
5944 dns_db_detach(&tdb);
5946 dns_zone_detach(&tzone);
5949 if (result != ISC_R_SUCCESS) {
5950 if (result == DNS_R_REFUSED) {
5951 if (WANTRECURSION(client)) {
5953 dns_nsstatscounter_recurserej);
5955 inc_stats(client, dns_nsstatscounter_authrej);
5956 if (!PARTIALANSWER(client))
5957 QUERY_ERROR(DNS_R_REFUSED);
5959 CTRACE(ISC_LOG_ERROR,
5960 "query_find: query_getdb failed");
5961 QUERY_ERROR(DNS_R_SERVFAIL);
5966 is_staticstub_zone = ISC_FALSE;
5968 authoritative = ISC_TRUE;
5970 dns_zone_gettype(zone) == dns_zone_staticstub)
5971 is_staticstub_zone = ISC_TRUE;
5974 if (event == NULL && client->query.restarts == 0) {
5978 * if is_zone = true, zone = NULL then this is
5979 * a DLZ zone. Don't attempt to attach zone.
5981 dns_zone_attach(zone, &client->query.authzone);
5983 dns_db_attach(db, &client->query.authdb);
5985 client->query.authdbset = ISC_TRUE;
5989 CTRACE(ISC_LOG_DEBUG(3), "query_find: db_find");
5991 * We'll need some resources...
5993 dbuf = query_getnamebuf(client);
5994 if (ISC_UNLIKELY(dbuf == NULL)) {
5995 CTRACE(ISC_LOG_ERROR,
5996 "query_find: query_getnamebuf failed (2)");
5997 QUERY_ERROR(DNS_R_SERVFAIL);
6000 fname = query_newname(client, dbuf, &b);
6001 rdataset = query_newrdataset(client);
6002 if (ISC_UNLIKELY(fname == NULL || rdataset == NULL)) {
6003 CTRACE(ISC_LOG_ERROR,
6004 "query_find: query_newname failed (2)");
6005 QUERY_ERROR(DNS_R_SERVFAIL);
6008 if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) {
6009 sigrdataset = query_newrdataset(client);
6010 if (sigrdataset == NULL) {
6011 CTRACE(ISC_LOG_ERROR,
6012 "query_find: query_newrdataset failed (2)");
6013 QUERY_ERROR(DNS_R_SERVFAIL);
6019 * Now look for an answer in the database.
6021 result = dns_db_findext(db, client->query.qname, version, type,
6022 client->query.dboptions, client->now,
6023 &node, fname, &cm, &ci, rdataset, sigrdataset);
6026 CTRACE(ISC_LOG_DEBUG(3), "query_find: resume");
6030 * Rate limit these responses to this client.
6031 * Do not delay counting and handling obvious referrals,
6032 * since those won't come here again.
6033 * Delay handling delegations for which we are certain to recurse and
6034 * return here (DNS_R_DELEGATION, not a child of one of our
6035 * own zones, and recursion enabled)
6036 * Don't mess with responses rewritten by RPZ
6037 * Count each response at most once.
6039 if (client->view->rrl != NULL &&
6040 ((fname != NULL && dns_name_isabsolute(fname)) ||
6041 (result == ISC_R_NOTFOUND && !RECURSIONOK(client))) &&
6042 !(result == DNS_R_DELEGATION && !is_zone && RECURSIONOK(client)) &&
6043 (client->query.rpz_st == NULL ||
6044 (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0)&&
6045 (client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0) {
6046 dns_rdataset_t nc_rdataset;
6047 isc_boolean_t wouldlog;
6048 char log_buf[DNS_RRL_LOG_BUF_LEN];
6049 isc_result_t nc_result, resp_result;
6050 dns_rrl_result_t rrl_result;
6052 client->query.attributes |= NS_QUERYATTR_RRL_CHECKED;
6054 wouldlog = isc_log_wouldlog(ns_g_lctx, DNS_RRL_LOG_DROP);
6056 if (result == DNS_R_NXDOMAIN) {
6058 * Use the database origin name to rate limit NXDOMAIN
6061 tname = dns_db_origin(db);
6062 resp_result = result;
6063 } else if (result == DNS_R_NCACHENXDOMAIN &&
6065 dns_rdataset_isassociated(rdataset) &&
6066 (rdataset->attributes &
6067 DNS_RDATASETATTR_NEGATIVE) != 0) {
6069 * Try to use owner name in the negative cache SOA.
6071 dns_fixedname_init(&fixed);
6072 dns_rdataset_init(&nc_rdataset);
6073 for (nc_result = dns_rdataset_first(rdataset);
6074 nc_result == ISC_R_SUCCESS;
6075 nc_result = dns_rdataset_next(rdataset)) {
6076 dns_ncache_current(rdataset,
6077 dns_fixedname_name(&fixed),
6079 if (nc_rdataset.type == dns_rdatatype_soa) {
6080 dns_rdataset_disassociate(&nc_rdataset);
6081 tname = dns_fixedname_name(&fixed);
6084 dns_rdataset_disassociate(&nc_rdataset);
6086 resp_result = DNS_R_NXDOMAIN;
6087 } else if (result == DNS_R_NXRRSET ||
6088 result == DNS_R_EMPTYNAME) {
6089 resp_result = DNS_R_NXRRSET;
6090 } else if (result == DNS_R_DELEGATION) {
6091 resp_result = result;
6092 } else if (result == ISC_R_NOTFOUND) {
6094 * Handle referral to ".", including when recursion
6095 * is off or not requested and the hints have not
6096 * been loaded or we have "additional-from-cache no".
6098 tname = dns_rootname;
6099 resp_result = DNS_R_DELEGATION;
6101 resp_result = ISC_R_SUCCESS;
6103 rrl_result = dns_rrl(client->view, &client->peeraddr,
6104 ISC_TF((client->attributes
6105 & NS_CLIENTATTR_TCP) != 0),
6106 client->message->rdclass, qtype, tname,
6107 resp_result, client->now,
6108 wouldlog, log_buf, sizeof(log_buf));
6109 if (rrl_result != DNS_RRL_RESULT_OK) {
6111 * Log dropped or slipped responses in the query
6112 * category so that requests are not silently lost.
6113 * Starts of rate-limited bursts are logged in
6114 * DNS_LOGCATEGORY_RRL.
6116 * Dropped responses are counted with dropped queries
6117 * in QryDropped while slipped responses are counted
6118 * with other truncated responses in RespTruncated.
6121 ns_client_log(client, DNS_LOGCATEGORY_RRL,
6126 if (!client->view->rrl->log_only) {
6127 if (rrl_result == DNS_RRL_RESULT_DROP) {
6129 * These will also be counted in
6130 * dns_nsstatscounter_dropped
6133 dns_nsstatscounter_ratedropped);
6134 QUERY_ERROR(DNS_R_DROP);
6137 * These will also be counted in
6138 * dns_nsstatscounter_truncatedresp
6141 dns_nsstatscounter_rateslipped);
6142 client->message->flags |=
6144 if (resp_result == DNS_R_NXDOMAIN)
6145 client->message->rcode =
6152 #endif /* USE_RRL */
6154 if (!ISC_LIST_EMPTY(client->view->rpz_zones) &&
6155 (RECURSIONOK(client) || !client->view->rpz_recursive_only) &&
6156 rpz_ck_dnssec(client, result, rdataset, sigrdataset) &&
6157 !RECURSING(client) &&
6158 (client->query.rpz_st == NULL ||
6159 (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) &&
6160 !dns_name_equal(client->query.qname, dns_rootname)) {
6161 isc_result_t rresult;
6163 rresult = rpz_rewrite(client, qtype, result, resuming);
6164 rpz_st = client->query.rpz_st;
6168 case DNS_R_DELEGATION:
6170 * recursing for NS names or addresses,
6171 * so save the main query state
6173 rpz_st->q.qtype = qtype;
6174 rpz_st->q.is_zone = is_zone;
6175 rpz_st->q.authoritative = authoritative;
6176 rpz_st->q.zone = zone;
6180 rpz_st->q.node = node;
6182 rpz_st->q.rdataset = rdataset;
6184 rpz_st->q.sigrdataset = sigrdataset;
6186 dns_name_copy(fname, rpz_st->fname, NULL);
6187 rpz_st->q.result = result;
6188 client->query.attributes |= NS_QUERYATTR_RECURSING;
6191 RECURSE_ERROR(rresult);
6194 if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS)
6195 rpz_st->state |= DNS_RPZ_REWRITTEN;
6196 if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS &&
6197 rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU &&
6198 rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
6199 if (rpz_st->m.type == DNS_RPZ_TYPE_QNAME) {
6200 result = dns_name_copy(client->query.qname,
6202 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6204 rpz_clean(&zone, &db, &node, NULL);
6205 if (rpz_st->m.rdataset != NULL) {
6206 query_putrdataset(client, &rdataset);
6207 rdataset = rpz_st->m.rdataset;
6208 rpz_st->m.rdataset = NULL;
6209 } else if (rdataset != NULL &&
6210 dns_rdataset_isassociated(rdataset)) {
6211 dns_rdataset_disassociate(rdataset);
6213 node = rpz_st->m.node;
6214 rpz_st->m.node = NULL;
6216 rpz_st->m.db = NULL;
6217 version = rpz_st->m.version;
6218 rpz_st->m.version = NULL;
6219 zone = rpz_st->m.zone;
6220 rpz_st->m.zone = NULL;
6222 switch (rpz_st->m.policy) {
6223 case DNS_RPZ_POLICY_NXDOMAIN:
6224 result = DNS_R_NXDOMAIN;
6225 nxrewrite = ISC_TRUE;
6227 case DNS_RPZ_POLICY_NODATA:
6228 result = DNS_R_NXRRSET;
6229 nxrewrite = ISC_TRUE;
6231 case DNS_RPZ_POLICY_RECORD:
6232 result = rpz_st->m.result;
6233 if (qtype == dns_rdatatype_any &&
6234 result != DNS_R_CNAME) {
6236 * We will add all of the rdatasets of
6237 * the node by iterating, setting the
6240 if (dns_rdataset_isassociated(rdataset))
6241 dns_rdataset_disassociate(rdataset);
6244 * We will add this rdataset.
6246 rdataset->ttl = ISC_MIN(rdataset->ttl,
6250 case DNS_RPZ_POLICY_WILDCNAME:
6251 result = dns_rdataset_first(rdataset);
6252 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6253 dns_rdataset_current(rdataset, &rdata);
6254 result = dns_rdata_tostruct(&rdata, &cname,
6256 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6257 dns_rdata_reset(&rdata);
6258 result = rpz_add_cname(client, rpz_st,
6261 if (result != ISC_R_SUCCESS)
6264 want_restart = ISC_TRUE;
6266 case DNS_RPZ_POLICY_CNAME:
6268 * Add overridding CNAME from a named.conf
6269 * response-policy statement
6271 result = rpz_add_cname(client, rpz_st,
6272 &rpz_st->m.rpz->cname,
6274 if (result != ISC_R_SUCCESS)
6277 want_restart = ISC_TRUE;
6284 * Turn off DNSSEC because the results of a
6285 * response policy zone cannot verify.
6287 client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
6288 NS_CLIENTATTR_WANTAD);
6289 client->message->flags &= ~DNS_MESSAGEFLAG_AD;
6290 query_putrdataset(client, &sigrdataset);
6291 rpz_st->q.is_zone = is_zone;
6293 rpz_log_rewrite(client, ISC_FALSE, rpz_st->m.policy,
6294 rpz_st->m.type, zone, rpz_st->qname);
6301 * This case is handled in the main line below.
6307 * These cases are handled in the main line below.
6310 authoritative = ISC_FALSE;
6312 case ISC_R_NOTFOUND:
6314 * The cache doesn't even have the root NS. Get them from
6321 if (client->view->hints == NULL) {
6322 /* We have no hints. */
6323 result = ISC_R_FAILURE;
6325 dns_db_attach(client->view->hints, &db);
6326 result = dns_db_findext(db, dns_rootname,
6327 NULL, dns_rdatatype_ns,
6328 0, client->now, &node,
6330 rdataset, sigrdataset);
6332 if (result != ISC_R_SUCCESS) {
6334 * Nonsensical root hints may require cleanup.
6336 if (dns_rdataset_isassociated(rdataset))
6337 dns_rdataset_disassociate(rdataset);
6338 if (sigrdataset != NULL &&
6339 dns_rdataset_isassociated(sigrdataset))
6340 dns_rdataset_disassociate(sigrdataset);
6342 dns_db_detachnode(db, &node);
6345 * We don't have any root server hints, but
6346 * we may have working forwarders, so try to
6349 if (RECURSIONOK(client)) {
6350 result = query_recurse(client, qtype,
6351 client->query.qname,
6352 NULL, NULL, resuming);
6353 if (result == ISC_R_SUCCESS) {
6354 client->query.attributes |=
6355 NS_QUERYATTR_RECURSING;
6357 client->query.attributes |=
6360 client->query.attributes |=
6361 NS_QUERYATTR_DNS64EXCLUDE;
6363 RECURSE_ERROR(result);
6366 /* Unable to give root server referral. */
6367 CTRACE(ISC_LOG_ERROR,
6368 "unable to give root server referral");
6369 QUERY_ERROR(DNS_R_SERVFAIL);
6374 * XXXRTH We should trigger root server priming here.
6377 case DNS_R_DELEGATION:
6378 authoritative = ISC_FALSE;
6381 * Look to see if we are authoritative for the
6382 * child zone if the query type is DS.
6384 if (!RECURSIONOK(client) &&
6385 (options & DNS_GETDB_NOEXACT) != 0 &&
6386 qtype == dns_rdatatype_ds) {
6387 dns_db_t *tdb = NULL;
6388 dns_zone_t *tzone = NULL;
6389 dns_dbversion_t *tversion = NULL;
6390 result = query_getzonedb(client,
6391 client->query.qname,
6396 if (result == ISC_R_SUCCESS) {
6397 options &= ~DNS_GETDB_NOEXACT;
6398 query_putrdataset(client, &rdataset);
6399 if (sigrdataset != NULL)
6400 query_putrdataset(client,
6403 query_releasename(client,
6406 dns_db_detachnode(db, &node);
6410 dns_zone_detach(&zone);
6414 authoritative = ISC_TRUE;
6418 dns_db_detach(&tdb);
6420 dns_zone_detach(&tzone);
6423 * We're authoritative for an ancestor of QNAME.
6425 if (!USECACHE(client) || !RECURSIONOK(client)) {
6426 dns_fixedname_init(&fixed);
6427 dns_name_copy(fname,
6428 dns_fixedname_name(&fixed), NULL);
6431 * If we don't have a cache, this is the best
6434 * If the client is making a nonrecursive
6435 * query we always give out the authoritative
6436 * delegation. This way even if we get
6437 * junk in our cache, we won't fail in our
6438 * role as the delegating authority if another
6439 * nameserver asks us about a delegated
6442 * We enable the retrieval of glue for this
6443 * database by setting client->query.gluedb.
6445 client->query.gluedb = db;
6446 client->query.isreferral = ISC_TRUE;
6448 * We must ensure NOADDITIONAL is off,
6449 * because the generation of
6450 * additional data is required in
6453 client->query.attributes &=
6454 ~NS_QUERYATTR_NOADDITIONAL;
6455 if (sigrdataset != NULL)
6456 sigrdatasetp = &sigrdataset;
6458 sigrdatasetp = NULL;
6459 query_addrrset(client, &fname,
6460 &rdataset, sigrdatasetp,
6461 dbuf, DNS_SECTION_AUTHORITY);
6462 client->query.gluedb = NULL;
6463 if (WANTDNSSEC(client))
6464 query_addds(client, db, node, version,
6465 dns_fixedname_name(&fixed));
6468 * We might have a better answer or delegation
6469 * in the cache. We'll remember the current
6470 * values of fname, rdataset, and sigrdataset.
6471 * We'll then go looking for QNAME in the
6472 * cache. If we find something better, we'll
6475 query_keepname(client, fname, dbuf);
6479 zrdataset = rdataset;
6481 zsigrdataset = sigrdataset;
6483 dns_db_detachnode(db, &node);
6487 dns_db_attach(client->view->cachedb, &db);
6488 is_zone = ISC_FALSE;
6492 if (zfname != NULL &&
6493 (!dns_name_issubdomain(fname, zfname) ||
6494 (is_staticstub_zone &&
6495 dns_name_equal(fname, zfname)))) {
6497 * In the following cases use "authoritative"
6498 * data instead of the cache delegation:
6499 * 1. We've already got a delegation from
6500 * authoritative data, and it is better
6501 * than what we found in the cache.
6502 * 2. The query name matches the origin name
6503 * of a static-stub zone. This needs to be
6504 * considered for the case where the NS of
6505 * the static-stub zone and the cached NS
6506 * are different. We still need to contact
6507 * the nameservers configured in the
6510 query_releasename(client, &fname);
6514 * We've already done query_keepname() on
6515 * zfname, so we must set dbuf to NULL to
6516 * prevent query_addrrset() from trying to
6517 * call query_keepname() again.
6520 query_putrdataset(client, &rdataset);
6521 if (sigrdataset != NULL)
6522 query_putrdataset(client,
6524 rdataset = zrdataset;
6526 sigrdataset = zsigrdataset;
6527 zsigrdataset = NULL;
6531 * We don't clean up zdb here because we
6532 * may still need it. It will get cleaned
6533 * up by the main cleanup code.
6537 if (RECURSIONOK(client)) {
6541 if (dns_rdatatype_atparent(type))
6542 result = query_recurse(client, qtype,
6543 client->query.qname,
6544 NULL, NULL, resuming);
6546 result = query_recurse(client,
6548 client->query.qname,
6549 NULL, NULL, resuming);
6551 result = query_recurse(client, qtype,
6552 client->query.qname,
6556 if (result == ISC_R_SUCCESS) {
6557 client->query.attributes |=
6558 NS_QUERYATTR_RECURSING;
6560 client->query.attributes |=
6563 client->query.attributes |=
6564 NS_QUERYATTR_DNS64EXCLUDE;
6565 } else if (result == DNS_R_DUPLICATE ||
6566 result == DNS_R_DROP)
6567 QUERY_ERROR(result);
6569 RECURSE_ERROR(result);
6571 dns_fixedname_init(&fixed);
6572 dns_name_copy(fname,
6573 dns_fixedname_name(&fixed), NULL);
6575 * This is the best answer.
6577 client->query.attributes |=
6578 NS_QUERYATTR_CACHEGLUEOK;
6579 client->query.gluedb = zdb;
6580 client->query.isreferral = ISC_TRUE;
6582 * We must ensure NOADDITIONAL is off,
6583 * because the generation of
6584 * additional data is required in
6587 client->query.attributes &=
6588 ~NS_QUERYATTR_NOADDITIONAL;
6589 if (sigrdataset != NULL)
6590 sigrdatasetp = &sigrdataset;
6592 sigrdatasetp = NULL;
6593 query_addrrset(client, &fname,
6594 &rdataset, sigrdatasetp,
6595 dbuf, DNS_SECTION_AUTHORITY);
6596 client->query.gluedb = NULL;
6597 client->query.attributes &=
6598 ~NS_QUERYATTR_CACHEGLUEOK;
6599 if (WANTDNSSEC(client))
6600 query_addds(client, db, node, version,
6601 dns_fixedname_name(&fixed));
6606 case DNS_R_EMPTYNAME:
6611 #ifdef dns64_bis_return_excluded_addresses
6614 if (dns64 && !dns64_exclude)
6618 * Restore the answers from the previous AAAA lookup.
6620 if (rdataset != NULL)
6621 query_putrdataset(client, &rdataset);
6622 if (sigrdataset != NULL)
6623 query_putrdataset(client, &sigrdataset);
6624 rdataset = client->query.dns64_aaaa;
6625 sigrdataset = client->query.dns64_sigaaaa;
6626 client->query.dns64_aaaa = NULL;
6627 client->query.dns64_sigaaaa = NULL;
6628 if (fname == NULL) {
6629 dbuf = query_getnamebuf(client);
6631 CTRACE(ISC_LOG_ERROR,
6633 "query_getnamebuf failed (3)");
6634 QUERY_ERROR(DNS_R_SERVFAIL);
6637 fname = query_newname(client, dbuf, &b);
6638 if (fname == NULL) {
6639 CTRACE(ISC_LOG_ERROR,
6641 "query_newname failed (3)");
6642 QUERY_ERROR(DNS_R_SERVFAIL);
6646 dns_name_copy(client->query.qname, fname, NULL);
6648 #ifdef dns64_bis_return_excluded_addresses
6650 * Resume the diverted processing of the AAAA response?
6655 } else if (result == DNS_R_NXRRSET &&
6656 !ISC_LIST_EMPTY(client->view->dns64) &&
6657 client->message->rdclass == dns_rdataclass_in &&
6658 qtype == dns_rdatatype_aaaa)
6661 * Look to see if there are A records for this
6664 INSIST(client->query.dns64_aaaa == NULL);
6665 INSIST(client->query.dns64_sigaaaa == NULL);
6666 client->query.dns64_aaaa = rdataset;
6667 client->query.dns64_sigaaaa = sigrdataset;
6668 client->query.dns64_ttl = dns64_ttl(db, version);
6669 query_releasename(client, &fname);
6670 dns_db_detachnode(db, &node);
6673 type = qtype = dns_rdatatype_a;
6674 rpz_st = client->query.rpz_st;
6675 if (rpz_st != NULL) {
6677 * Arrange for RPZ rewriting of any A records.
6679 if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0)
6680 is_zone = rpz_st->q.is_zone;
6681 rpz_st_clear(client);
6688 * Look for a NSEC3 record if we don't have a NSEC record.
6693 if (!dns_rdataset_isassociated(rdataset) &&
6694 WANTDNSSEC(client)) {
6695 if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
6699 dns_fixedname_init(&fixed);
6700 found = dns_fixedname_name(&fixed);
6701 qname = client->query.qname;
6703 query_findclosestnsec3(qname, db, version,
6708 * Did we find the closest provable encloser
6709 * instead? If so add the nearest to the
6710 * closest provable encloser.
6712 if (dns_rdataset_isassociated(rdataset) &&
6713 !dns_name_equal(qname, found) &&
6715 qtype != dns_rdatatype_ds))
6721 * Add the closest provable encloser.
6723 query_addrrset(client, &fname,
6724 &rdataset, &sigrdataset,
6726 DNS_SECTION_AUTHORITY);
6728 count = dns_name_countlabels(found)
6730 skip = dns_name_countlabels(qname) -
6732 dns_name_getlabelsequence(qname, skip,
6736 fixfname(client, &fname, &dbuf, &b);
6737 fixrdataset(client, &rdataset);
6738 fixrdataset(client, &sigrdataset);
6739 if (fname == NULL ||
6741 sigrdataset == NULL) {
6742 CTRACE(ISC_LOG_ERROR,
6745 "closest encloser");
6746 QUERY_ERROR(DNS_R_SERVFAIL);
6750 * 'nearest' doesn't exist so
6751 * 'exist' is set to ISC_FALSE.
6753 query_findclosestnsec3(found, db,
6763 query_releasename(client, &fname);
6764 query_addwildcardproof(client, db, version,
6765 client->query.qname,
6766 ISC_FALSE, ISC_TRUE);
6769 if (dns_rdataset_isassociated(rdataset)) {
6771 * If we've got a NSEC record, we need to save the
6772 * name now because we're going call query_addsoa()
6773 * below, and it needs to use the name buffer.
6775 query_keepname(client, fname, dbuf);
6776 } else if (fname != NULL) {
6778 * We're not going to use fname, and need to release
6779 * our hold on the name buffer so query_addsoa()
6782 query_releasename(client, &fname);
6786 * Add SOA to the additional section if generated by a RPZ
6789 associated = dns_rdataset_isassociated(rdataset);
6790 section = nxrewrite ? DNS_SECTION_ADDITIONAL :
6791 DNS_SECTION_AUTHORITY;
6793 result = query_addsoa(client, db, version, ISC_UINT32_MAX,
6794 associated, section);
6795 if (result != ISC_R_SUCCESS) {
6796 QUERY_ERROR(result);
6801 * Add NSEC record if we found one.
6803 if (WANTDNSSEC(client)) {
6804 if (dns_rdataset_isassociated(rdataset))
6805 query_addnxrrsetnsec(client, db, version,
6811 case DNS_R_EMPTYWILD:
6812 empty_wild = ISC_TRUE;
6815 case DNS_R_NXDOMAIN:
6818 tresult = redirect(client, fname, rdataset, &node,
6819 &db, &version, type);
6820 if (tresult == ISC_R_SUCCESS)
6822 if (tresult == DNS_R_NXRRSET) {
6823 redirected = ISC_TRUE;
6824 goto iszone_nxrrset;
6826 if (tresult == DNS_R_NCACHENXRRSET) {
6827 redirected = ISC_TRUE;
6828 is_zone = ISC_FALSE;
6829 goto ncache_nxrrset;
6832 if (dns_rdataset_isassociated(rdataset)) {
6834 * If we've got a NSEC record, we need to save the
6835 * name now because we're going call query_addsoa()
6836 * below, and it needs to use the name buffer.
6838 query_keepname(client, fname, dbuf);
6839 } else if (fname != NULL) {
6841 * We're not going to use fname, and need to release
6842 * our hold on the name buffer so query_addsoa()
6845 query_releasename(client, &fname);
6849 * Add SOA to the additional section if generated by a
6852 * If the query was for a SOA record force the
6853 * ttl to zero so that it is possible for clients to find
6854 * the containing zone of an arbitrary name with a stub
6855 * resolver and not have it cached.
6857 associated = dns_rdataset_isassociated(rdataset);
6858 section = nxrewrite ? DNS_SECTION_ADDITIONAL :
6859 DNS_SECTION_AUTHORITY;
6860 ttl = ISC_UINT32_MAX;
6861 if (!nxrewrite && qtype == dns_rdatatype_soa &&
6862 zone != NULL && dns_zone_getzeronosoattl(zone))
6864 result = query_addsoa(client, db, version, ttl, associated,
6866 if (result != ISC_R_SUCCESS) {
6867 QUERY_ERROR(result);
6871 if (WANTDNSSEC(client)) {
6873 * Add NSEC record if we found one.
6875 if (dns_rdataset_isassociated(rdataset))
6876 query_addrrset(client, &fname, &rdataset,
6878 NULL, DNS_SECTION_AUTHORITY);
6879 query_addwildcardproof(client, db, version,
6880 client->query.qname, ISC_FALSE,
6885 * Set message rcode.
6888 client->message->rcode = dns_rcode_noerror;
6890 client->message->rcode = dns_rcode_nxdomain;
6893 case DNS_R_NCACHENXDOMAIN:
6894 tresult = redirect(client, fname, rdataset, &node,
6895 &db, &version, type);
6896 if (tresult == ISC_R_SUCCESS)
6898 if (tresult == DNS_R_NXRRSET) {
6899 redirected = ISC_TRUE;
6901 goto iszone_nxrrset;
6903 if (tresult == DNS_R_NCACHENXRRSET) {
6904 redirected = ISC_TRUE;
6906 goto ncache_nxrrset;
6910 case DNS_R_NCACHENXRRSET:
6913 authoritative = ISC_FALSE;
6915 * Set message rcode, if required.
6917 if (result == DNS_R_NCACHENXDOMAIN)
6918 client->message->rcode = dns_rcode_nxdomain;
6920 * Look for RFC 1918 leakage from Internet.
6922 if (result == DNS_R_NCACHENXDOMAIN &&
6923 qtype == dns_rdatatype_ptr &&
6924 client->message->rdclass == dns_rdataclass_in &&
6925 dns_name_countlabels(fname) == 7)
6926 warn_rfc1918(client, fname, rdataset);
6928 #ifdef dns64_bis_return_excluded_addresses
6931 if (dns64 && !dns64_exclude)
6935 * Restore the answers from the previous AAAA lookup.
6937 if (rdataset != NULL)
6938 query_putrdataset(client, &rdataset);
6939 if (sigrdataset != NULL)
6940 query_putrdataset(client, &sigrdataset);
6941 rdataset = client->query.dns64_aaaa;
6942 sigrdataset = client->query.dns64_sigaaaa;
6943 client->query.dns64_aaaa = NULL;
6944 client->query.dns64_sigaaaa = NULL;
6945 if (fname == NULL) {
6946 dbuf = query_getnamebuf(client);
6948 CTRACE(ISC_LOG_ERROR,
6950 "query_getnamebuf failed (4)");
6951 QUERY_ERROR(DNS_R_SERVFAIL);
6954 fname = query_newname(client, dbuf, &b);
6955 if (fname == NULL) {
6956 CTRACE(ISC_LOG_ERROR,
6958 "query_newname failed (4)");
6959 QUERY_ERROR(DNS_R_SERVFAIL);
6963 dns_name_copy(client->query.qname, fname, NULL);
6965 #ifdef dns64_bis_return_excluded_addresses
6969 } else if (result == DNS_R_NCACHENXRRSET &&
6970 !ISC_LIST_EMPTY(client->view->dns64) &&
6971 client->message->rdclass == dns_rdataclass_in &&
6972 qtype == dns_rdatatype_aaaa)
6975 * Look to see if there are A records for this
6978 INSIST(client->query.dns64_aaaa == NULL);
6979 INSIST(client->query.dns64_sigaaaa == NULL);
6980 client->query.dns64_aaaa = rdataset;
6981 client->query.dns64_sigaaaa = sigrdataset;
6983 * If the ttl is zero we need to workout if we have just
6984 * decremented to zero or if there was no negative cache
6985 * ttl in the answer.
6987 if (rdataset->ttl != 0)
6988 client->query.dns64_ttl = rdataset->ttl;
6989 else if (dns_rdataset_first(rdataset) == ISC_R_SUCCESS)
6990 client->query.dns64_ttl = 0;
6991 query_releasename(client, &fname);
6992 dns_db_detachnode(db, &node);
6996 type = qtype = dns_rdatatype_a;
6997 rpz_st = client->query.rpz_st;
6998 if (rpz_st != NULL) {
7000 * Arrange for RPZ rewriting of any A records.
7002 if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0)
7003 is_zone = rpz_st->q.is_zone;
7004 rpz_st_clear(client);
7011 * We don't call query_addrrset() because we don't need any
7012 * of its extra features (and things would probably break!).
7014 query_keepname(client, fname, dbuf);
7015 dns_message_addname(client->message, fname,
7016 DNS_SECTION_AUTHORITY);
7017 ISC_LIST_APPEND(fname->list, rdataset, link);
7024 * Keep a copy of the rdataset. We have to do this because
7025 * query_addrrset may clear 'rdataset' (to prevent the
7026 * cleanup code from cleaning it up).
7028 trdataset = rdataset;
7030 * Add the CNAME to the answer section.
7032 if (sigrdataset != NULL)
7033 sigrdatasetp = &sigrdataset;
7035 sigrdatasetp = NULL;
7036 if (WANTDNSSEC(client) &&
7037 (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
7039 dns_fixedname_init(&wildcardname);
7040 dns_name_copy(fname, dns_fixedname_name(&wildcardname),
7042 need_wildcardproof = ISC_TRUE;
7044 if (NOQNAME(rdataset) && WANTDNSSEC(client))
7048 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
7049 DNS_SECTION_ANSWER);
7050 if (noqname != NULL)
7051 query_addnoqnameproof(client, noqname);
7053 * We set the PARTIALANSWER attribute so that if anything goes
7054 * wrong later on, we'll return what we've got so far.
7056 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
7058 * Reset qname to be the target name of the CNAME and restart
7062 result = dns_message_gettempname(client->message, &tname);
7063 if (result != ISC_R_SUCCESS)
7065 result = dns_rdataset_first(trdataset);
7066 if (result != ISC_R_SUCCESS) {
7067 dns_message_puttempname(client->message, &tname);
7070 dns_rdataset_current(trdataset, &rdata);
7071 result = dns_rdata_tostruct(&rdata, &cname, NULL);
7072 dns_rdata_reset(&rdata);
7073 if (result != ISC_R_SUCCESS) {
7074 dns_message_puttempname(client->message, &tname);
7077 dns_name_init(tname, NULL);
7078 result = dns_name_dup(&cname.cname, client->mctx, tname);
7079 if (result != ISC_R_SUCCESS) {
7080 dns_message_puttempname(client->message, &tname);
7081 dns_rdata_freestruct(&cname);
7084 dns_rdata_freestruct(&cname);
7085 ns_client_qnamereplace(client, tname);
7086 want_restart = ISC_TRUE;
7087 if (!WANTRECURSION(client))
7088 options |= DNS_GETDB_NOLOG;
7092 * Compare the current qname to the found name. We need
7093 * to know how many labels and bits are in common because
7094 * we're going to have to split qname later on.
7096 namereln = dns_name_fullcompare(client->query.qname, fname,
7098 INSIST(namereln == dns_namereln_subdomain);
7100 * Keep a copy of the rdataset. We have to do this because
7101 * query_addrrset may clear 'rdataset' (to prevent the
7102 * cleanup code from cleaning it up).
7104 trdataset = rdataset;
7106 * Add the DNAME to the answer section.
7108 if (sigrdataset != NULL)
7109 sigrdatasetp = &sigrdataset;
7111 sigrdatasetp = NULL;
7112 if (WANTDNSSEC(client) &&
7113 (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
7115 dns_fixedname_init(&wildcardname);
7116 dns_name_copy(fname, dns_fixedname_name(&wildcardname),
7118 need_wildcardproof = ISC_TRUE;
7120 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
7121 DNS_SECTION_ANSWER);
7123 * We set the PARTIALANSWER attribute so that if anything goes
7124 * wrong later on, we'll return what we've got so far.
7126 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
7128 * Get the target name of the DNAME.
7131 result = dns_message_gettempname(client->message, &tname);
7132 if (result != ISC_R_SUCCESS)
7134 result = dns_rdataset_first(trdataset);
7135 if (result != ISC_R_SUCCESS) {
7136 dns_message_puttempname(client->message, &tname);
7139 dns_rdataset_current(trdataset, &rdata);
7140 result = dns_rdata_tostruct(&rdata, &dname, NULL);
7141 dns_rdata_reset(&rdata);
7142 if (result != ISC_R_SUCCESS) {
7143 dns_message_puttempname(client->message, &tname);
7146 dns_name_clone(&dname.dname, tname);
7147 dns_rdata_freestruct(&dname);
7149 * Construct the new qname consisting of
7150 * <found name prefix>.<dname target>
7152 dns_fixedname_init(&fixed);
7153 prefix = dns_fixedname_name(&fixed);
7154 dns_name_split(client->query.qname, nlabels, prefix, NULL);
7155 INSIST(fname == NULL);
7156 dbuf = query_getnamebuf(client);
7158 dns_message_puttempname(client->message, &tname);
7161 fname = query_newname(client, dbuf, &b);
7162 if (fname == NULL) {
7163 dns_message_puttempname(client->message, &tname);
7166 result = dns_name_concatenate(prefix, tname, fname, NULL);
7167 dns_message_puttempname(client->message, &tname);
7170 * RFC2672, section 4.1, subsection 3c says
7171 * we should return YXDOMAIN if the constructed
7172 * name would be too long.
7174 if (result == DNS_R_NAMETOOLONG)
7175 client->message->rcode = dns_rcode_yxdomain;
7176 if (result != ISC_R_SUCCESS)
7179 query_keepname(client, fname, dbuf);
7181 * Synthesize a CNAME consisting of
7182 * <old qname> <dname ttl> CNAME <new qname>
7183 * with <dname trust value>
7185 * Synthesize a CNAME so old old clients that don't understand
7188 * We do not try to synthesize a signature because we hope
7189 * that security aware servers will understand DNAME. Also,
7190 * even if we had an online key, making a signature
7191 * on-the-fly is costly, and not really legitimate anyway
7192 * since the synthesized CNAME is NOT in the zone.
7194 result = query_add_cname(client, client->query.qname, fname,
7195 trdataset->trust, trdataset->ttl);
7196 if (result != ISC_R_SUCCESS)
7199 * Switch to the new qname and restart.
7201 ns_client_qnamereplace(client, fname);
7203 want_restart = ISC_TRUE;
7204 if (!WANTRECURSION(client))
7205 options |= DNS_GETDB_NOLOG;
7209 * Something has gone wrong.
7211 snprintf(errmsg, sizeof(errmsg) - 1,
7212 "query_find: unexpected error after resuming: %s",
7213 isc_result_totext(result));
7214 CTRACE(ISC_LOG_ERROR, errmsg);
7215 QUERY_ERROR(DNS_R_SERVFAIL);
7219 if (WANTDNSSEC(client) &&
7220 (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
7222 dns_fixedname_init(&wildcardname);
7223 dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL);
7224 need_wildcardproof = ISC_TRUE;
7227 #ifdef ALLOW_FILTER_AAAA_ON_V4
7228 if (client->view->v4_aaaa != dns_v4_aaaa_ok &&
7229 is_v4_client(client) &&
7230 ns_client_checkaclsilent(client, NULL,
7231 client->view->v4_aaaa_acl,
7232 ISC_TRUE) == ISC_R_SUCCESS)
7233 client->filter_aaaa = client->view->v4_aaaa;
7235 client->filter_aaaa = dns_v4_aaaa_ok;
7239 if (type == dns_rdatatype_any) {
7240 #ifdef ALLOW_FILTER_AAAA_ON_V4
7241 isc_boolean_t have_aaaa, have_a, have_sig;
7244 * The filter-aaaa-on-v4 option should
7245 * suppress AAAAs for IPv4 clients if there is an A.
7246 * If we are not authoritative, assume there is a A
7247 * even in if it is not in our cache. This assumption could
7248 * be wrong but it is a good bet.
7250 have_aaaa = ISC_FALSE;
7251 have_a = !authoritative;
7252 have_sig = ISC_FALSE;
7255 * XXXRTH Need to handle zonecuts with special case
7260 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
7261 if (result != ISC_R_SUCCESS) {
7262 CTRACE(ISC_LOG_ERROR,
7263 "query_find: type any; allrdatasets failed");
7264 QUERY_ERROR(DNS_R_SERVFAIL);
7269 * Calling query_addrrset() with a non-NULL dbuf is going
7270 * to either keep or release the name. We don't want it to
7271 * release fname, since we may have to call query_addrrset()
7272 * more than once. That means we have to call query_keepname()
7273 * now, and pass a NULL dbuf to query_addrrset().
7275 * If we do a query_addrrset() below, we must set fname to
7276 * NULL before leaving this block, otherwise we might try to
7277 * cleanup fname even though we're using it!
7279 query_keepname(client, fname, dbuf);
7281 result = dns_rdatasetiter_first(rdsiter);
7282 while (result == ISC_R_SUCCESS) {
7283 dns_rdatasetiter_current(rdsiter, rdataset);
7284 #ifdef ALLOW_FILTER_AAAA_ON_V4
7286 * Notice the presence of A and AAAAs so
7287 * that AAAAs can be hidden from IPv4 clients.
7289 if (client->filter_aaaa != dns_v4_aaaa_ok) {
7290 if (rdataset->type == dns_rdatatype_aaaa)
7291 have_aaaa = ISC_TRUE;
7292 else if (rdataset->type == dns_rdatatype_a)
7296 if (is_zone && qtype == dns_rdatatype_any &&
7297 !dns_db_issecure(db) &&
7298 dns_rdatatype_isdnssec(rdataset->type)) {
7300 * The zone is transitioning from insecure
7301 * to secure. Hide the dnssec records from
7304 dns_rdataset_disassociate(rdataset);
7305 } else if ((qtype == dns_rdatatype_any ||
7306 rdataset->type == qtype) && rdataset->type != 0) {
7307 #ifdef ALLOW_FILTER_AAAA_ON_V4
7308 if (dns_rdatatype_isdnssec(rdataset->type))
7309 have_sig = ISC_TRUE;
7311 if (NOQNAME(rdataset) && WANTDNSSEC(client))
7315 rpz_st = client->query.rpz_st;
7317 rdataset->ttl = ISC_MIN(rdataset->ttl,
7319 query_addrrset(client,
7320 fname != NULL ? &fname : &tname,
7322 NULL, DNS_SECTION_ANSWER);
7323 if (noqname != NULL)
7324 query_addnoqnameproof(client, noqname);
7326 INSIST(tname != NULL);
7328 * rdataset is non-NULL only in certain
7329 * pathological cases involving DNAMEs.
7331 if (rdataset != NULL)
7332 query_putrdataset(client, &rdataset);
7333 rdataset = query_newrdataset(client);
7334 if (rdataset == NULL)
7338 * We're not interested in this rdataset.
7340 dns_rdataset_disassociate(rdataset);
7342 result = dns_rdatasetiter_next(rdsiter);
7345 #ifdef ALLOW_FILTER_AAAA_ON_V4
7347 * Filter AAAAs if there is an A and there is no signature
7348 * or we are supposed to break DNSSEC.
7350 if (client->filter_aaaa == dns_v4_aaaa_break_dnssec)
7351 client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
7352 else if (client->filter_aaaa != dns_v4_aaaa_ok &&
7353 have_aaaa && have_a &&
7354 (!have_sig || !WANTDNSSEC(client)))
7355 client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
7358 dns_message_puttempname(client->message, &fname);
7362 * No matching rdatasets found in cache. If we were
7363 * searching for RRSIG/SIG, that's probably okay;
7364 * otherwise this is an error condition.
7366 if ((qtype == dns_rdatatype_rrsig ||
7367 qtype == dns_rdatatype_sig) &&
7368 result == ISC_R_NOMORE) {
7370 authoritative = ISC_FALSE;
7371 dns_rdatasetiter_destroy(&rdsiter);
7372 client->attributes &= ~NS_CLIENTATTR_RA;
7376 if (qtype == dns_rdatatype_rrsig &&
7377 dns_db_issecure(db)) {
7378 char namebuf[DNS_NAME_FORMATSIZE];
7379 dns_name_format(client->query.qname,
7382 ns_client_log(client,
7383 DNS_LOGCATEGORY_DNSSEC,
7386 "missing signature "
7390 dns_rdatasetiter_destroy(&rdsiter);
7391 fname = query_newname(client, dbuf, &b);
7394 CTRACE(ISC_LOG_ERROR,
7395 "query_find: no matching rdatasets "
7397 result = DNS_R_SERVFAIL;
7401 dns_rdatasetiter_destroy(&rdsiter);
7402 if (result != ISC_R_NOMORE) {
7403 CTRACE(ISC_LOG_ERROR,
7404 "query_find: dns_rdatasetiter_destroy failed");
7405 QUERY_ERROR(DNS_R_SERVFAIL);
7410 * This is the "normal" case -- an ordinary question to which
7411 * we know the answer.
7414 #ifdef ALLOW_FILTER_AAAA_ON_V4
7416 * Optionally hide AAAAs from IPv4 clients if there is an A.
7417 * We add the AAAAs now, but might refuse to render them later
7418 * after DNSSEC is figured out.
7419 * This could be more efficient, but the whole idea is
7420 * so fundamentally wrong, unavoidably inaccurate, and
7421 * unneeded that it is best to keep it as short as possible.
7423 if (client->filter_aaaa == dns_v4_aaaa_break_dnssec ||
7424 (client->filter_aaaa == dns_v4_aaaa_filter &&
7425 (!WANTDNSSEC(client) || sigrdataset == NULL ||
7426 !dns_rdataset_isassociated(sigrdataset))))
7428 if (qtype == dns_rdatatype_aaaa) {
7429 trdataset = query_newrdataset(client);
7430 result = dns_db_findrdataset(db, node, version,
7434 if (dns_rdataset_isassociated(trdataset))
7435 dns_rdataset_disassociate(trdataset);
7436 query_putrdataset(client, &trdataset);
7439 * We have an AAAA but the A is not in our cache.
7440 * Assume any result other than DNS_R_DELEGATION
7441 * or ISC_R_NOTFOUND means there is no A and
7443 * Assume there is no A if we can't recurse
7444 * for this client, although that could be
7445 * the wrong answer. What else can we do?
7446 * Besides, that we have the AAAA and are using
7447 * this mechanism suggests that we care more
7448 * about As than AAAAs and would have cached
7449 * the A if it existed.
7451 if (result == ISC_R_SUCCESS) {
7452 client->attributes |=
7453 NS_CLIENTATTR_FILTER_AAAA;
7455 } else if (authoritative ||
7456 !RECURSIONOK(client) ||
7457 (result != DNS_R_DELEGATION &&
7458 result != ISC_R_NOTFOUND)) {
7459 client->attributes &=
7460 ~NS_CLIENTATTR_FILTER_AAAA;
7463 * This is an ugly kludge to recurse
7464 * for the A and discard the result.
7466 * Continue to add the AAAA now.
7467 * We'll make a note to not render it
7468 * if the recursion for the A succeeds.
7470 result = query_recurse(client,
7472 client->query.qname,
7473 NULL, NULL, resuming);
7474 if (result == ISC_R_SUCCESS) {
7475 client->attributes |=
7476 NS_CLIENTATTR_FILTER_AAAA_RC;
7477 client->query.attributes |=
7478 NS_QUERYATTR_RECURSING;
7482 } else if (qtype == dns_rdatatype_a &&
7483 (client->attributes &
7484 NS_CLIENTATTR_FILTER_AAAA_RC) != 0) {
7485 client->attributes &=
7486 ~NS_CLIENTATTR_FILTER_AAAA_RC;
7487 client->attributes |=
7488 NS_CLIENTATTR_FILTER_AAAA;
7489 dns_rdataset_disassociate(rdataset);
7490 if (sigrdataset != NULL &&
7491 dns_rdataset_isassociated(sigrdataset))
7492 dns_rdataset_disassociate(sigrdataset);
7498 * Check to see if the AAAA RRset has non-excluded addresses
7499 * in it. If not look for a A RRset.
7501 INSIST(client->query.dns64_aaaaok == NULL);
7503 if (qtype == dns_rdatatype_aaaa && !dns64_exclude &&
7504 !ISC_LIST_EMPTY(client->view->dns64) &&
7505 client->message->rdclass == dns_rdataclass_in &&
7506 !dns64_aaaaok(client, rdataset, sigrdataset)) {
7508 * Look to see if there are A records for this
7511 client->query.dns64_aaaa = rdataset;
7512 client->query.dns64_sigaaaa = sigrdataset;
7513 client->query.dns64_ttl = rdataset->ttl;
7514 query_releasename(client, &fname);
7515 dns_db_detachnode(db, &node);
7518 type = qtype = dns_rdatatype_a;
7519 rpz_st = client->query.rpz_st;
7520 if (rpz_st != NULL) {
7522 * Arrange for RPZ rewriting of any A records.
7524 if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0)
7525 is_zone = rpz_st->q.is_zone;
7526 rpz_st_clear(client);
7528 dns64_exclude = dns64 = ISC_TRUE;
7532 if (sigrdataset != NULL)
7533 sigrdatasetp = &sigrdataset;
7535 sigrdatasetp = NULL;
7536 if (NOQNAME(rdataset) && WANTDNSSEC(client))
7541 * BIND 8 priming queries need the additional section.
7543 if (is_zone && qtype == dns_rdatatype_ns &&
7544 dns_name_equal(client->query.qname, dns_rootname))
7545 client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL;
7548 qtype = type = dns_rdatatype_aaaa;
7549 result = query_dns64(client, &fname, rdataset,
7551 DNS_SECTION_ANSWER);
7552 dns_rdataset_disassociate(rdataset);
7553 dns_message_puttemprdataset(client->message, &rdataset);
7554 if (result == ISC_R_NOMORE) {
7555 #ifndef dns64_bis_return_excluded_addresses
7556 if (dns64_exclude) {
7560 * Add a fake SOA record.
7562 (void)query_addsoa(client, db, version,
7564 DNS_SECTION_AUTHORITY);
7569 goto iszone_nxrrset;
7571 goto ncache_nxrrset;
7572 } else if (result != ISC_R_SUCCESS) {
7576 } else if (client->query.dns64_aaaaok != NULL) {
7577 query_filter64(client, &fname, rdataset, dbuf,
7578 DNS_SECTION_ANSWER);
7579 query_putrdataset(client, &rdataset);
7581 query_addrrset(client, &fname, &rdataset,
7582 sigrdatasetp, dbuf, DNS_SECTION_ANSWER);
7584 if (noqname != NULL)
7585 query_addnoqnameproof(client, noqname);
7587 * We shouldn't ever fail to add 'rdataset'
7588 * because it's already in the answer.
7590 INSIST(rdataset == NULL);
7594 CTRACE(ISC_LOG_DEBUG(3), "query_find: addauth");
7596 * Add NS records to the authority section (if we haven't already
7597 * added them to the answer section).
7599 if (!want_restart && !NOAUTHORITY(client)) {
7601 if (!((qtype == dns_rdatatype_ns ||
7602 qtype == dns_rdatatype_any) &&
7603 dns_name_equal(client->query.qname,
7604 dns_db_origin(db))))
7605 (void)query_addns(client, db, version);
7606 } else if (qtype != dns_rdatatype_ns) {
7608 query_releasename(client, &fname);
7609 query_addbestns(client);
7614 * Add NSEC records to the authority section if they're needed for
7615 * DNSSEC wildcard proofs.
7617 if (need_wildcardproof && dns_db_issecure(db))
7618 query_addwildcardproof(client, db, version,
7619 dns_fixedname_name(&wildcardname),
7620 ISC_TRUE, ISC_FALSE);
7622 CTRACE(ISC_LOG_DEBUG(3), "query_find: cleanup");
7626 rpz_st = client->query.rpz_st;
7627 if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) {
7628 rpz_match_clear(rpz_st);
7629 rpz_st->state &= ~DNS_RPZ_DONE_QNAME;
7631 if (rdataset != NULL)
7632 query_putrdataset(client, &rdataset);
7633 if (sigrdataset != NULL)
7634 query_putrdataset(client, &sigrdataset);
7636 query_releasename(client, &fname);
7638 dns_db_detachnode(db, &node);
7642 dns_zone_detach(&zone);
7644 query_putrdataset(client, &zrdataset);
7645 if (zsigrdataset != NULL)
7646 query_putrdataset(client, &zsigrdataset);
7648 query_releasename(client, &zfname);
7649 dns_db_detach(&zdb);
7652 isc_event_free(ISC_EVENT_PTR(&event));
7657 if (client->query.restarts == 0 && !authoritative) {
7659 * We're not authoritative, so we must ensure the AA bit
7662 client->message->flags &= ~DNS_MESSAGEFLAG_AA;
7666 * Restart the query?
7668 if (want_restart && client->query.restarts < MAX_RESTARTS) {
7669 client->query.restarts++;
7674 if (eresult != ISC_R_SUCCESS &&
7675 (!PARTIALANSWER(client) || WANTRECURSION(client)
7676 || eresult == DNS_R_DROP))
7678 if (eresult != ISC_R_SUCCESS &&
7679 (!PARTIALANSWER(client) || WANTRECURSION(client)))
7680 #endif /* USE_RRL */
7682 if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) {
7684 * This was a duplicate query that we are
7685 * recursing on or the result of rate limiting.
7686 * Don't send a response now for a duplicate query,
7687 * because the original will still cause a response.
7689 query_next(client, eresult);
7692 * If we don't have any answer to give the client,
7693 * or if the client requested recursion and thus wanted
7694 * the complete answer, send an error response.
7697 query_error(client, eresult, line);
7699 ns_client_detach(&client);
7700 } else if (!RECURSING(client)) {
7702 * We are done. Set up sortlist data for the message
7703 * rendering code, make a final tweak to the AA bit if the
7704 * auth-nxdomain config option says so, then render and
7705 * send the response.
7707 setup_query_sortlist(client);
7710 * If this is a referral and the answer to the question
7711 * is in the glue sort it to the start of the additional
7714 if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) &&
7715 client->message->rcode == dns_rcode_noerror &&
7716 (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa))
7717 answer_in_glue(client, qtype);
7719 if (client->message->rcode == dns_rcode_nxdomain &&
7720 client->view->auth_nxdomain == ISC_TRUE)
7721 client->message->flags |= DNS_MESSAGEFLAG_AA;
7724 * If the response is somehow unexpected for the client and this
7725 * is a result of recursion, return an error to the caller
7726 * to indicate it may need to be logged.
7729 (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) ||
7730 client->message->rcode != dns_rcode_noerror))
7731 eresult = ISC_R_FAILURE;
7734 ns_client_detach(&client);
7736 CTRACE(ISC_LOG_DEBUG(3), "query_find: done");
7742 log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
7743 char namebuf[DNS_NAME_FORMATSIZE];
7744 char typename[DNS_RDATATYPE_FORMATSIZE];
7745 char classname[DNS_RDATACLASS_FORMATSIZE];
7746 char onbuf[ISC_NETADDR_FORMATSIZE];
7747 dns_rdataset_t *rdataset;
7748 int level = ISC_LOG_INFO;
7750 if (! isc_log_wouldlog(ns_g_lctx, level))
7753 rdataset = ISC_LIST_HEAD(client->query.qname->list);
7754 INSIST(rdataset != NULL);
7755 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
7756 dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname));
7757 dns_rdatatype_format(rdataset->type, typename, sizeof(typename));
7758 isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf));
7760 ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
7761 level, "query: %s %s %s %s%s%s%s%s%s (%s)", namebuf,
7762 classname, typename, WANTRECURSION(client) ? "+" : "-",
7763 (client->signer != NULL) ? "S": "",
7764 (client->opt != NULL) ? "E" : "",
7765 ((client->attributes & NS_CLIENTATTR_TCP) != 0) ?
7767 ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
7768 ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "",
7773 log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) {
7774 char namebuf[DNS_NAME_FORMATSIZE];
7775 char typename[DNS_RDATATYPE_FORMATSIZE];
7776 char classname[DNS_RDATACLASS_FORMATSIZE];
7777 const char *namep, *typep, *classp, *sep1, *sep2;
7778 dns_rdataset_t *rdataset;
7780 if (!isc_log_wouldlog(ns_g_lctx, level))
7783 namep = typep = classp = sep1 = sep2 = "";
7786 * Query errors can happen for various reasons. In some cases we cannot
7787 * even assume the query contains a valid question section, so we should
7788 * expect exceptional cases.
7790 if (client->query.origqname != NULL) {
7791 dns_name_format(client->query.origqname, namebuf,
7796 rdataset = ISC_LIST_HEAD(client->query.origqname->list);
7797 if (rdataset != NULL) {
7798 dns_rdataclass_format(rdataset->rdclass, classname,
7801 dns_rdatatype_format(rdataset->type, typename,
7808 ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY,
7809 level, "query failed (%s)%s%s%s%s%s%s at %s:%d",
7810 isc_result_totext(result), sep1, namep, sep2,
7811 classp, sep2, typep, __FILE__, line);
7815 ns_query_start(ns_client_t *client) {
7816 isc_result_t result;
7817 dns_message_t *message = client->message;
7818 dns_rdataset_t *rdataset;
7819 ns_client_t *qclient;
7820 dns_rdatatype_t qtype;
7821 unsigned int saved_extflags = client->extflags;
7822 unsigned int saved_flags = client->message->flags;
7824 CTRACE(ISC_LOG_DEBUG(3), "ns_query_start");
7829 if (ns_g_clienttest && !TCP(client)) {
7830 result = ns_client_replace(client);
7831 if (result == ISC_R_SHUTTINGDOWN) {
7832 ns_client_next(client, result);
7834 } else if (result != ISC_R_SUCCESS) {
7835 query_error(client, result, __LINE__);
7841 * Ensure that appropriate cleanups occur.
7843 client->next = query_next_callback;
7846 * Behave as if we don't support DNSSEC if not enabled.
7848 if (!client->view->enablednssec) {
7849 message->flags &= ~DNS_MESSAGEFLAG_CD;
7850 client->extflags &= ~DNS_MESSAGEEXTFLAG_DO;
7851 if (client->opt != NULL)
7852 client->opt->ttl &= ~DNS_MESSAGEEXTFLAG_DO;
7855 if ((message->flags & DNS_MESSAGEFLAG_RD) != 0)
7856 client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
7858 if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0)
7859 client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
7861 if (client->view->minimalresponses)
7862 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
7863 NS_QUERYATTR_NOADDITIONAL);
7865 if ((client->view->cachedb == NULL)
7866 || (!client->view->additionalfromcache)) {
7868 * We don't have a cache. Turn off cache support and
7871 client->query.attributes &=
7872 ~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK);
7873 } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
7874 (message->flags & DNS_MESSAGEFLAG_RD) == 0) {
7876 * If the client isn't allowed to recurse (due to
7877 * "recursion no", the allow-recursion ACL, or the
7878 * lack of a resolver in this view), or if it
7879 * doesn't want recursion, turn recursion off.
7881 client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
7885 * Check for multiple question queries, since edns1 is dead.
7887 if (message->counts[DNS_SECTION_QUESTION] > 1) {
7888 query_error(client, DNS_R_FORMERR, __LINE__);
7893 * Get the question name.
7895 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
7896 if (result != ISC_R_SUCCESS) {
7897 query_error(client, result, __LINE__);
7900 dns_message_currentname(message, DNS_SECTION_QUESTION,
7901 &client->query.qname);
7902 client->query.origqname = client->query.qname;
7903 result = dns_message_nextname(message, DNS_SECTION_QUESTION);
7904 if (result != ISC_R_NOMORE) {
7905 if (result == ISC_R_SUCCESS) {
7907 * There's more than one QNAME in the question
7910 query_error(client, DNS_R_FORMERR, __LINE__);
7912 query_error(client, result, __LINE__);
7916 if (ns_g_server->log_queries)
7917 log_query(client, saved_flags, saved_extflags);
7920 * Check for meta-queries like IXFR and AXFR.
7922 rdataset = ISC_LIST_HEAD(client->query.qname->list);
7923 INSIST(rdataset != NULL);
7924 client->query.qtype = qtype = rdataset->type;
7925 dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype);
7927 if (dns_rdatatype_ismeta(qtype)) {
7929 case dns_rdatatype_any:
7930 break; /* Let query_find handle it. */
7931 case dns_rdatatype_ixfr:
7932 case dns_rdatatype_axfr:
7933 ns_xfr_start(client, rdataset->type);
7935 case dns_rdatatype_maila:
7936 case dns_rdatatype_mailb:
7937 query_error(client, DNS_R_NOTIMP, __LINE__);
7939 case dns_rdatatype_tkey:
7940 result = dns_tkey_processquery(client->message,
7941 ns_g_server->tkeyctx,
7942 client->view->dynamickeys);
7943 if (result == ISC_R_SUCCESS)
7946 query_error(client, result, __LINE__);
7948 default: /* TSIG, etc. */
7949 query_error(client, DNS_R_FORMERR, __LINE__);
7955 * Turn on minimal response for DNSKEY and DS queries.
7957 if (qtype == dns_rdatatype_dnskey || qtype == dns_rdatatype_ds)
7958 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
7959 NS_QUERYATTR_NOADDITIONAL);
7962 * Turn on minimal responses for EDNS/UDP bufsize 512 queries.
7964 if (client->opt != NULL && client->udpsize <= 512U &&
7965 (client->attributes & NS_CLIENTATTR_TCP) == 0)
7966 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
7967 NS_QUERYATTR_NOADDITIONAL);
7970 * If the client has requested that DNSSEC checking be disabled,
7971 * allow lookups to return pending data and instruct the resolver
7972 * to return data before validation has completed.
7974 * We don't need to set DNS_DBFIND_PENDINGOK when validation is
7975 * disabled as there will be no pending data.
7977 if (message->flags & DNS_MESSAGEFLAG_CD ||
7978 qtype == dns_rdatatype_rrsig)
7980 client->query.dboptions |= DNS_DBFIND_PENDINGOK;
7981 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
7982 } else if (!client->view->enablevalidation)
7983 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
7986 * Allow glue NS records to be added to the authority section
7987 * if the answer is secure.
7989 if (message->flags & DNS_MESSAGEFLAG_CD)
7990 client->query.attributes &= ~NS_QUERYATTR_SECURE;
7993 * Set NS_CLIENTATTR_WANTDNSSEC if the client has set AD in the query.
7994 * This allows AD to be returned on queries without DO set.
7996 if ((message->flags & DNS_MESSAGEFLAG_AD) != 0)
7997 client->attributes |= NS_CLIENTATTR_WANTAD;
8000 * This is an ordinary query.
8002 result = dns_message_reply(message, ISC_TRUE);
8003 if (result != ISC_R_SUCCESS) {
8004 query_next(client, result);
8009 * Assume authoritative response until it is known to be
8012 * If "-T noaa" has been set on the command line don't set
8013 * AA on authoritative answers.
8016 message->flags |= DNS_MESSAGEFLAG_AA;
8019 * Set AD. We must clear it if we add non-validated data to a
8022 if (WANTDNSSEC(client) || WANTAD(client))
8023 message->flags |= DNS_MESSAGEFLAG_AD;
8026 ns_client_attach(client, &qclient);
8027 (void)query_find(qclient, NULL, qtype);