2 * Copyright (C) 2004-2009 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.
18 /* $Id: query.c,v 1.298.48.15 2009/09/16 22:28:52 marka Exp $ */
27 #include <isc/stats.h>
31 #include <dns/byaddr.h>
36 #include <dns/dnssec.h>
37 #include <dns/events.h>
38 #include <dns/message.h>
39 #include <dns/ncache.h>
40 #include <dns/order.h>
41 #include <dns/rdata.h>
42 #include <dns/rdataclass.h>
43 #include <dns/rdatalist.h>
44 #include <dns/rdataset.h>
45 #include <dns/rdatasetiter.h>
46 #include <dns/rdatastruct.h>
47 #include <dns/rdatatype.h>
48 #include <dns/resolver.h>
49 #include <dns/result.h>
50 #include <dns/stats.h>
56 #include <named/client.h>
57 #include <named/log.h>
58 #include <named/server.h>
59 #include <named/sortlist.h>
60 #include <named/xfrout.h>
62 /*% Partial answer? */
63 #define PARTIALANSWER(c) (((c)->query.attributes & \
64 NS_QUERYATTR_PARTIALANSWER) != 0)
66 #define USECACHE(c) (((c)->query.attributes & \
67 NS_QUERYATTR_CACHEOK) != 0)
69 #define RECURSIONOK(c) (((c)->query.attributes & \
70 NS_QUERYATTR_RECURSIONOK) != 0)
72 #define RECURSING(c) (((c)->query.attributes & \
73 NS_QUERYATTR_RECURSING) != 0)
75 #define CACHEGLUEOK(c) (((c)->query.attributes & \
76 NS_QUERYATTR_CACHEGLUEOK) != 0)
77 /*% Want Recursion? */
78 #define WANTRECURSION(c) (((c)->query.attributes & \
79 NS_QUERYATTR_WANTRECURSION) != 0)
81 #define WANTDNSSEC(c) (((c)->attributes & \
82 NS_CLIENTATTR_WANTDNSSEC) != 0)
84 #define NOAUTHORITY(c) (((c)->query.attributes & \
85 NS_QUERYATTR_NOAUTHORITY) != 0)
87 #define NOADDITIONAL(c) (((c)->query.attributes & \
88 NS_QUERYATTR_NOADDITIONAL) != 0)
90 #define SECURE(c) (((c)->query.attributes & \
91 NS_QUERYATTR_SECURE) != 0)
94 #define CTRACE(m) isc_log_write(ns_g_lctx, \
95 NS_LOGCATEGORY_CLIENT, \
98 "client %p: %s", client, (m))
99 #define QTRACE(m) isc_log_write(ns_g_lctx, \
100 NS_LOGCATEGORY_GENERAL, \
101 NS_LOGMODULE_QUERY, \
103 "query %p: %s", query, (m))
105 #define CTRACE(m) ((void)m)
106 #define QTRACE(m) ((void)m)
109 #define DNS_GETDB_NOEXACT 0x01U
110 #define DNS_GETDB_NOLOG 0x02U
111 #define DNS_GETDB_PARTIAL 0x04U
113 typedef struct client_additionalctx
{
115 dns_rdataset_t
*rdataset
;
116 } client_additionalctx_t
;
119 query_find(ns_client_t
*client
, dns_fetchevent_t
*event
, dns_rdatatype_t qtype
);
122 validate(ns_client_t
*client
, dns_db_t
*db
, dns_name_t
*name
,
123 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
);
126 log_queryerror(ns_client_t
*client
, isc_result_t result
, int line
, int level
);
129 * Increment query statistics counters.
132 inc_stats(ns_client_t
*client
, isc_statscounter_t counter
) {
133 dns_zone_t
*zone
= client
->query
.authzone
;
135 isc_stats_increment(ns_g_server
->nsstats
, counter
);
138 isc_stats_t
*zonestats
= dns_zone_getrequeststats(zone
);
139 if (zonestats
!= NULL
)
140 isc_stats_increment(zonestats
, counter
);
145 query_send(ns_client_t
*client
) {
146 isc_statscounter_t counter
;
147 if ((client
->message
->flags
& DNS_MESSAGEFLAG_AA
) == 0)
148 inc_stats(client
, dns_nsstatscounter_nonauthans
);
150 inc_stats(client
, dns_nsstatscounter_authans
);
151 if (client
->message
->rcode
== dns_rcode_noerror
) {
152 if (ISC_LIST_EMPTY(client
->message
->sections
[DNS_SECTION_ANSWER
])) {
153 if (client
->query
.isreferral
) {
154 counter
= dns_nsstatscounter_referral
;
156 counter
= dns_nsstatscounter_nxrrset
;
159 counter
= dns_nsstatscounter_success
;
161 } else if (client
->message
->rcode
== dns_rcode_nxdomain
) {
162 counter
= dns_nsstatscounter_nxdomain
;
164 /* We end up here in case of YXDOMAIN, and maybe others */
165 counter
= dns_nsstatscounter_failure
;
167 inc_stats(client
, counter
);
168 ns_client_send(client
);
172 query_error(ns_client_t
*client
, isc_result_t result
, int line
) {
173 int loglevel
= ISC_LOG_DEBUG(3);
177 loglevel
= ISC_LOG_DEBUG(1);
178 inc_stats(client
, dns_nsstatscounter_servfail
);
181 inc_stats(client
, dns_nsstatscounter_formerr
);
184 inc_stats(client
, dns_nsstatscounter_failure
);
188 log_queryerror(client
, result
, line
, loglevel
);
190 ns_client_error(client
, result
);
194 query_next(ns_client_t
*client
, isc_result_t result
) {
195 if (result
== DNS_R_DUPLICATE
)
196 inc_stats(client
, dns_nsstatscounter_duplicate
);
197 else if (result
== DNS_R_DROP
)
198 inc_stats(client
, dns_nsstatscounter_dropped
);
200 inc_stats(client
, dns_nsstatscounter_failure
);
201 ns_client_next(client
, result
);
205 query_freefreeversions(ns_client_t
*client
, isc_boolean_t everything
) {
206 ns_dbversion_t
*dbversion
, *dbversion_next
;
209 for (dbversion
= ISC_LIST_HEAD(client
->query
.freeversions
), i
= 0;
211 dbversion
= dbversion_next
, i
++)
213 dbversion_next
= ISC_LIST_NEXT(dbversion
, link
);
215 * If we're not freeing everything, we keep the first three
216 * dbversions structures around.
218 if (i
> 3 || everything
) {
219 ISC_LIST_UNLINK(client
->query
.freeversions
, dbversion
,
221 isc_mem_put(client
->mctx
, dbversion
,
228 ns_query_cancel(ns_client_t
*client
) {
229 LOCK(&client
->query
.fetchlock
);
230 if (client
->query
.fetch
!= NULL
) {
231 dns_resolver_cancelfetch(client
->query
.fetch
);
233 client
->query
.fetch
= NULL
;
235 UNLOCK(&client
->query
.fetchlock
);
239 query_reset(ns_client_t
*client
, isc_boolean_t everything
) {
240 isc_buffer_t
*dbuf
, *dbuf_next
;
241 ns_dbversion_t
*dbversion
, *dbversion_next
;
244 * Reset the query state of a client to its default state.
248 * Cancel the fetch if it's running.
250 ns_query_cancel(client
);
253 * Cleanup any active versions.
255 for (dbversion
= ISC_LIST_HEAD(client
->query
.activeversions
);
257 dbversion
= dbversion_next
) {
258 dbversion_next
= ISC_LIST_NEXT(dbversion
, link
);
259 dns_db_closeversion(dbversion
->db
, &dbversion
->version
,
261 dns_db_detach(&dbversion
->db
);
262 ISC_LIST_INITANDAPPEND(client
->query
.freeversions
,
265 ISC_LIST_INIT(client
->query
.activeversions
);
267 if (client
->query
.authdb
!= NULL
)
268 dns_db_detach(&client
->query
.authdb
);
269 if (client
->query
.authzone
!= NULL
)
270 dns_zone_detach(&client
->query
.authzone
);
272 query_freefreeversions(client
, everything
);
274 for (dbuf
= ISC_LIST_HEAD(client
->query
.namebufs
);
277 dbuf_next
= ISC_LIST_NEXT(dbuf
, link
);
278 if (dbuf_next
!= NULL
|| everything
) {
279 ISC_LIST_UNLINK(client
->query
.namebufs
, dbuf
, link
);
280 isc_buffer_free(&dbuf
);
284 if (client
->query
.restarts
> 0) {
286 * client->query.qname was dynamically allocated.
288 dns_message_puttempname(client
->message
,
289 &client
->query
.qname
);
291 client
->query
.qname
= NULL
;
292 client
->query
.attributes
= (NS_QUERYATTR_RECURSIONOK
|
293 NS_QUERYATTR_CACHEOK
|
294 NS_QUERYATTR_SECURE
);
295 client
->query
.restarts
= 0;
296 client
->query
.timerset
= ISC_FALSE
;
297 client
->query
.origqname
= NULL
;
298 client
->query
.qname
= NULL
;
299 client
->query
.dboptions
= 0;
300 client
->query
.fetchoptions
= 0;
301 client
->query
.gluedb
= NULL
;
302 client
->query
.authdbset
= ISC_FALSE
;
303 client
->query
.isreferral
= ISC_FALSE
;
307 query_next_callback(ns_client_t
*client
) {
308 query_reset(client
, ISC_FALSE
);
312 ns_query_free(ns_client_t
*client
) {
313 query_reset(client
, ISC_TRUE
);
316 static inline isc_result_t
317 query_newnamebuf(ns_client_t
*client
) {
321 CTRACE("query_newnamebuf");
323 * Allocate a name buffer.
327 result
= isc_buffer_allocate(client
->mctx
, &dbuf
, 1024);
328 if (result
!= ISC_R_SUCCESS
) {
329 CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
332 ISC_LIST_APPEND(client
->query
.namebufs
, dbuf
, link
);
334 CTRACE("query_newnamebuf: done");
335 return (ISC_R_SUCCESS
);
338 static inline isc_buffer_t
*
339 query_getnamebuf(ns_client_t
*client
) {
344 CTRACE("query_getnamebuf");
346 * Return a name buffer with space for a maximal name, allocating
347 * a new one if necessary.
350 if (ISC_LIST_EMPTY(client
->query
.namebufs
)) {
351 result
= query_newnamebuf(client
);
352 if (result
!= ISC_R_SUCCESS
) {
353 CTRACE("query_getnamebuf: query_newnamebuf failed: done");
358 dbuf
= ISC_LIST_TAIL(client
->query
.namebufs
);
359 INSIST(dbuf
!= NULL
);
360 isc_buffer_availableregion(dbuf
, &r
);
361 if (r
.length
< 255) {
362 result
= query_newnamebuf(client
);
363 if (result
!= ISC_R_SUCCESS
) {
364 CTRACE("query_getnamebuf: query_newnamebuf failed: done");
368 dbuf
= ISC_LIST_TAIL(client
->query
.namebufs
);
369 isc_buffer_availableregion(dbuf
, &r
);
370 INSIST(r
.length
>= 255);
372 CTRACE("query_getnamebuf: done");
377 query_keepname(ns_client_t
*client
, dns_name_t
*name
, isc_buffer_t
*dbuf
) {
380 CTRACE("query_keepname");
382 * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
383 * adjusted to take account of that. We do the adjustment.
386 REQUIRE((client
->query
.attributes
& NS_QUERYATTR_NAMEBUFUSED
) != 0);
388 dns_name_toregion(name
, &r
);
389 isc_buffer_add(dbuf
, r
.length
);
390 dns_name_setbuffer(name
, NULL
);
391 client
->query
.attributes
&= ~NS_QUERYATTR_NAMEBUFUSED
;
395 query_releasename(ns_client_t
*client
, dns_name_t
**namep
) {
396 dns_name_t
*name
= *namep
;
399 * 'name' is no longer needed. Return it to our pool of temporary
400 * names. If it is using a name buffer, relinquish its exclusive
401 * rights on the buffer.
404 CTRACE("query_releasename");
405 if (dns_name_hasbuffer(name
)) {
406 INSIST((client
->query
.attributes
& NS_QUERYATTR_NAMEBUFUSED
)
408 client
->query
.attributes
&= ~NS_QUERYATTR_NAMEBUFUSED
;
410 dns_message_puttempname(client
->message
, namep
);
411 CTRACE("query_releasename: done");
414 static inline dns_name_t
*
415 query_newname(ns_client_t
*client
, isc_buffer_t
*dbuf
,
422 REQUIRE((client
->query
.attributes
& NS_QUERYATTR_NAMEBUFUSED
) == 0);
424 CTRACE("query_newname");
426 result
= dns_message_gettempname(client
->message
, &name
);
427 if (result
!= ISC_R_SUCCESS
) {
428 CTRACE("query_newname: dns_message_gettempname failed: done");
431 isc_buffer_availableregion(dbuf
, &r
);
432 isc_buffer_init(nbuf
, r
.base
, r
.length
);
433 dns_name_init(name
, NULL
);
434 dns_name_setbuffer(name
, nbuf
);
435 client
->query
.attributes
|= NS_QUERYATTR_NAMEBUFUSED
;
437 CTRACE("query_newname: done");
441 static inline dns_rdataset_t
*
442 query_newrdataset(ns_client_t
*client
) {
443 dns_rdataset_t
*rdataset
;
446 CTRACE("query_newrdataset");
448 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
449 if (result
!= ISC_R_SUCCESS
) {
450 CTRACE("query_newrdataset: "
451 "dns_message_gettemprdataset failed: done");
454 dns_rdataset_init(rdataset
);
456 CTRACE("query_newrdataset: done");
461 query_putrdataset(ns_client_t
*client
, dns_rdataset_t
**rdatasetp
) {
462 dns_rdataset_t
*rdataset
= *rdatasetp
;
464 CTRACE("query_putrdataset");
465 if (rdataset
!= NULL
) {
466 if (dns_rdataset_isassociated(rdataset
))
467 dns_rdataset_disassociate(rdataset
);
468 dns_message_puttemprdataset(client
->message
, rdatasetp
);
470 CTRACE("query_putrdataset: done");
474 static inline isc_result_t
475 query_newdbversion(ns_client_t
*client
, unsigned int n
) {
477 ns_dbversion_t
*dbversion
;
479 for (i
= 0; i
< n
; i
++) {
480 dbversion
= isc_mem_get(client
->mctx
, sizeof(*dbversion
));
481 if (dbversion
!= NULL
) {
482 dbversion
->db
= NULL
;
483 dbversion
->version
= NULL
;
484 ISC_LIST_INITANDAPPEND(client
->query
.freeversions
,
488 * We only return ISC_R_NOMEMORY if we couldn't
492 return (ISC_R_NOMEMORY
);
494 return (ISC_R_SUCCESS
);
498 return (ISC_R_SUCCESS
);
501 static inline ns_dbversion_t
*
502 query_getdbversion(ns_client_t
*client
) {
504 ns_dbversion_t
*dbversion
;
506 if (ISC_LIST_EMPTY(client
->query
.freeversions
)) {
507 result
= query_newdbversion(client
, 1);
508 if (result
!= ISC_R_SUCCESS
)
511 dbversion
= ISC_LIST_HEAD(client
->query
.freeversions
);
512 INSIST(dbversion
!= NULL
);
513 ISC_LIST_UNLINK(client
->query
.freeversions
, dbversion
, link
);
519 ns_query_init(ns_client_t
*client
) {
522 ISC_LIST_INIT(client
->query
.namebufs
);
523 ISC_LIST_INIT(client
->query
.activeversions
);
524 ISC_LIST_INIT(client
->query
.freeversions
);
525 client
->query
.restarts
= 0;
526 client
->query
.timerset
= ISC_FALSE
;
527 client
->query
.qname
= NULL
;
528 result
= isc_mutex_init(&client
->query
.fetchlock
);
529 if (result
!= ISC_R_SUCCESS
)
531 client
->query
.fetch
= NULL
;
532 client
->query
.authdb
= NULL
;
533 client
->query
.authzone
= NULL
;
534 client
->query
.authdbset
= ISC_FALSE
;
535 client
->query
.isreferral
= ISC_FALSE
;
536 query_reset(client
, ISC_FALSE
);
537 result
= query_newdbversion(client
, 3);
538 if (result
!= ISC_R_SUCCESS
) {
539 DESTROYLOCK(&client
->query
.fetchlock
);
542 result
= query_newnamebuf(client
);
543 if (result
!= ISC_R_SUCCESS
)
544 query_freefreeversions(client
, ISC_TRUE
);
549 static inline ns_dbversion_t
*
550 query_findversion(ns_client_t
*client
, dns_db_t
*db
,
551 isc_boolean_t
*newzonep
)
553 ns_dbversion_t
*dbversion
;
556 * We may already have done a query related to this
557 * database. If so, we must be sure to make subsequent
558 * queries from the same version.
560 for (dbversion
= ISC_LIST_HEAD(client
->query
.activeversions
);
562 dbversion
= ISC_LIST_NEXT(dbversion
, link
)) {
563 if (dbversion
->db
== db
)
567 if (dbversion
== NULL
) {
569 * This is a new zone for this query. Add it to
572 dbversion
= query_getdbversion(client
);
573 if (dbversion
== NULL
)
575 dns_db_attach(db
, &dbversion
->db
);
576 dns_db_currentversion(db
, &dbversion
->version
);
577 dbversion
->queryok
= ISC_FALSE
;
578 ISC_LIST_APPEND(client
->query
.activeversions
,
580 *newzonep
= ISC_TRUE
;
582 *newzonep
= ISC_FALSE
;
587 static inline isc_result_t
588 query_validatezonedb(ns_client_t
*client
, dns_name_t
*name
,
589 dns_rdatatype_t qtype
, unsigned int options
,
590 dns_zone_t
*zone
, dns_db_t
*db
,
591 dns_dbversion_t
**versionp
)
594 isc_boolean_t check_acl
, new_zone
;
596 ns_dbversion_t
*dbversion
;
598 REQUIRE(zone
!= NULL
);
602 * This limits our searching to the zone where the first name
603 * (the query target) was looked for. This prevents following
604 * CNAMES or DNAMES into other zones and prevents returning
605 * additional data from other zones.
607 if (!client
->view
->additionalfromauth
&&
608 client
->query
.authdbset
&&
609 db
!= client
->query
.authdb
)
613 * If the zone has an ACL, we'll check it, otherwise
614 * we use the view's "allow-query" ACL. Each ACL is only checked
617 * Also, get the database version to use.
620 check_acl
= ISC_TRUE
; /* Keep compiler happy. */
624 * Get the current version of this database.
626 dbversion
= query_findversion(client
, db
, &new_zone
);
627 if (dbversion
== NULL
) {
628 result
= DNS_R_SERVFAIL
;
632 check_acl
= ISC_TRUE
;
633 } else if (!dbversion
->queryok
) {
636 check_acl
= ISC_FALSE
;
639 queryacl
= dns_zone_getqueryacl(zone
);
640 if (queryacl
== NULL
) {
641 queryacl
= client
->view
->queryacl
;
642 if ((client
->query
.attributes
&
643 NS_QUERYATTR_QUERYOKVALID
) != 0) {
645 * We've evaluated the view's queryacl already. If
646 * NS_QUERYATTR_QUERYOK is set, then the client is
647 * allowed to make queries, otherwise the query should
650 check_acl
= ISC_FALSE
;
651 if ((client
->query
.attributes
&
652 NS_QUERYATTR_QUERYOK
) == 0)
656 * We haven't evaluated the view's queryacl yet.
658 check_acl
= ISC_TRUE
;
663 isc_boolean_t log
= ISC_TF((options
& DNS_GETDB_NOLOG
) == 0);
665 result
= ns_client_checkaclsilent(client
, NULL
, queryacl
,
668 char msg
[NS_CLIENT_ACLMSGSIZE("query")];
669 if (result
== ISC_R_SUCCESS
) {
670 if (isc_log_wouldlog(ns_g_lctx
,
673 ns_client_aclmsg("query", name
, qtype
,
674 client
->view
->rdclass
,
676 ns_client_log(client
,
677 DNS_LOGCATEGORY_SECURITY
,
683 ns_client_aclmsg("query", name
, qtype
,
684 client
->view
->rdclass
,
686 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
687 NS_LOGMODULE_QUERY
, ISC_LOG_INFO
,
692 if (queryacl
== client
->view
->queryacl
) {
693 if (result
== ISC_R_SUCCESS
) {
695 * We were allowed by the default
696 * "allow-query" ACL. Remember this so we
697 * don't have to check again.
699 client
->query
.attributes
|=
700 NS_QUERYATTR_QUERYOK
;
703 * We've now evaluated the view's query ACL, and
704 * the NS_QUERYATTR_QUERYOK attribute is now valid.
706 client
->query
.attributes
|= NS_QUERYATTR_QUERYOKVALID
;
709 if (result
!= ISC_R_SUCCESS
)
716 * Remember the result of the ACL check so we
717 * don't have to check again.
719 dbversion
->queryok
= ISC_TRUE
;
721 /* Transfer ownership, if necessary. */
722 if (versionp
!= NULL
)
723 *versionp
= dbversion
->version
;
725 return (ISC_R_SUCCESS
);
728 return (DNS_R_REFUSED
);
734 static inline isc_result_t
735 query_getzonedb(ns_client_t
*client
, dns_name_t
*name
, dns_rdatatype_t qtype
,
736 unsigned int options
, dns_zone_t
**zonep
, dns_db_t
**dbp
,
737 dns_dbversion_t
**versionp
)
740 unsigned int ztoptions
;
741 dns_zone_t
*zone
= NULL
;
743 isc_boolean_t partial
= ISC_FALSE
;
745 REQUIRE(zonep
!= NULL
&& *zonep
== NULL
);
746 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
749 * Find a zone database to answer the query.
751 ztoptions
= ((options
& DNS_GETDB_NOEXACT
) != 0) ?
752 DNS_ZTFIND_NOEXACT
: 0;
754 result
= dns_zt_find(client
->view
->zonetable
, name
, ztoptions
, NULL
,
756 if (result
== DNS_R_PARTIALMATCH
)
758 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
759 result
= dns_zone_getdb(zone
, &db
);
761 if (result
!= ISC_R_SUCCESS
)
764 result
= query_validatezonedb(client
, name
, qtype
, options
, zone
, db
,
767 if (result
!= ISC_R_SUCCESS
)
770 /* Transfer ownership. */
774 if (partial
&& (options
& DNS_GETDB_PARTIAL
) != 0)
775 return (DNS_R_PARTIALMATCH
);
776 return (ISC_R_SUCCESS
);
780 dns_zone_detach(&zone
);
787 static inline isc_result_t
788 query_getcachedb(ns_client_t
*client
, dns_name_t
*name
, dns_rdatatype_t qtype
,
789 dns_db_t
**dbp
, unsigned int options
)
792 isc_boolean_t check_acl
;
795 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
798 * Find a cache database to answer the query.
799 * This may fail with DNS_R_REFUSED if the client
800 * is not allowed to use the cache.
803 if (!USECACHE(client
))
804 return (DNS_R_REFUSED
);
805 dns_db_attach(client
->view
->cachedb
, &db
);
807 if ((client
->query
.attributes
&
808 NS_QUERYATTR_QUERYOKVALID
) != 0) {
810 * We've evaluated the view's queryacl already. If
811 * NS_QUERYATTR_QUERYOK is set, then the client is
812 * allowed to make queries, otherwise the query should
815 check_acl
= ISC_FALSE
;
816 if ((client
->query
.attributes
&
817 NS_QUERYATTR_QUERYOK
) == 0)
821 * We haven't evaluated the view's queryacl yet.
823 check_acl
= ISC_TRUE
;
827 isc_boolean_t log
= ISC_TF((options
& DNS_GETDB_NOLOG
) == 0);
828 char msg
[NS_CLIENT_ACLMSGSIZE("query (cache)")];
830 result
= ns_client_checkaclsilent(client
, NULL
,
831 client
->view
->queryacl
,
833 if (result
== ISC_R_SUCCESS
) {
835 * We were allowed by the default
836 * "allow-query" ACL. Remember this so we
837 * don't have to check again.
839 client
->query
.attributes
|=
840 NS_QUERYATTR_QUERYOK
;
841 if (log
&& isc_log_wouldlog(ns_g_lctx
,
844 ns_client_aclmsg("query (cache)", name
, qtype
,
845 client
->view
->rdclass
,
847 ns_client_log(client
,
848 DNS_LOGCATEGORY_SECURITY
,
854 ns_client_aclmsg("query (cache)", name
, qtype
,
855 client
->view
->rdclass
, msg
,
857 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
858 NS_LOGMODULE_QUERY
, ISC_LOG_INFO
,
862 * We've now evaluated the view's query ACL, and
863 * the NS_QUERYATTR_QUERYOK attribute is now valid.
865 client
->query
.attributes
|= NS_QUERYATTR_QUERYOKVALID
;
867 if (result
!= ISC_R_SUCCESS
)
873 /* Transfer ownership. */
876 return (ISC_R_SUCCESS
);
879 result
= DNS_R_REFUSED
;
888 static inline isc_result_t
889 query_getdb(ns_client_t
*client
, dns_name_t
*name
, dns_rdatatype_t qtype
,
890 unsigned int options
, dns_zone_t
**zonep
, dns_db_t
**dbp
,
891 dns_dbversion_t
**versionp
, isc_boolean_t
*is_zonep
)
896 isc_result_t tresult
;
897 unsigned int namelabels
;
898 unsigned int zonelabels
;
899 dns_zone_t
*zone
= NULL
;
902 REQUIRE(zonep
!= NULL
&& *zonep
== NULL
);
906 /* Calculate how many labels are in name. */
907 namelabels
= dns_name_countlabels(name
);
910 /* Try to find name in bind's standard database. */
911 result
= query_getzonedb(client
, name
, qtype
, options
, &zone
,
914 /* See how many labels are in the zone's name. */
915 if (result
== ISC_R_SUCCESS
&& zone
!= NULL
)
916 zonelabels
= dns_name_countlabels(dns_zone_getorigin(zone
));
918 * If # zone labels < # name labels, try to find an even better match
919 * Only try if a DLZ driver is loaded for this view
921 if (zonelabels
< namelabels
&& client
->view
->dlzdatabase
!= NULL
) {
922 tresult
= dns_dlzfindzone(client
->view
, name
,
924 /* If we successful, we found a better match. */
925 if (tresult
== ISC_R_SUCCESS
) {
927 * If the previous search returned a zone, detach it.
930 dns_zone_detach(&zone
);
933 * If the previous search returned a database,
940 * If the previous search returned a version, clear it.
945 * Get our database version.
947 dns_db_currentversion(tdbp
, versionp
);
950 * Be sure to return our database.
955 * We return a null zone, No stats for DLZ zones.
962 result
= query_getzonedb(client
, name
, qtype
, options
,
963 zonep
, dbp
, versionp
);
966 /* If successful, Transfer ownership of zone. */
967 if (result
== ISC_R_SUCCESS
) {
972 * If neither attempt above succeeded, return the cache instead
974 *is_zonep
= ISC_TRUE
;
975 } else if (result
== ISC_R_NOTFOUND
) {
976 result
= query_getcachedb(client
, name
, qtype
, dbp
, options
);
977 *is_zonep
= ISC_FALSE
;
982 static inline isc_boolean_t
983 query_isduplicate(ns_client_t
*client
, dns_name_t
*name
,
984 dns_rdatatype_t type
, dns_name_t
**mnamep
)
986 dns_section_t section
;
987 dns_name_t
*mname
= NULL
;
990 CTRACE("query_isduplicate");
992 for (section
= DNS_SECTION_ANSWER
;
993 section
<= DNS_SECTION_ADDITIONAL
;
995 result
= dns_message_findname(client
->message
, section
,
996 name
, type
, 0, &mname
, NULL
);
997 if (result
== ISC_R_SUCCESS
) {
999 * We've already got this RRset in the response.
1001 CTRACE("query_isduplicate: true: done");
1003 } else if (result
== DNS_R_NXRRSET
) {
1005 * The name exists, but the rdataset does not.
1007 if (section
== DNS_SECTION_ADDITIONAL
)
1010 RUNTIME_CHECK(result
== DNS_R_NXDOMAIN
);
1015 * If the dns_name_t we're looking up is already in the message,
1016 * we don't want to trigger the caller's name replacement logic.
1023 CTRACE("query_isduplicate: false: done");
1028 query_addadditional(void *arg
, dns_name_t
*name
, dns_rdatatype_t qtype
) {
1029 ns_client_t
*client
= arg
;
1030 isc_result_t result
, eresult
;
1033 dns_name_t
*fname
, *mname
;
1034 dns_rdataset_t
*rdataset
, *sigrdataset
, *trdataset
;
1037 dns_dbversion_t
*version
;
1038 isc_boolean_t added_something
, need_addname
;
1040 dns_rdatatype_t type
;
1042 REQUIRE(NS_CLIENT_VALID(client
));
1043 REQUIRE(qtype
!= dns_rdatatype_any
);
1045 if (!WANTDNSSEC(client
) && dns_rdatatype_isdnssec(qtype
))
1046 return (ISC_R_SUCCESS
);
1048 CTRACE("query_addadditional");
1053 eresult
= ISC_R_SUCCESS
;
1061 added_something
= ISC_FALSE
;
1062 need_addname
= ISC_FALSE
;
1066 * We treat type A additional section processing as if it
1067 * were "any address type" additional section processing.
1068 * To avoid multiple lookups, we do an 'any' database
1069 * lookup and iterate over the node.
1071 if (qtype
== dns_rdatatype_a
)
1072 type
= dns_rdatatype_any
;
1077 * Get some resources.
1079 dbuf
= query_getnamebuf(client
);
1082 fname
= query_newname(client
, dbuf
, &b
);
1083 rdataset
= query_newrdataset(client
);
1084 if (fname
== NULL
|| rdataset
== NULL
)
1086 if (WANTDNSSEC(client
)) {
1087 sigrdataset
= query_newrdataset(client
);
1088 if (sigrdataset
== NULL
)
1093 * Look for a zone database that might contain authoritative
1096 result
= query_getzonedb(client
, name
, qtype
, DNS_GETDB_NOLOG
,
1097 &zone
, &db
, &version
);
1098 if (result
!= ISC_R_SUCCESS
)
1101 CTRACE("query_addadditional: db_find");
1104 * Since we are looking for authoritative data, we do not set
1105 * the GLUEOK flag. Glue will be looked for later, but not
1106 * necessarily in the same database.
1109 result
= dns_db_find(db
, name
, version
, type
, client
->query
.dboptions
,
1110 client
->now
, &node
, fname
, rdataset
,
1112 if (result
== ISC_R_SUCCESS
)
1115 if (dns_rdataset_isassociated(rdataset
))
1116 dns_rdataset_disassociate(rdataset
);
1117 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
))
1118 dns_rdataset_disassociate(sigrdataset
);
1120 dns_db_detachnode(db
, &node
);
1125 * No authoritative data was found. The cache is our next best bet.
1129 result
= query_getcachedb(client
, name
, qtype
, &db
, DNS_GETDB_NOLOG
);
1130 if (result
!= ISC_R_SUCCESS
)
1132 * Most likely the client isn't allowed to query the cache.
1136 * Attempt to validate glue.
1138 if (sigrdataset
== NULL
) {
1139 sigrdataset
= query_newrdataset(client
);
1140 if (sigrdataset
== NULL
)
1143 result
= dns_db_find(db
, name
, version
, type
,
1144 client
->query
.dboptions
| DNS_DBFIND_GLUEOK
,
1145 client
->now
, &node
, fname
, rdataset
,
1147 if (result
== DNS_R_GLUE
&&
1148 validate(client
, db
, fname
, rdataset
, sigrdataset
))
1149 result
= ISC_R_SUCCESS
;
1150 if (!WANTDNSSEC(client
))
1151 query_putrdataset(client
, &sigrdataset
);
1152 if (result
== ISC_R_SUCCESS
)
1155 if (dns_rdataset_isassociated(rdataset
))
1156 dns_rdataset_disassociate(rdataset
);
1157 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
))
1158 dns_rdataset_disassociate(sigrdataset
);
1160 dns_db_detachnode(db
, &node
);
1165 * No cached data was found. Glue is our last chance.
1168 * NS records cause both the usual additional section
1169 * processing to locate a type A record, and, when used
1170 * in a referral, a special search of the zone in which
1171 * they reside for glue information.
1173 * This is the "special search". Note that we must search
1174 * the zone where the NS record resides, not the zone it
1175 * points to, and that we only do the search in the delegation
1176 * case (identified by client->query.gluedb being set).
1179 if (client
->query
.gluedb
== NULL
)
1183 * Don't poison caches using the bailiwick protection model.
1185 if (!dns_name_issubdomain(name
, dns_db_origin(client
->query
.gluedb
)))
1188 dns_db_attach(client
->query
.gluedb
, &db
);
1189 result
= dns_db_find(db
, name
, version
, type
,
1190 client
->query
.dboptions
| DNS_DBFIND_GLUEOK
,
1191 client
->now
, &node
, fname
, rdataset
,
1193 if (!(result
== ISC_R_SUCCESS
||
1194 result
== DNS_R_ZONECUT
||
1195 result
== DNS_R_GLUE
))
1200 * We have found a potential additional data rdataset, or
1201 * at least a node to iterate over.
1203 query_keepname(client
, fname
, dbuf
);
1206 * If we have an rdataset, add it to the additional data
1210 if (dns_rdataset_isassociated(rdataset
) &&
1211 !query_isduplicate(client
, fname
, type
, &mname
)) {
1212 if (mname
!= NULL
) {
1213 query_releasename(client
, &fname
);
1216 need_addname
= ISC_TRUE
;
1217 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1218 trdataset
= rdataset
;
1220 added_something
= ISC_TRUE
;
1222 * Note: we only add SIGs if we've added the type they cover,
1223 * so we do not need to check if the SIG rdataset is already
1226 if (sigrdataset
!= NULL
&&
1227 dns_rdataset_isassociated(sigrdataset
))
1229 ISC_LIST_APPEND(fname
->list
, sigrdataset
, link
);
1234 if (qtype
== dns_rdatatype_a
) {
1236 * We now go looking for A and AAAA records, along with
1239 * XXXRTH This code could be more efficient.
1241 if (rdataset
!= NULL
) {
1242 if (dns_rdataset_isassociated(rdataset
))
1243 dns_rdataset_disassociate(rdataset
);
1245 rdataset
= query_newrdataset(client
);
1246 if (rdataset
== NULL
)
1249 if (sigrdataset
!= NULL
) {
1250 if (dns_rdataset_isassociated(sigrdataset
))
1251 dns_rdataset_disassociate(sigrdataset
);
1252 } else if (WANTDNSSEC(client
)) {
1253 sigrdataset
= query_newrdataset(client
);
1254 if (sigrdataset
== NULL
)
1257 result
= dns_db_findrdataset(db
, node
, version
,
1259 client
->now
, rdataset
,
1261 if (result
== DNS_R_NCACHENXDOMAIN
)
1263 if (result
== DNS_R_NCACHENXRRSET
) {
1264 dns_rdataset_disassociate(rdataset
);
1266 * Negative cache entries don't have sigrdatasets.
1268 INSIST(sigrdataset
== NULL
||
1269 ! dns_rdataset_isassociated(sigrdataset
));
1271 if (result
== ISC_R_SUCCESS
) {
1273 if (!query_isduplicate(client
, fname
,
1274 dns_rdatatype_a
, &mname
)) {
1275 if (mname
!= NULL
) {
1276 query_releasename(client
, &fname
);
1279 need_addname
= ISC_TRUE
;
1280 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1281 added_something
= ISC_TRUE
;
1282 if (sigrdataset
!= NULL
&&
1283 dns_rdataset_isassociated(sigrdataset
))
1285 ISC_LIST_APPEND(fname
->list
,
1288 query_newrdataset(client
);
1290 rdataset
= query_newrdataset(client
);
1291 if (rdataset
== NULL
)
1293 if (WANTDNSSEC(client
) && sigrdataset
== NULL
)
1296 dns_rdataset_disassociate(rdataset
);
1297 if (sigrdataset
!= NULL
&&
1298 dns_rdataset_isassociated(sigrdataset
))
1299 dns_rdataset_disassociate(sigrdataset
);
1302 result
= dns_db_findrdataset(db
, node
, version
,
1303 dns_rdatatype_aaaa
, 0,
1304 client
->now
, rdataset
,
1306 if (result
== DNS_R_NCACHENXDOMAIN
)
1308 if (result
== DNS_R_NCACHENXRRSET
) {
1309 dns_rdataset_disassociate(rdataset
);
1310 INSIST(sigrdataset
== NULL
||
1311 ! dns_rdataset_isassociated(sigrdataset
));
1313 if (result
== ISC_R_SUCCESS
) {
1315 if (!query_isduplicate(client
, fname
,
1316 dns_rdatatype_aaaa
, &mname
)) {
1317 if (mname
!= NULL
) {
1318 query_releasename(client
, &fname
);
1321 need_addname
= ISC_TRUE
;
1322 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1323 added_something
= ISC_TRUE
;
1324 if (sigrdataset
!= NULL
&&
1325 dns_rdataset_isassociated(sigrdataset
))
1327 ISC_LIST_APPEND(fname
->list
,
1337 CTRACE("query_addadditional: addname");
1339 * If we haven't added anything, then we're done.
1341 if (!added_something
)
1345 * We may have added our rdatasets to an existing name, if so, then
1346 * need_addname will be ISC_FALSE. Whether we used an existing name
1347 * or a new one, we must set fname to NULL to prevent cleanup.
1350 dns_message_addname(client
->message
, fname
,
1351 DNS_SECTION_ADDITIONAL
);
1355 * In a few cases, we want to add additional data for additional
1356 * data. It's simpler to just deal with special cases here than
1357 * to try to create a general purpose mechanism and allow the
1358 * rdata implementations to do it themselves.
1360 * This involves recursion, but the depth is limited. The
1361 * most complex case is adding a SRV rdataset, which involves
1362 * recursing to add address records, which in turn can cause
1363 * recursion to add KEYs.
1365 if (type
== dns_rdatatype_srv
&& trdataset
!= NULL
) {
1367 * If we're adding SRV records to the additional data
1368 * section, it's helpful if we add the SRV additional data
1371 eresult
= dns_rdataset_additionaldata(trdataset
,
1372 query_addadditional
,
1377 CTRACE("query_addadditional: cleanup");
1378 query_putrdataset(client
, &rdataset
);
1379 if (sigrdataset
!= NULL
)
1380 query_putrdataset(client
, &sigrdataset
);
1382 query_releasename(client
, &fname
);
1384 dns_db_detachnode(db
, &node
);
1388 dns_zone_detach(&zone
);
1390 CTRACE("query_addadditional: done");
1395 query_discardcache(ns_client_t
*client
, dns_rdataset_t
*rdataset_base
,
1396 dns_rdatasetadditional_t additionaltype
,
1397 dns_rdatatype_t type
, dns_zone_t
**zonep
, dns_db_t
**dbp
,
1398 dns_dbversion_t
**versionp
, dns_dbnode_t
**nodep
,
1401 dns_rdataset_t
*rdataset
;
1403 while ((rdataset
= ISC_LIST_HEAD(fname
->list
)) != NULL
) {
1404 ISC_LIST_UNLINK(fname
->list
, rdataset
, link
);
1405 query_putrdataset(client
, &rdataset
);
1407 if (*versionp
!= NULL
)
1408 dns_db_closeversion(*dbp
, versionp
, ISC_FALSE
);
1410 dns_db_detachnode(*dbp
, nodep
);
1414 dns_zone_detach(zonep
);
1415 (void)dns_rdataset_putadditional(client
->view
->acache
, rdataset_base
,
1416 additionaltype
, type
);
1419 static inline isc_result_t
1420 query_iscachevalid(dns_zone_t
*zone
, dns_db_t
*db
, dns_db_t
*db0
,
1421 dns_dbversion_t
*version
)
1423 isc_result_t result
= ISC_R_SUCCESS
;
1424 dns_dbversion_t
*version_current
= NULL
;
1425 dns_db_t
*db_current
= db0
;
1427 if (db_current
== NULL
) {
1428 result
= dns_zone_getdb(zone
, &db_current
);
1429 if (result
!= ISC_R_SUCCESS
)
1432 dns_db_currentversion(db_current
, &version_current
);
1433 if (db_current
!= db
|| version_current
!= version
) {
1434 result
= ISC_R_FAILURE
;
1439 dns_db_closeversion(db_current
, &version_current
, ISC_FALSE
);
1440 if (db0
== NULL
&& db_current
!= NULL
)
1441 dns_db_detach(&db_current
);
1447 query_addadditional2(void *arg
, dns_name_t
*name
, dns_rdatatype_t qtype
) {
1448 client_additionalctx_t
*additionalctx
= arg
;
1449 dns_rdataset_t
*rdataset_base
;
1450 ns_client_t
*client
;
1451 isc_result_t result
, eresult
;
1452 dns_dbnode_t
*node
, *cnode
;
1454 dns_name_t
*fname
, *mname0
, cfname
;
1455 dns_rdataset_t
*rdataset
, *sigrdataset
;
1456 dns_rdataset_t
*crdataset
, *crdataset_next
;
1459 dns_dbversion_t
*version
, *cversion
;
1460 isc_boolean_t added_something
, need_addname
, needadditionalcache
;
1461 isc_boolean_t need_sigrrset
;
1463 dns_rdatatype_t type
;
1464 dns_rdatasetadditional_t additionaltype
;
1466 if (qtype
!= dns_rdatatype_a
) {
1468 * This function is optimized for "address" types. For other
1469 * types, use a generic routine.
1470 * XXX: ideally, this function should be generic enough.
1472 return (query_addadditional(additionalctx
->client
,
1479 rdataset_base
= additionalctx
->rdataset
;
1480 client
= additionalctx
->client
;
1481 REQUIRE(NS_CLIENT_VALID(client
));
1482 eresult
= ISC_R_SUCCESS
;
1492 added_something
= ISC_FALSE
;
1493 need_addname
= ISC_FALSE
;
1495 needadditionalcache
= ISC_FALSE
;
1496 additionaltype
= dns_rdatasetadditional_fromauth
;
1497 dns_name_init(&cfname
, NULL
);
1499 CTRACE("query_addadditional2");
1502 * We treat type A additional section processing as if it
1503 * were "any address type" additional section processing.
1504 * To avoid multiple lookups, we do an 'any' database
1505 * lookup and iterate over the node.
1506 * XXXJT: this approach can cause a suboptimal result when the cache
1507 * DB only has partial address types and the glue DB has remaining
1510 type
= dns_rdatatype_any
;
1513 * Get some resources.
1515 dbuf
= query_getnamebuf(client
);
1518 fname
= query_newname(client
, dbuf
, &b
);
1521 dns_name_setbuffer(&cfname
, &b
); /* share the buffer */
1523 /* Check additional cache */
1524 result
= dns_rdataset_getadditional(rdataset_base
, additionaltype
,
1525 type
, client
->view
->acache
, &zone
,
1526 &cdb
, &cversion
, &cnode
, &cfname
,
1527 client
->message
, client
->now
);
1528 if (result
!= ISC_R_SUCCESS
)
1531 CTRACE("query_addadditional2: auth zone not found");
1535 /* Is the cached DB up-to-date? */
1536 result
= query_iscachevalid(zone
, cdb
, NULL
, cversion
);
1537 if (result
!= ISC_R_SUCCESS
) {
1538 CTRACE("query_addadditional2: old auth additional cache");
1539 query_discardcache(client
, rdataset_base
, additionaltype
,
1540 type
, &zone
, &cdb
, &cversion
, &cnode
,
1545 if (cnode
== NULL
) {
1547 * We have a negative cache. We don't have to check the zone
1548 * ACL, since the result (not using this zone) would be same
1549 * regardless of the result.
1551 CTRACE("query_addadditional2: negative auth additional cache");
1552 dns_db_closeversion(cdb
, &cversion
, ISC_FALSE
);
1553 dns_db_detach(&cdb
);
1554 dns_zone_detach(&zone
);
1558 result
= query_validatezonedb(client
, name
, qtype
, DNS_GETDB_NOLOG
,
1560 if (result
!= ISC_R_SUCCESS
) {
1561 query_discardcache(client
, rdataset_base
, additionaltype
,
1562 type
, &zone
, &cdb
, &cversion
, &cnode
,
1567 /* We've got an active cache. */
1568 CTRACE("query_addadditional2: auth additional cache");
1569 dns_db_closeversion(cdb
, &cversion
, ISC_FALSE
);
1572 dns_name_clone(&cfname
, fname
);
1573 query_keepname(client
, fname
, dbuf
);
1577 * Look for a zone database that might contain authoritative
1581 result
= query_getzonedb(client
, name
, qtype
, DNS_GETDB_NOLOG
,
1582 &zone
, &db
, &version
);
1583 if (result
!= ISC_R_SUCCESS
) {
1584 /* Cache the negative result */
1585 (void)dns_rdataset_setadditional(rdataset_base
, additionaltype
,
1586 type
, client
->view
->acache
,
1587 NULL
, NULL
, NULL
, NULL
,
1592 CTRACE("query_addadditional2: db_find");
1595 * Since we are looking for authoritative data, we do not set
1596 * the GLUEOK flag. Glue will be looked for later, but not
1597 * necessarily in the same database.
1600 result
= dns_db_find(db
, name
, version
, type
, client
->query
.dboptions
,
1601 client
->now
, &node
, fname
, NULL
, NULL
);
1602 if (result
== ISC_R_SUCCESS
)
1605 /* Cache the negative result */
1606 (void)dns_rdataset_setadditional(rdataset_base
, additionaltype
,
1607 type
, client
->view
->acache
, zone
, db
,
1608 version
, NULL
, fname
);
1611 dns_db_detachnode(db
, &node
);
1616 * No authoritative data was found. The cache is our next best bet.
1620 additionaltype
= dns_rdatasetadditional_fromcache
;
1621 result
= query_getcachedb(client
, name
, qtype
, &db
, DNS_GETDB_NOLOG
);
1622 if (result
!= ISC_R_SUCCESS
)
1624 * Most likely the client isn't allowed to query the cache.
1628 result
= dns_db_find(db
, name
, version
, type
,
1629 client
->query
.dboptions
| DNS_DBFIND_GLUEOK
,
1630 client
->now
, &node
, fname
, NULL
, NULL
);
1631 if (result
== ISC_R_SUCCESS
)
1635 dns_db_detachnode(db
, &node
);
1640 * No cached data was found. Glue is our last chance.
1643 * NS records cause both the usual additional section
1644 * processing to locate a type A record, and, when used
1645 * in a referral, a special search of the zone in which
1646 * they reside for glue information.
1648 * This is the "special search". Note that we must search
1649 * the zone where the NS record resides, not the zone it
1650 * points to, and that we only do the search in the delegation
1651 * case (identified by client->query.gluedb being set).
1653 if (client
->query
.gluedb
== NULL
)
1657 * Don't poison caches using the bailiwick protection model.
1659 if (!dns_name_issubdomain(name
, dns_db_origin(client
->query
.gluedb
)))
1662 /* Check additional cache */
1663 additionaltype
= dns_rdatasetadditional_fromglue
;
1664 result
= dns_rdataset_getadditional(rdataset_base
, additionaltype
,
1665 type
, client
->view
->acache
, NULL
,
1666 &cdb
, &cversion
, &cnode
, &cfname
,
1667 client
->message
, client
->now
);
1668 if (result
!= ISC_R_SUCCESS
)
1671 result
= query_iscachevalid(zone
, cdb
, client
->query
.gluedb
, cversion
);
1672 if (result
!= ISC_R_SUCCESS
) {
1673 CTRACE("query_addadditional2: old glue additional cache");
1674 query_discardcache(client
, rdataset_base
, additionaltype
,
1675 type
, &zone
, &cdb
, &cversion
, &cnode
,
1680 if (cnode
== NULL
) {
1681 /* We have a negative cache. */
1682 CTRACE("query_addadditional2: negative glue additional cache");
1683 dns_db_closeversion(cdb
, &cversion
, ISC_FALSE
);
1684 dns_db_detach(&cdb
);
1689 CTRACE("query_addadditional2: glue additional cache");
1690 dns_db_closeversion(cdb
, &cversion
, ISC_FALSE
);
1693 dns_name_clone(&cfname
, fname
);
1694 query_keepname(client
, fname
, dbuf
);
1698 dns_db_attach(client
->query
.gluedb
, &db
);
1699 result
= dns_db_find(db
, name
, version
, type
,
1700 client
->query
.dboptions
| DNS_DBFIND_GLUEOK
,
1701 client
->now
, &node
, fname
, NULL
, NULL
);
1702 if (!(result
== ISC_R_SUCCESS
||
1703 result
== DNS_R_ZONECUT
||
1704 result
== DNS_R_GLUE
)) {
1705 /* cache the negative result */
1706 (void)dns_rdataset_setadditional(rdataset_base
, additionaltype
,
1707 type
, client
->view
->acache
,
1708 NULL
, db
, version
, NULL
,
1715 * We have found a DB node to iterate over from a DB.
1716 * We are going to look for address RRsets (i.e., A and AAAA) in the DB
1717 * node we've just found. We'll then store the complete information
1718 * in the additional data cache.
1720 dns_name_clone(fname
, &cfname
);
1721 query_keepname(client
, fname
, dbuf
);
1722 needadditionalcache
= ISC_TRUE
;
1724 rdataset
= query_newrdataset(client
);
1725 if (rdataset
== NULL
)
1728 sigrdataset
= query_newrdataset(client
);
1729 if (sigrdataset
== NULL
)
1733 * Find A RRset with sig RRset. Even if we don't find a sig RRset
1734 * for a client using DNSSEC, we'll continue the process to make a
1735 * complete list to be cached. However, we need to cancel the
1736 * caching when something unexpected happens, in order to avoid
1737 * caching incomplete information.
1739 result
= dns_db_findrdataset(db
, node
, version
, dns_rdatatype_a
, 0,
1740 client
->now
, rdataset
, sigrdataset
);
1742 * If we can't promote glue/pending from the cache to secure
1745 if (result
== ISC_R_SUCCESS
&&
1746 additionaltype
== dns_rdatasetadditional_fromcache
&&
1747 (rdataset
->trust
== dns_trust_pending
||
1748 rdataset
->trust
== dns_trust_glue
) &&
1749 !validate(client
, db
, fname
, rdataset
, sigrdataset
)) {
1750 dns_rdataset_disassociate(rdataset
);
1751 if (dns_rdataset_isassociated(sigrdataset
))
1752 dns_rdataset_disassociate(sigrdataset
);
1753 result
= ISC_R_NOTFOUND
;
1755 if (result
== DNS_R_NCACHENXDOMAIN
)
1757 if (result
== DNS_R_NCACHENXRRSET
) {
1758 dns_rdataset_disassociate(rdataset
);
1760 * Negative cache entries don't have sigrdatasets.
1762 INSIST(! dns_rdataset_isassociated(sigrdataset
));
1764 if (result
== ISC_R_SUCCESS
) {
1765 /* Remember the result as a cache */
1766 ISC_LIST_APPEND(cfname
.list
, rdataset
, link
);
1767 if (dns_rdataset_isassociated(sigrdataset
)) {
1768 ISC_LIST_APPEND(cfname
.list
, sigrdataset
, link
);
1769 sigrdataset
= query_newrdataset(client
);
1771 rdataset
= query_newrdataset(client
);
1772 if (sigrdataset
== NULL
|| rdataset
== NULL
) {
1773 /* do not cache incomplete information */
1778 /* Find AAAA RRset with sig RRset */
1779 result
= dns_db_findrdataset(db
, node
, version
, dns_rdatatype_aaaa
,
1780 0, client
->now
, rdataset
, sigrdataset
);
1782 * If we can't promote glue/pending from the cache to secure
1785 if (result
== ISC_R_SUCCESS
&&
1786 additionaltype
== dns_rdatasetadditional_fromcache
&&
1787 (rdataset
->trust
== dns_trust_pending
||
1788 rdataset
->trust
== dns_trust_glue
) &&
1789 !validate(client
, db
, fname
, rdataset
, sigrdataset
)) {
1790 dns_rdataset_disassociate(rdataset
);
1791 if (dns_rdataset_isassociated(sigrdataset
))
1792 dns_rdataset_disassociate(sigrdataset
);
1793 result
= ISC_R_NOTFOUND
;
1795 if (result
== ISC_R_SUCCESS
) {
1796 ISC_LIST_APPEND(cfname
.list
, rdataset
, link
);
1798 if (dns_rdataset_isassociated(sigrdataset
)) {
1799 ISC_LIST_APPEND(cfname
.list
, sigrdataset
, link
);
1806 * Set the new result in the cache if required. We do not support
1807 * caching additional data from a cache DB.
1809 if (needadditionalcache
== ISC_TRUE
&&
1810 (additionaltype
== dns_rdatasetadditional_fromauth
||
1811 additionaltype
== dns_rdatasetadditional_fromglue
)) {
1812 (void)dns_rdataset_setadditional(rdataset_base
, additionaltype
,
1813 type
, client
->view
->acache
,
1814 zone
, db
, version
, node
,
1819 need_sigrrset
= ISC_FALSE
;
1821 for (crdataset
= ISC_LIST_HEAD(cfname
.list
);
1823 crdataset
= crdataset_next
) {
1826 crdataset_next
= ISC_LIST_NEXT(crdataset
, link
);
1829 if (crdataset
->type
== dns_rdatatype_a
||
1830 crdataset
->type
== dns_rdatatype_aaaa
) {
1831 if (!query_isduplicate(client
, fname
, crdataset
->type
,
1833 if (mname
!= NULL
) {
1835 * A different type of this name is
1836 * already stored in the additional
1837 * section. We'll reuse the name.
1838 * Note that this should happen at most
1839 * once. Otherwise, fname->link could
1842 INSIST(mname0
== NULL
);
1844 query_releasename(client
, &fname
);
1848 need_addname
= ISC_TRUE
;
1849 ISC_LIST_UNLINK(cfname
.list
, crdataset
, link
);
1850 ISC_LIST_APPEND(fname
->list
, crdataset
, link
);
1851 added_something
= ISC_TRUE
;
1852 need_sigrrset
= ISC_TRUE
;
1854 need_sigrrset
= ISC_FALSE
;
1855 } else if (crdataset
->type
== dns_rdatatype_rrsig
&&
1856 need_sigrrset
&& WANTDNSSEC(client
)) {
1857 ISC_LIST_UNLINK(cfname
.list
, crdataset
, link
);
1858 ISC_LIST_APPEND(fname
->list
, crdataset
, link
);
1859 added_something
= ISC_TRUE
; /* just in case */
1860 need_sigrrset
= ISC_FALSE
;
1864 CTRACE("query_addadditional2: addname");
1867 * If we haven't added anything, then we're done.
1869 if (!added_something
)
1873 * We may have added our rdatasets to an existing name, if so, then
1874 * need_addname will be ISC_FALSE. Whether we used an existing name
1875 * or a new one, we must set fname to NULL to prevent cleanup.
1878 dns_message_addname(client
->message
, fname
,
1879 DNS_SECTION_ADDITIONAL
);
1883 CTRACE("query_addadditional2: cleanup");
1885 if (rdataset
!= NULL
)
1886 query_putrdataset(client
, &rdataset
);
1887 if (sigrdataset
!= NULL
)
1888 query_putrdataset(client
, &sigrdataset
);
1889 while ((crdataset
= ISC_LIST_HEAD(cfname
.list
)) != NULL
) {
1890 ISC_LIST_UNLINK(cfname
.list
, crdataset
, link
);
1891 query_putrdataset(client
, &crdataset
);
1894 query_releasename(client
, &fname
);
1896 dns_db_detachnode(db
, &node
);
1900 dns_zone_detach(&zone
);
1902 CTRACE("query_addadditional2: done");
1907 query_addrdataset(ns_client_t
*client
, dns_name_t
*fname
,
1908 dns_rdataset_t
*rdataset
)
1910 client_additionalctx_t additionalctx
;
1913 * Add 'rdataset' and any pertinent additional data to
1914 * 'fname', a name in the response message for 'client'.
1917 CTRACE("query_addrdataset");
1919 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1921 if (client
->view
->order
!= NULL
)
1922 rdataset
->attributes
|= dns_order_find(client
->view
->order
,
1923 fname
, rdataset
->type
,
1925 rdataset
->attributes
|= DNS_RDATASETATTR_LOADORDER
;
1927 if (NOADDITIONAL(client
))
1931 * Add additional data.
1933 * We don't care if dns_rdataset_additionaldata() fails.
1935 additionalctx
.client
= client
;
1936 additionalctx
.rdataset
= rdataset
;
1937 (void)dns_rdataset_additionaldata(rdataset
, query_addadditional2
,
1939 CTRACE("query_addrdataset: done");
1943 query_addrrset(ns_client_t
*client
, dns_name_t
**namep
,
1944 dns_rdataset_t
**rdatasetp
, dns_rdataset_t
**sigrdatasetp
,
1945 isc_buffer_t
*dbuf
, dns_section_t section
)
1947 dns_name_t
*name
, *mname
;
1948 dns_rdataset_t
*rdataset
, *mrdataset
, *sigrdataset
;
1949 isc_result_t result
;
1952 * To the current response for 'client', add the answer RRset
1953 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
1954 * owner name '*namep', to section 'section', unless they are
1955 * already there. Also add any pertinent additional data.
1957 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
1958 * stored in 'dbuf'. In this case, query_addrrset() guarantees that
1959 * when it returns the name will either have been kept or released.
1961 CTRACE("query_addrrset");
1963 rdataset
= *rdatasetp
;
1964 if (sigrdatasetp
!= NULL
)
1965 sigrdataset
= *sigrdatasetp
;
1970 result
= dns_message_findname(client
->message
, section
,
1971 name
, rdataset
->type
, rdataset
->covers
,
1972 &mname
, &mrdataset
);
1973 if (result
== ISC_R_SUCCESS
) {
1975 * We've already got an RRset of the given name and type.
1976 * There's nothing else to do;
1978 CTRACE("query_addrrset: dns_message_findname succeeded: done");
1980 query_releasename(client
, namep
);
1982 } else if (result
== DNS_R_NXDOMAIN
) {
1984 * The name doesn't exist.
1987 query_keepname(client
, name
, dbuf
);
1988 dns_message_addname(client
->message
, name
, section
);
1992 RUNTIME_CHECK(result
== DNS_R_NXRRSET
);
1994 query_releasename(client
, namep
);
1997 if (rdataset
->trust
!= dns_trust_secure
&&
1998 (section
== DNS_SECTION_ANSWER
||
1999 section
== DNS_SECTION_AUTHORITY
))
2000 client
->query
.attributes
&= ~NS_QUERYATTR_SECURE
;
2002 * Note: we only add SIGs if we've added the type they cover, so
2003 * we do not need to check if the SIG rdataset is already in the
2006 query_addrdataset(client
, mname
, rdataset
);
2008 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
)) {
2010 * We have a signature. Add it to the response.
2012 ISC_LIST_APPEND(mname
->list
, sigrdataset
, link
);
2013 *sigrdatasetp
= NULL
;
2015 CTRACE("query_addrrset: done");
2018 static inline isc_result_t
2019 query_addsoa(ns_client_t
*client
, dns_db_t
*db
, dns_dbversion_t
*version
,
2020 isc_boolean_t zero_ttl
)
2024 isc_result_t result
, eresult
;
2025 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
2026 dns_rdataset_t
**sigrdatasetp
= NULL
;
2028 CTRACE("query_addsoa");
2032 eresult
= ISC_R_SUCCESS
;
2038 * Get resources and make 'name' be the database origin.
2040 result
= dns_message_gettempname(client
->message
, &name
);
2041 if (result
!= ISC_R_SUCCESS
)
2043 dns_name_init(name
, NULL
);
2044 dns_name_clone(dns_db_origin(db
), name
);
2045 rdataset
= query_newrdataset(client
);
2046 if (rdataset
== NULL
) {
2047 eresult
= DNS_R_SERVFAIL
;
2050 if (WANTDNSSEC(client
)) {
2051 sigrdataset
= query_newrdataset(client
);
2052 if (sigrdataset
== NULL
) {
2053 eresult
= DNS_R_SERVFAIL
;
2061 result
= dns_db_getoriginnode(db
, &node
);
2062 if (result
== ISC_R_SUCCESS
) {
2063 result
= dns_db_findrdataset(db
, node
, version
,
2065 0, client
->now
, rdataset
,
2068 dns_fixedname_t foundname
;
2071 dns_fixedname_init(&foundname
);
2072 fname
= dns_fixedname_name(&foundname
);
2074 result
= dns_db_find(db
, name
, version
, dns_rdatatype_soa
,
2075 client
->query
.dboptions
, 0, &node
,
2076 fname
, rdataset
, sigrdataset
);
2078 if (result
!= ISC_R_SUCCESS
) {
2080 * This is bad. We tried to get the SOA RR at the zone top
2081 * and it didn't work!
2083 eresult
= DNS_R_SERVFAIL
;
2086 * Extract the SOA MINIMUM.
2088 dns_rdata_soa_t soa
;
2089 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2090 result
= dns_rdataset_first(rdataset
);
2091 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2092 dns_rdataset_current(rdataset
, &rdata
);
2093 result
= dns_rdata_tostruct(&rdata
, &soa
, NULL
);
2094 if (result
!= ISC_R_SUCCESS
)
2099 if (sigrdataset
!= NULL
)
2100 sigrdataset
->ttl
= 0;
2104 * Add the SOA and its SIG to the response, with the
2105 * TTLs adjusted per RFC2308 section 3.
2107 if (rdataset
->ttl
> soa
.minimum
)
2108 rdataset
->ttl
= soa
.minimum
;
2109 if (sigrdataset
!= NULL
&& sigrdataset
->ttl
> soa
.minimum
)
2110 sigrdataset
->ttl
= soa
.minimum
;
2112 if (sigrdataset
!= NULL
)
2113 sigrdatasetp
= &sigrdataset
;
2115 sigrdatasetp
= NULL
;
2116 query_addrrset(client
, &name
, &rdataset
, sigrdatasetp
, NULL
,
2117 DNS_SECTION_AUTHORITY
);
2121 query_putrdataset(client
, &rdataset
);
2122 if (sigrdataset
!= NULL
)
2123 query_putrdataset(client
, &sigrdataset
);
2125 query_releasename(client
, &name
);
2127 dns_db_detachnode(db
, &node
);
2132 static inline isc_result_t
2133 query_addns(ns_client_t
*client
, dns_db_t
*db
, dns_dbversion_t
*version
) {
2134 dns_name_t
*name
, *fname
;
2136 isc_result_t result
, eresult
;
2137 dns_fixedname_t foundname
;
2138 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
2139 dns_rdataset_t
**sigrdatasetp
= NULL
;
2141 CTRACE("query_addns");
2145 eresult
= ISC_R_SUCCESS
;
2149 dns_fixedname_init(&foundname
);
2150 fname
= dns_fixedname_name(&foundname
);
2153 * Get resources and make 'name' be the database origin.
2155 result
= dns_message_gettempname(client
->message
, &name
);
2156 if (result
!= ISC_R_SUCCESS
) {
2157 CTRACE("query_addns: dns_message_gettempname failed: done");
2160 dns_name_init(name
, NULL
);
2161 dns_name_clone(dns_db_origin(db
), name
);
2162 rdataset
= query_newrdataset(client
);
2163 if (rdataset
== NULL
) {
2164 CTRACE("query_addns: query_newrdataset failed");
2165 eresult
= DNS_R_SERVFAIL
;
2168 if (WANTDNSSEC(client
)) {
2169 sigrdataset
= query_newrdataset(client
);
2170 if (sigrdataset
== NULL
) {
2171 CTRACE("query_addns: query_newrdataset failed");
2172 eresult
= DNS_R_SERVFAIL
;
2178 * Find the NS rdataset.
2180 result
= dns_db_getoriginnode(db
, &node
);
2181 if (result
== ISC_R_SUCCESS
) {
2182 result
= dns_db_findrdataset(db
, node
, version
,
2184 0, client
->now
, rdataset
,
2187 CTRACE("query_addns: calling dns_db_find");
2188 result
= dns_db_find(db
, name
, NULL
, dns_rdatatype_ns
,
2189 client
->query
.dboptions
, 0, &node
,
2190 fname
, rdataset
, sigrdataset
);
2191 CTRACE("query_addns: dns_db_find complete");
2193 if (result
!= ISC_R_SUCCESS
) {
2194 CTRACE("query_addns: "
2195 "dns_db_findrdataset or dns_db_find failed");
2197 * This is bad. We tried to get the NS rdataset at the zone
2198 * top and it didn't work!
2200 eresult
= DNS_R_SERVFAIL
;
2202 if (sigrdataset
!= NULL
)
2203 sigrdatasetp
= &sigrdataset
;
2205 sigrdatasetp
= NULL
;
2206 query_addrrset(client
, &name
, &rdataset
, sigrdatasetp
, NULL
,
2207 DNS_SECTION_AUTHORITY
);
2211 CTRACE("query_addns: cleanup");
2212 query_putrdataset(client
, &rdataset
);
2213 if (sigrdataset
!= NULL
)
2214 query_putrdataset(client
, &sigrdataset
);
2216 query_releasename(client
, &name
);
2218 dns_db_detachnode(db
, &node
);
2220 CTRACE("query_addns: done");
2224 static inline isc_result_t
2225 query_addcnamelike(ns_client_t
*client
, dns_name_t
*qname
, dns_name_t
*tname
,
2226 dns_trust_t trust
, dns_name_t
**anamep
, dns_rdatatype_t type
)
2228 dns_rdataset_t
*rdataset
;
2229 dns_rdatalist_t
*rdatalist
;
2231 isc_result_t result
;
2235 * We assume the name data referred to by tname won't go away.
2238 REQUIRE(anamep
!= NULL
);
2241 result
= dns_message_gettemprdatalist(client
->message
, &rdatalist
);
2242 if (result
!= ISC_R_SUCCESS
)
2245 result
= dns_message_gettemprdata(client
->message
, &rdata
);
2246 if (result
!= ISC_R_SUCCESS
)
2249 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
2250 if (result
!= ISC_R_SUCCESS
)
2252 dns_rdataset_init(rdataset
);
2253 result
= dns_name_dup(qname
, client
->mctx
, *anamep
);
2254 if (result
!= ISC_R_SUCCESS
) {
2255 dns_message_puttemprdataset(client
->message
, &rdataset
);
2259 rdatalist
->type
= type
;
2260 rdatalist
->covers
= 0;
2261 rdatalist
->rdclass
= client
->message
->rdclass
;
2264 dns_name_toregion(tname
, &r
);
2265 rdata
->data
= r
.base
;
2266 rdata
->length
= r
.length
;
2267 rdata
->rdclass
= client
->message
->rdclass
;
2270 ISC_LIST_INIT(rdatalist
->rdata
);
2271 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
2272 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
, rdataset
)
2274 rdataset
->trust
= trust
;
2276 query_addrrset(client
, anamep
, &rdataset
, NULL
, NULL
,
2277 DNS_SECTION_ANSWER
);
2279 if (rdataset
!= NULL
) {
2280 if (dns_rdataset_isassociated(rdataset
))
2281 dns_rdataset_disassociate(rdataset
);
2282 dns_message_puttemprdataset(client
->message
, &rdataset
);
2285 return (ISC_R_SUCCESS
);
2289 * Mark the RRsets as secure. Update the cache (db) to reflect the
2290 * change in trust level.
2293 mark_secure(ns_client_t
*client
, dns_db_t
*db
, dns_name_t
*name
,
2294 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
2296 isc_result_t result
;
2297 dns_dbnode_t
*node
= NULL
;
2299 rdataset
->trust
= dns_trust_secure
;
2300 sigrdataset
->trust
= dns_trust_secure
;
2303 * Save the updated secure state. Ignore failures.
2305 result
= dns_db_findnode(db
, name
, ISC_TRUE
, &node
);
2306 if (result
!= ISC_R_SUCCESS
)
2308 (void)dns_db_addrdataset(db
, node
, NULL
, client
->now
, rdataset
,
2310 (void)dns_db_addrdataset(db
, node
, NULL
, client
->now
, sigrdataset
,
2312 dns_db_detachnode(db
, &node
);
2316 * Find the secure key that corresponds to rrsig.
2317 * Note: 'keyrdataset' maintains state between successive calls,
2318 * there may be multiple keys with the same keyid.
2319 * Return ISC_FALSE if we have exhausted all the possible keys.
2321 static isc_boolean_t
2322 get_key(ns_client_t
*client
, dns_db_t
*db
, dns_rdata_rrsig_t
*rrsig
,
2323 dns_rdataset_t
*keyrdataset
, dst_key_t
**keyp
)
2325 isc_result_t result
;
2326 dns_dbnode_t
*node
= NULL
;
2327 isc_boolean_t secure
= ISC_FALSE
;
2329 if (!dns_rdataset_isassociated(keyrdataset
)) {
2330 result
= dns_db_findnode(db
, &rrsig
->signer
, ISC_FALSE
, &node
);
2331 if (result
!= ISC_R_SUCCESS
)
2334 result
= dns_db_findrdataset(db
, node
, NULL
,
2335 dns_rdatatype_dnskey
, 0,
2336 client
->now
, keyrdataset
, NULL
);
2337 dns_db_detachnode(db
, &node
);
2338 if (result
!= ISC_R_SUCCESS
)
2341 if (keyrdataset
->trust
!= dns_trust_secure
)
2344 result
= dns_rdataset_first(keyrdataset
);
2346 result
= dns_rdataset_next(keyrdataset
);
2348 for ( ; result
== ISC_R_SUCCESS
;
2349 result
= dns_rdataset_next(keyrdataset
)) {
2350 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2353 dns_rdataset_current(keyrdataset
, &rdata
);
2354 isc_buffer_init(&b
, rdata
.data
, rdata
.length
);
2355 isc_buffer_add(&b
, rdata
.length
);
2356 result
= dst_key_fromdns(&rrsig
->signer
, rdata
.rdclass
, &b
,
2357 client
->mctx
, keyp
);
2358 if (result
!= ISC_R_SUCCESS
)
2360 if (rrsig
->algorithm
== (dns_secalg_t
)dst_key_alg(*keyp
) &&
2361 rrsig
->keyid
== (dns_keytag_t
)dst_key_id(*keyp
) &&
2362 dst_key_iszonekey(*keyp
)) {
2371 static isc_boolean_t
2372 verify(dst_key_t
*key
, dns_name_t
*name
, dns_rdataset_t
*rdataset
,
2373 dns_rdata_t
*rdata
, isc_mem_t
*mctx
, isc_boolean_t acceptexpired
)
2375 isc_result_t result
;
2376 dns_fixedname_t fixed
;
2377 isc_boolean_t ignore
= ISC_FALSE
;
2379 dns_fixedname_init(&fixed
);
2382 result
= dns_dnssec_verify2(name
, rdataset
, key
, ignore
, mctx
,
2384 if (result
== DNS_R_SIGEXPIRED
&& acceptexpired
) {
2388 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_FROMWILDCARD
)
2394 * Validate the rdataset if possible with available records.
2396 static isc_boolean_t
2397 validate(ns_client_t
*client
, dns_db_t
*db
, dns_name_t
*name
,
2398 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
2400 isc_result_t result
;
2401 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2402 dns_rdata_rrsig_t rrsig
;
2403 dst_key_t
*key
= NULL
;
2404 dns_rdataset_t keyrdataset
;
2406 if (sigrdataset
== NULL
|| !dns_rdataset_isassociated(sigrdataset
))
2409 for (result
= dns_rdataset_first(sigrdataset
);
2410 result
== ISC_R_SUCCESS
;
2411 result
= dns_rdataset_next(sigrdataset
)) {
2413 dns_rdata_reset(&rdata
);
2414 dns_rdataset_current(sigrdataset
, &rdata
);
2415 result
= dns_rdata_tostruct(&rdata
, &rrsig
, NULL
);
2416 if (result
!= ISC_R_SUCCESS
)
2418 if (!dns_resolver_algorithm_supported(client
->view
->resolver
,
2419 name
, rrsig
.algorithm
))
2421 if (!dns_name_issubdomain(name
, &rrsig
.signer
))
2423 dns_rdataset_init(&keyrdataset
);
2425 if (!get_key(client
, db
, &rrsig
, &keyrdataset
, &key
))
2427 if (verify(key
, name
, rdataset
, &rdata
, client
->mctx
,
2428 client
->view
->acceptexpired
)) {
2430 dns_rdataset_disassociate(&keyrdataset
);
2431 mark_secure(client
, db
, name
, rdataset
,
2437 if (dns_rdataset_isassociated(&keyrdataset
))
2438 dns_rdataset_disassociate(&keyrdataset
);
2444 query_addbestns(ns_client_t
*client
) {
2447 dns_name_t
*fname
, *zfname
;
2448 dns_rdataset_t
*rdataset
, *sigrdataset
, *zrdataset
, *zsigrdataset
;
2449 isc_boolean_t is_zone
, use_zone
;
2451 isc_result_t result
;
2452 dns_dbversion_t
*version
;
2456 CTRACE("query_addbestns");
2462 zsigrdataset
= NULL
;
2468 is_zone
= ISC_FALSE
;
2469 use_zone
= ISC_FALSE
;
2472 * Find the right database.
2474 result
= query_getdb(client
, client
->query
.qname
, dns_rdatatype_ns
, 0,
2475 &zone
, &db
, &version
, &is_zone
);
2476 if (result
!= ISC_R_SUCCESS
)
2481 * We'll need some resources...
2483 dbuf
= query_getnamebuf(client
);
2486 fname
= query_newname(client
, dbuf
, &b
);
2487 rdataset
= query_newrdataset(client
);
2488 if (fname
== NULL
|| rdataset
== NULL
)
2491 * Get the RRSIGs if the client requested them or if we may
2492 * need to validate answers from the cache.
2494 if (WANTDNSSEC(client
) || !is_zone
) {
2495 sigrdataset
= query_newrdataset(client
);
2496 if (sigrdataset
== NULL
)
2501 * Now look for the zonecut.
2504 result
= dns_db_find(db
, client
->query
.qname
, version
,
2505 dns_rdatatype_ns
, client
->query
.dboptions
,
2506 client
->now
, &node
, fname
,
2507 rdataset
, sigrdataset
);
2508 if (result
!= DNS_R_DELEGATION
)
2510 if (USECACHE(client
)) {
2511 query_keepname(client
, fname
, dbuf
);
2515 zrdataset
= rdataset
;
2517 zsigrdataset
= sigrdataset
;
2519 dns_db_detachnode(db
, &node
);
2522 dns_db_attach(client
->view
->cachedb
, &db
);
2523 is_zone
= ISC_FALSE
;
2527 result
= dns_db_findzonecut(db
, client
->query
.qname
,
2528 client
->query
.dboptions
,
2529 client
->now
, &node
, fname
,
2530 rdataset
, sigrdataset
);
2531 if (result
== ISC_R_SUCCESS
) {
2532 if (zfname
!= NULL
&&
2533 !dns_name_issubdomain(fname
, zfname
)) {
2535 * We found a zonecut in the cache, but our
2536 * zone delegation is better.
2538 use_zone
= ISC_TRUE
;
2540 } else if (result
== ISC_R_NOTFOUND
&& zfname
!= NULL
) {
2542 * We didn't find anything in the cache, but we
2543 * have a zone delegation, so use it.
2545 use_zone
= ISC_TRUE
;
2551 query_releasename(client
, &fname
);
2555 * We've already done query_keepname() on
2556 * zfname, so we must set dbuf to NULL to
2557 * prevent query_addrrset() from trying to
2558 * call query_keepname() again.
2561 query_putrdataset(client
, &rdataset
);
2562 if (sigrdataset
!= NULL
)
2563 query_putrdataset(client
, &sigrdataset
);
2564 rdataset
= zrdataset
;
2566 sigrdataset
= zsigrdataset
;
2567 zsigrdataset
= NULL
;
2571 * Attempt to validate RRsets that are pending or that are glue.
2573 if ((rdataset
->trust
== dns_trust_pending
||
2574 (sigrdataset
!= NULL
&& sigrdataset
->trust
== dns_trust_pending
))
2575 && !validate(client
, db
, fname
, rdataset
, sigrdataset
) &&
2576 (client
->query
.dboptions
& DNS_DBFIND_PENDINGOK
) == 0)
2579 if ((rdataset
->trust
== dns_trust_glue
||
2580 (sigrdataset
!= NULL
&& sigrdataset
->trust
== dns_trust_glue
)) &&
2581 !validate(client
, db
, fname
, rdataset
, sigrdataset
) &&
2582 SECURE(client
) && WANTDNSSEC(client
))
2586 * If the client doesn't want DNSSEC we can discard the sigrdataset
2589 if (!WANTDNSSEC(client
))
2590 query_putrdataset(client
, &sigrdataset
);
2591 query_addrrset(client
, &fname
, &rdataset
, &sigrdataset
, dbuf
,
2592 DNS_SECTION_AUTHORITY
);
2595 if (rdataset
!= NULL
)
2596 query_putrdataset(client
, &rdataset
);
2597 if (sigrdataset
!= NULL
)
2598 query_putrdataset(client
, &sigrdataset
);
2600 query_releasename(client
, &fname
);
2602 dns_db_detachnode(db
, &node
);
2606 dns_zone_detach(&zone
);
2608 query_putrdataset(client
, &zrdataset
);
2609 if (zsigrdataset
!= NULL
)
2610 query_putrdataset(client
, &zsigrdataset
);
2612 query_releasename(client
, &zfname
);
2613 dns_db_detach(&zdb
);
2618 query_addds(ns_client_t
*client
, dns_db_t
*db
, dns_dbnode_t
*node
,
2619 dns_dbversion_t
*version
)
2622 dns_rdataset_t
*rdataset
, *sigrdataset
;
2623 isc_result_t result
;
2625 CTRACE("query_addds");
2631 * We'll need some resources...
2633 rdataset
= query_newrdataset(client
);
2634 sigrdataset
= query_newrdataset(client
);
2635 if (rdataset
== NULL
|| sigrdataset
== NULL
)
2639 * Look for the DS record, which may or may not be present.
2641 result
= dns_db_findrdataset(db
, node
, version
, dns_rdatatype_ds
, 0,
2642 client
->now
, rdataset
, sigrdataset
);
2644 * If we didn't find it, look for an NSEC. */
2645 if (result
== ISC_R_NOTFOUND
)
2646 result
= dns_db_findrdataset(db
, node
, version
,
2647 dns_rdatatype_nsec
, 0, client
->now
,
2648 rdataset
, sigrdataset
);
2649 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOTFOUND
)
2651 if (!dns_rdataset_isassociated(rdataset
) ||
2652 !dns_rdataset_isassociated(sigrdataset
))
2656 * We've already added the NS record, so if the name's not there,
2657 * we have other problems. Use this name rather than calling
2660 result
= dns_message_firstname(client
->message
, DNS_SECTION_AUTHORITY
);
2661 if (result
!= ISC_R_SUCCESS
)
2665 dns_message_currentname(client
->message
, DNS_SECTION_AUTHORITY
,
2667 result
= dns_message_findtype(rname
, dns_rdatatype_ns
, 0, NULL
);
2668 if (result
!= ISC_R_SUCCESS
)
2671 ISC_LIST_APPEND(rname
->list
, rdataset
, link
);
2672 ISC_LIST_APPEND(rname
->list
, sigrdataset
, link
);
2677 if (rdataset
!= NULL
)
2678 query_putrdataset(client
, &rdataset
);
2679 if (sigrdataset
!= NULL
)
2680 query_putrdataset(client
, &sigrdataset
);
2684 query_addwildcardproof(ns_client_t
*client
, dns_db_t
*db
,
2685 dns_dbversion_t
*version
, dns_name_t
*name
,
2686 isc_boolean_t ispositive
)
2688 isc_buffer_t
*dbuf
, b
;
2690 dns_rdataset_t
*rdataset
, *sigrdataset
;
2691 dns_fixedname_t wfixed
;
2694 unsigned int options
;
2695 unsigned int olabels
, nlabels
;
2696 isc_result_t result
;
2697 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2698 dns_rdata_nsec_t nsec
;
2699 isc_boolean_t have_wname
;
2702 CTRACE("query_addwildcardproof");
2709 * Get the NOQNAME proof then if !ispositive
2710 * get the NOWILDCARD proof.
2712 * DNS_DBFIND_NOWILD finds the NSEC records that covers the
2713 * name ignoring any wildcard. From the owner and next names
2714 * of this record you can compute which wildcard (if it exists)
2715 * will match by finding the longest common suffix of the
2716 * owner name and next names with the qname and prefixing that
2717 * with the wildcard label.
2722 * example NSEC b.example
2724 * b.example NSEC a.d.example
2726 * a.d.example NSEC g.f.example
2728 * g.f.example NSEC z.i.example
2730 * z.i.example NSEC example
2733 * a.example -> example NSEC b.example
2734 * owner common example
2735 * next common example
2737 * d.b.example -> b.example NSEC a.d.example
2738 * owner common b.example
2739 * next common example
2741 * a.f.example -> a.d.example NSEC g.f.example
2742 * owner common example
2743 * next common f.example
2745 * j.example -> z.i.example NSEC example
2746 * owner common example
2747 * next common example
2750 options
= client
->query
.dboptions
| DNS_DBFIND_NOWILD
;
2751 dns_fixedname_init(&wfixed
);
2752 wname
= dns_fixedname_name(&wfixed
);
2754 have_wname
= ISC_FALSE
;
2756 * We'll need some resources...
2758 dbuf
= query_getnamebuf(client
);
2761 fname
= query_newname(client
, dbuf
, &b
);
2762 rdataset
= query_newrdataset(client
);
2763 sigrdataset
= query_newrdataset(client
);
2764 if (fname
== NULL
|| rdataset
== NULL
|| sigrdataset
== NULL
)
2767 result
= dns_db_find(db
, name
, version
, dns_rdatatype_nsec
, options
,
2768 0, &node
, fname
, rdataset
, sigrdataset
);
2770 dns_db_detachnode(db
, &node
);
2771 if (result
== DNS_R_NXDOMAIN
) {
2773 result
= dns_rdataset_first(rdataset
);
2774 if (result
== ISC_R_SUCCESS
) {
2775 dns_rdataset_current(rdataset
, &rdata
);
2776 result
= dns_rdata_tostruct(&rdata
, &nsec
, NULL
);
2778 if (result
== ISC_R_SUCCESS
) {
2779 (void)dns_name_fullcompare(name
, fname
, &order
,
2781 (void)dns_name_fullcompare(name
, &nsec
.next
, &order
,
2784 * Check for a pathological condition created when
2785 * serving some malformed signed zones and bail out.
2787 if (dns_name_countlabels(name
) == nlabels
)
2790 if (olabels
> nlabels
)
2791 dns_name_split(name
, olabels
, NULL
, wname
);
2793 dns_name_split(name
, nlabels
, NULL
, wname
);
2794 result
= dns_name_concatenate(dns_wildcardname
,
2795 wname
, wname
, NULL
);
2796 if (result
== ISC_R_SUCCESS
)
2797 have_wname
= ISC_TRUE
;
2798 dns_rdata_freestruct(&nsec
);
2800 query_addrrset(client
, &fname
, &rdataset
, &sigrdataset
,
2801 dbuf
, DNS_SECTION_AUTHORITY
);
2803 if (rdataset
!= NULL
)
2804 query_putrdataset(client
, &rdataset
);
2805 if (sigrdataset
!= NULL
)
2806 query_putrdataset(client
, &sigrdataset
);
2808 query_releasename(client
, &fname
);
2810 ispositive
= ISC_TRUE
; /* prevent loop */
2811 if (!dns_name_equal(name
, wname
)) {
2817 if (rdataset
!= NULL
)
2818 query_putrdataset(client
, &rdataset
);
2819 if (sigrdataset
!= NULL
)
2820 query_putrdataset(client
, &sigrdataset
);
2822 query_releasename(client
, &fname
);
2826 query_addnxrrsetnsec(ns_client_t
*client
, dns_db_t
*db
,
2827 dns_dbversion_t
*version
, dns_name_t
**namep
,
2828 dns_rdataset_t
**rdatasetp
, dns_rdataset_t
**sigrdatasetp
)
2831 dns_rdataset_t
*sigrdataset
;
2832 dns_rdata_t sigrdata
;
2833 dns_rdata_rrsig_t sig
;
2834 unsigned int labels
;
2835 isc_buffer_t
*dbuf
, b
;
2837 isc_result_t result
;
2840 if ((name
->attributes
& DNS_NAMEATTR_WILDCARD
) == 0) {
2841 query_addrrset(client
, namep
, rdatasetp
, sigrdatasetp
,
2842 NULL
, DNS_SECTION_AUTHORITY
);
2846 if (sigrdatasetp
== NULL
)
2848 sigrdataset
= *sigrdatasetp
;
2849 if (sigrdataset
== NULL
|| !dns_rdataset_isassociated(sigrdataset
))
2851 result
= dns_rdataset_first(sigrdataset
);
2852 if (result
!= ISC_R_SUCCESS
)
2854 dns_rdata_init(&sigrdata
);
2855 dns_rdataset_current(sigrdataset
, &sigrdata
);
2856 result
= dns_rdata_tostruct(&sigrdata
, &sig
, NULL
);
2857 if (result
!= ISC_R_SUCCESS
)
2860 labels
= dns_name_countlabels(name
);
2861 if ((unsigned int)sig
.labels
+ 1 >= labels
)
2865 query_addwildcardproof(client
, db
, version
, client
->query
.qname
,
2869 * We'll need some resources...
2871 dbuf
= query_getnamebuf(client
);
2874 fname
= query_newname(client
, dbuf
, &b
);
2877 dns_name_split(name
, sig
.labels
+ 1, NULL
, fname
);
2878 /* This will succeed, since we've stripped labels. */
2879 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname
, fname
, fname
,
2880 NULL
) == ISC_R_SUCCESS
);
2881 query_addrrset(client
, &fname
, rdatasetp
, sigrdatasetp
,
2882 dbuf
, DNS_SECTION_AUTHORITY
);
2886 query_resume(isc_task_t
*task
, isc_event_t
*event
) {
2887 dns_fetchevent_t
*devent
= (dns_fetchevent_t
*)event
;
2889 ns_client_t
*client
;
2890 isc_boolean_t fetch_canceled
, client_shuttingdown
;
2891 isc_result_t result
;
2892 isc_logcategory_t
*logcategory
= NS_LOGCATEGORY_QUERY_EERRORS
;
2896 * Resume a query after recursion.
2901 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
2902 client
= devent
->ev_arg
;
2903 REQUIRE(NS_CLIENT_VALID(client
));
2904 REQUIRE(task
== client
->task
);
2905 REQUIRE(RECURSING(client
));
2907 LOCK(&client
->query
.fetchlock
);
2908 if (client
->query
.fetch
!= NULL
) {
2910 * This is the fetch we've been waiting for.
2912 INSIST(devent
->fetch
== client
->query
.fetch
);
2913 client
->query
.fetch
= NULL
;
2914 fetch_canceled
= ISC_FALSE
;
2916 * Update client->now.
2918 isc_stdtime_get(&client
->now
);
2921 * This is a fetch completion event for a canceled fetch.
2922 * Clean up and don't resume the find.
2924 fetch_canceled
= ISC_TRUE
;
2926 UNLOCK(&client
->query
.fetchlock
);
2927 INSIST(client
->query
.fetch
== NULL
);
2929 client
->query
.attributes
&= ~NS_QUERYATTR_RECURSING
;
2930 fetch
= devent
->fetch
;
2931 devent
->fetch
= NULL
;
2934 * If this client is shutting down, or this transaction
2935 * has timed out, do not resume the find.
2937 client_shuttingdown
= ns_client_shuttingdown(client
);
2938 if (fetch_canceled
|| client_shuttingdown
) {
2939 if (devent
->node
!= NULL
)
2940 dns_db_detachnode(devent
->db
, &devent
->node
);
2941 if (devent
->db
!= NULL
)
2942 dns_db_detach(&devent
->db
);
2943 query_putrdataset(client
, &devent
->rdataset
);
2944 if (devent
->sigrdataset
!= NULL
)
2945 query_putrdataset(client
, &devent
->sigrdataset
);
2946 isc_event_free(&event
);
2948 query_error(client
, DNS_R_SERVFAIL
, __LINE__
);
2950 query_next(client
, ISC_R_CANCELED
);
2952 * This may destroy the client.
2954 ns_client_detach(&client
);
2956 result
= query_find(client
, devent
, 0);
2957 if (result
!= ISC_R_SUCCESS
) {
2958 if (result
== DNS_R_SERVFAIL
)
2959 errorloglevel
= ISC_LOG_DEBUG(2);
2961 errorloglevel
= ISC_LOG_DEBUG(4);
2962 if (isc_log_wouldlog(ns_g_lctx
, errorloglevel
)) {
2963 dns_resolver_logfetch(fetch
, ns_g_lctx
,
2966 errorloglevel
, ISC_FALSE
);
2971 dns_resolver_destroyfetch(&fetch
);
2975 query_recurse(ns_client_t
*client
, dns_rdatatype_t qtype
, dns_name_t
*qdomain
,
2976 dns_rdataset_t
*nameservers
, isc_boolean_t resuming
)
2978 isc_result_t result
;
2979 dns_rdataset_t
*rdataset
, *sigrdataset
;
2980 isc_sockaddr_t
*peeraddr
;
2983 inc_stats(client
, dns_nsstatscounter_recursion
);
2986 * We are about to recurse, which means that this client will
2987 * be unavailable for serving new requests for an indeterminate
2988 * amount of time. If this client is currently responsible
2989 * for handling incoming queries, set up a new client
2990 * object to handle them while we are waiting for a
2991 * response. There is no need to replace TCP clients
2992 * because those have already been replaced when the
2993 * connection was accepted (if allowed by the TCP quota).
2995 if (client
->recursionquota
== NULL
) {
2996 result
= isc_quota_attach(&ns_g_server
->recursionquota
,
2997 &client
->recursionquota
);
2998 if (result
== ISC_R_SOFTQUOTA
) {
2999 static isc_stdtime_t last
= 0;
3001 isc_stdtime_get(&now
);
3004 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
3007 "recursive-clients soft limit "
3008 "exceeded, aborting oldest query");
3010 ns_client_killoldestquery(client
);
3011 result
= ISC_R_SUCCESS
;
3012 } else if (result
== ISC_R_QUOTA
) {
3013 static isc_stdtime_t last
= 0;
3015 isc_stdtime_get(&now
);
3018 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
3021 "no more recursive clients: %s",
3022 isc_result_totext(result
));
3024 ns_client_killoldestquery(client
);
3026 if (result
== ISC_R_SUCCESS
&& !client
->mortal
&&
3027 (client
->attributes
& NS_CLIENTATTR_TCP
) == 0) {
3028 result
= ns_client_replace(client
);
3029 if (result
!= ISC_R_SUCCESS
) {
3030 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
3033 "ns_client_replace() failed: %s",
3034 isc_result_totext(result
));
3035 isc_quota_detach(&client
->recursionquota
);
3038 if (result
!= ISC_R_SUCCESS
)
3040 ns_client_recursing(client
);
3044 * Invoke the resolver.
3046 REQUIRE(nameservers
== NULL
|| nameservers
->type
== dns_rdatatype_ns
);
3047 REQUIRE(client
->query
.fetch
== NULL
);
3049 rdataset
= query_newrdataset(client
);
3050 if (rdataset
== NULL
)
3051 return (ISC_R_NOMEMORY
);
3052 if (WANTDNSSEC(client
)) {
3053 sigrdataset
= query_newrdataset(client
);
3054 if (sigrdataset
== NULL
) {
3055 query_putrdataset(client
, &rdataset
);
3056 return (ISC_R_NOMEMORY
);
3061 if (client
->query
.timerset
== ISC_FALSE
)
3062 ns_client_settimeout(client
, 60);
3063 if ((client
->attributes
& NS_CLIENTATTR_TCP
) == 0)
3064 peeraddr
= &client
->peeraddr
;
3067 result
= dns_resolver_createfetch2(client
->view
->resolver
,
3068 client
->query
.qname
,
3069 qtype
, qdomain
, nameservers
,
3070 NULL
, peeraddr
, client
->message
->id
,
3071 client
->query
.fetchoptions
,
3073 query_resume
, client
,
3074 rdataset
, sigrdataset
,
3075 &client
->query
.fetch
);
3077 if (result
== ISC_R_SUCCESS
) {
3079 * Record that we're waiting for an event. A client which
3080 * is shutting down will not be destroyed until all the
3081 * events have been received.
3084 query_putrdataset(client
, &rdataset
);
3085 if (sigrdataset
!= NULL
)
3086 query_putrdataset(client
, &sigrdataset
);
3092 #define MAX_RESTARTS 16
3094 #define QUERY_ERROR(r) \
3097 want_restart = ISC_FALSE; \
3102 * Extract a network address from the RDATA of an A or AAAA
3107 * ISC_R_NOTIMPLEMENTED The rdata is not a known address type.
3110 rdata_tonetaddr(const dns_rdata_t
*rdata
, isc_netaddr_t
*netaddr
) {
3112 struct in6_addr in6a
;
3114 switch (rdata
->type
) {
3115 case dns_rdatatype_a
:
3116 INSIST(rdata
->length
== 4);
3117 memcpy(&ina
.s_addr
, rdata
->data
, 4);
3118 isc_netaddr_fromin(netaddr
, &ina
);
3119 return (ISC_R_SUCCESS
);
3120 case dns_rdatatype_aaaa
:
3121 INSIST(rdata
->length
== 16);
3122 memcpy(in6a
.s6_addr
, rdata
->data
, 16);
3123 isc_netaddr_fromin6(netaddr
, &in6a
);
3124 return (ISC_R_SUCCESS
);
3126 return (ISC_R_NOTIMPLEMENTED
);
3131 * Find the sort order of 'rdata' in the topology-like
3132 * ACL forming the second element in a 2-element top-level
3133 * sortlist statement.
3136 query_sortlist_order_2element(const dns_rdata_t
*rdata
, const void *arg
) {
3137 isc_netaddr_t netaddr
;
3139 if (rdata_tonetaddr(rdata
, &netaddr
) != ISC_R_SUCCESS
)
3141 return (ns_sortlist_addrorder2(&netaddr
, arg
));
3145 * Find the sort order of 'rdata' in the matching element
3146 * of a 1-element top-level sortlist statement.
3149 query_sortlist_order_1element(const dns_rdata_t
*rdata
, const void *arg
) {
3150 isc_netaddr_t netaddr
;
3152 if (rdata_tonetaddr(rdata
, &netaddr
) != ISC_R_SUCCESS
)
3154 return (ns_sortlist_addrorder1(&netaddr
, arg
));
3158 * Find the sortlist statement that applies to 'client' and set up
3159 * the sortlist info in in client->message appropriately.
3162 setup_query_sortlist(ns_client_t
*client
) {
3163 isc_netaddr_t netaddr
;
3164 dns_rdatasetorderfunc_t order
= NULL
;
3165 const void *order_arg
= NULL
;
3167 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
3168 switch (ns_sortlist_setup(client
->view
->sortlist
,
3169 &netaddr
, &order_arg
)) {
3170 case NS_SORTLISTTYPE_1ELEMENT
:
3171 order
= query_sortlist_order_1element
;
3173 case NS_SORTLISTTYPE_2ELEMENT
:
3174 order
= query_sortlist_order_2element
;
3176 case NS_SORTLISTTYPE_NONE
:
3183 dns_message_setsortorder(client
->message
, order
, order_arg
);
3187 query_addnoqnameproof(ns_client_t
*client
, dns_rdataset_t
*rdataset
) {
3188 isc_buffer_t
*dbuf
, b
;
3190 dns_rdataset_t
*nsec
, *nsecsig
;
3191 isc_result_t result
= ISC_R_NOMEMORY
;
3193 CTRACE("query_addnoqnameproof");
3199 dbuf
= query_getnamebuf(client
);
3202 fname
= query_newname(client
, dbuf
, &b
);
3203 nsec
= query_newrdataset(client
);
3204 nsecsig
= query_newrdataset(client
);
3205 if (fname
== NULL
|| nsec
== NULL
|| nsecsig
== NULL
)
3208 result
= dns_rdataset_getnoqname(rdataset
, fname
, nsec
, nsecsig
);
3209 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3211 query_addrrset(client
, &fname
, &nsec
, &nsecsig
, dbuf
,
3212 DNS_SECTION_AUTHORITY
);
3216 query_putrdataset(client
, &nsec
);
3217 if (nsecsig
!= NULL
)
3218 query_putrdataset(client
, &nsecsig
);
3220 query_releasename(client
, &fname
);
3224 answer_in_glue(ns_client_t
*client
, dns_rdatatype_t qtype
) {
3227 dns_section_t section
= DNS_SECTION_ADDITIONAL
;
3228 dns_rdataset_t
*rdataset
= NULL
;
3230 msg
= client
->message
;
3231 for (name
= ISC_LIST_HEAD(msg
->sections
[section
]);
3233 name
= ISC_LIST_NEXT(name
, link
))
3234 if (dns_name_equal(name
, client
->query
.qname
)) {
3235 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3237 rdataset
= ISC_LIST_NEXT(rdataset
, link
))
3238 if (rdataset
->type
== qtype
)
3242 if (rdataset
!= NULL
) {
3243 ISC_LIST_UNLINK(msg
->sections
[section
], name
, link
);
3244 ISC_LIST_PREPEND(msg
->sections
[section
], name
, link
);
3245 ISC_LIST_UNLINK(name
->list
, rdataset
, link
);
3246 ISC_LIST_PREPEND(name
->list
, rdataset
, link
);
3247 rdataset
->attributes
|= DNS_RDATASETATTR_REQUIREDGLUE
;
3251 #define NS_NAME_INIT(A,B) \
3254 A, sizeof(A), sizeof(B), \
3255 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
3256 B, NULL, { (void *)-1, (void *)-1}, \
3260 static unsigned char inaddr10_offsets
[] = { 0, 3, 11, 16 };
3261 static unsigned char inaddr172_offsets
[] = { 0, 3, 7, 15, 20 };
3262 static unsigned char inaddr192_offsets
[] = { 0, 4, 8, 16, 21 };
3264 static unsigned char inaddr10
[] = "\00210\007IN-ADDR\004ARPA";
3266 static unsigned char inaddr16172
[] = "\00216\003172\007IN-ADDR\004ARPA";
3267 static unsigned char inaddr17172
[] = "\00217\003172\007IN-ADDR\004ARPA";
3268 static unsigned char inaddr18172
[] = "\00218\003172\007IN-ADDR\004ARPA";
3269 static unsigned char inaddr19172
[] = "\00219\003172\007IN-ADDR\004ARPA";
3270 static unsigned char inaddr20172
[] = "\00220\003172\007IN-ADDR\004ARPA";
3271 static unsigned char inaddr21172
[] = "\00221\003172\007IN-ADDR\004ARPA";
3272 static unsigned char inaddr22172
[] = "\00222\003172\007IN-ADDR\004ARPA";
3273 static unsigned char inaddr23172
[] = "\00223\003172\007IN-ADDR\004ARPA";
3274 static unsigned char inaddr24172
[] = "\00224\003172\007IN-ADDR\004ARPA";
3275 static unsigned char inaddr25172
[] = "\00225\003172\007IN-ADDR\004ARPA";
3276 static unsigned char inaddr26172
[] = "\00226\003172\007IN-ADDR\004ARPA";
3277 static unsigned char inaddr27172
[] = "\00227\003172\007IN-ADDR\004ARPA";
3278 static unsigned char inaddr28172
[] = "\00228\003172\007IN-ADDR\004ARPA";
3279 static unsigned char inaddr29172
[] = "\00229\003172\007IN-ADDR\004ARPA";
3280 static unsigned char inaddr30172
[] = "\00230\003172\007IN-ADDR\004ARPA";
3281 static unsigned char inaddr31172
[] = "\00231\003172\007IN-ADDR\004ARPA";
3283 static unsigned char inaddr168192
[] = "\003168\003192\007IN-ADDR\004ARPA";
3285 static dns_name_t rfc1918names
[] = {
3286 NS_NAME_INIT(inaddr10
, inaddr10_offsets
),
3287 NS_NAME_INIT(inaddr16172
, inaddr172_offsets
),
3288 NS_NAME_INIT(inaddr17172
, inaddr172_offsets
),
3289 NS_NAME_INIT(inaddr18172
, inaddr172_offsets
),
3290 NS_NAME_INIT(inaddr19172
, inaddr172_offsets
),
3291 NS_NAME_INIT(inaddr20172
, inaddr172_offsets
),
3292 NS_NAME_INIT(inaddr21172
, inaddr172_offsets
),
3293 NS_NAME_INIT(inaddr22172
, inaddr172_offsets
),
3294 NS_NAME_INIT(inaddr23172
, inaddr172_offsets
),
3295 NS_NAME_INIT(inaddr24172
, inaddr172_offsets
),
3296 NS_NAME_INIT(inaddr25172
, inaddr172_offsets
),
3297 NS_NAME_INIT(inaddr26172
, inaddr172_offsets
),
3298 NS_NAME_INIT(inaddr27172
, inaddr172_offsets
),
3299 NS_NAME_INIT(inaddr28172
, inaddr172_offsets
),
3300 NS_NAME_INIT(inaddr29172
, inaddr172_offsets
),
3301 NS_NAME_INIT(inaddr30172
, inaddr172_offsets
),
3302 NS_NAME_INIT(inaddr31172
, inaddr172_offsets
),
3303 NS_NAME_INIT(inaddr168192
, inaddr192_offsets
)
3307 static unsigned char prisoner_data
[] = "\010prisoner\004iana\003org";
3308 static unsigned char hostmaster_data
[] = "\012hostmaster\014root-servers\003org";
3310 static unsigned char prisoner_offsets
[] = { 0, 9, 14, 18 };
3311 static unsigned char hostmaster_offsets
[] = { 0, 11, 24, 28 };
3313 static dns_name_t prisoner
= NS_NAME_INIT(prisoner_data
, prisoner_offsets
);
3314 static dns_name_t hostmaster
= NS_NAME_INIT(hostmaster_data
, hostmaster_offsets
);
3317 warn_rfc1918(ns_client_t
*client
, dns_name_t
*fname
, dns_rdataset_t
*rdataset
) {
3319 dns_rdata_t rdata
= DNS_RDATA_INIT
;
3320 dns_rdata_soa_t soa
;
3321 dns_rdataset_t found
;
3322 isc_result_t result
;
3324 for (i
= 0; i
< (sizeof(rfc1918names
)/sizeof(*rfc1918names
)); i
++) {
3325 if (dns_name_issubdomain(fname
, &rfc1918names
[i
])) {
3326 dns_rdataset_init(&found
);
3327 result
= dns_ncache_getrdataset(rdataset
,
3331 if (result
!= ISC_R_SUCCESS
)
3334 result
= dns_rdataset_first(&found
);
3335 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3336 dns_rdataset_current(&found
, &rdata
);
3337 result
= dns_rdata_tostruct(&rdata
, &soa
, NULL
);
3338 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3339 if (dns_name_equal(&soa
.origin
, &prisoner
) &&
3340 dns_name_equal(&soa
.contact
, &hostmaster
)) {
3341 char buf
[DNS_NAME_FORMATSIZE
];
3342 dns_name_format(fname
, buf
, sizeof(buf
));
3343 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
3346 "RFC 1918 response from "
3347 "Internet for %s", buf
);
3349 dns_rdataset_disassociate(&found
);
3356 * Do the bulk of query processing for the current query of 'client'.
3357 * If 'event' is non-NULL, we are returning from recursion and 'qtype'
3358 * is ignored. Otherwise, 'qtype' is the query type.
3361 query_find(ns_client_t
*client
, dns_fetchevent_t
*event
, dns_rdatatype_t qtype
)
3365 dns_rdatatype_t type
;
3366 dns_name_t
*fname
, *zfname
, *tname
, *prefix
;
3367 dns_rdataset_t
*rdataset
, *trdataset
;
3368 dns_rdataset_t
*sigrdataset
, *zrdataset
, *zsigrdataset
;
3369 dns_rdataset_t
**sigrdatasetp
;
3370 dns_rdata_t rdata
= DNS_RDATA_INIT
;
3371 dns_rdatasetiter_t
*rdsiter
;
3372 isc_boolean_t want_restart
, authoritative
, is_zone
, need_wildcardproof
;
3373 unsigned int n
, nlabels
;
3374 dns_namereln_t namereln
;
3378 isc_result_t result
, eresult
;
3379 dns_fixedname_t fixed
;
3380 dns_fixedname_t wildcardname
;
3381 dns_dbversion_t
*version
;
3383 dns_rdata_cname_t cname
;
3384 dns_rdata_dname_t dname
;
3385 unsigned int options
;
3386 isc_boolean_t empty_wild
;
3387 dns_rdataset_t
*noqname
;
3388 isc_boolean_t resuming
;
3391 CTRACE("query_find");
3394 * One-time initialization.
3396 * It's especially important to initialize anything that the cleanup
3397 * code might cleanup.
3400 eresult
= ISC_R_SUCCESS
;
3406 zsigrdataset
= NULL
;
3412 need_wildcardproof
= ISC_FALSE
;
3413 empty_wild
= ISC_FALSE
;
3415 resuming
= ISC_FALSE
;
3416 is_zone
= ISC_FALSE
;
3418 if (event
!= NULL
) {
3420 * We're returning from recursion. Restore the query context
3424 want_restart
= ISC_FALSE
;
3425 authoritative
= ISC_FALSE
;
3427 qtype
= event
->qtype
;
3428 if (qtype
== dns_rdatatype_rrsig
|| qtype
== dns_rdatatype_sig
)
3429 type
= dns_rdatatype_any
;
3434 rdataset
= event
->rdataset
;
3435 sigrdataset
= event
->sigrdataset
;
3438 * We'll need some resources...
3440 dbuf
= query_getnamebuf(client
);
3442 QUERY_ERROR(DNS_R_SERVFAIL
);
3445 fname
= query_newname(client
, dbuf
, &b
);
3446 if (fname
== NULL
) {
3447 QUERY_ERROR(DNS_R_SERVFAIL
);
3450 tname
= dns_fixedname_name(&event
->foundname
);
3451 result
= dns_name_copy(tname
, fname
, NULL
);
3452 if (result
!= ISC_R_SUCCESS
) {
3453 QUERY_ERROR(DNS_R_SERVFAIL
);
3457 result
= event
->result
;
3458 resuming
= ISC_TRUE
;
3464 * Not returning from recursion.
3468 * If it's a SIG query, we'll iterate the node.
3470 if (qtype
== dns_rdatatype_rrsig
|| qtype
== dns_rdatatype_sig
)
3471 type
= dns_rdatatype_any
;
3476 CTRACE("query_find: restart");
3477 want_restart
= ISC_FALSE
;
3478 authoritative
= ISC_FALSE
;
3480 need_wildcardproof
= ISC_FALSE
;
3482 if (client
->view
->checknames
&&
3483 !dns_rdata_checkowner(client
->query
.qname
,
3484 client
->message
->rdclass
,
3485 qtype
, ISC_FALSE
)) {
3486 char namebuf
[DNS_NAME_FORMATSIZE
];
3487 char typename
[DNS_RDATATYPE_FORMATSIZE
];
3488 char classname
[DNS_RDATACLASS_FORMATSIZE
];
3490 dns_name_format(client
->query
.qname
, namebuf
, sizeof(namebuf
));
3491 dns_rdatatype_format(qtype
, typename
, sizeof(typename
));
3492 dns_rdataclass_format(client
->message
->rdclass
, classname
,
3494 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
3495 NS_LOGMODULE_QUERY
, ISC_LOG_ERROR
,
3496 "check-names failure %s/%s/%s", namebuf
,
3497 typename
, classname
);
3498 QUERY_ERROR(DNS_R_REFUSED
);
3503 * First we must find the right database.
3505 options
&= DNS_GETDB_NOLOG
; /* Preserve DNS_GETDB_NOLOG. */
3506 if (dns_rdatatype_atparent(qtype
) &&
3507 !dns_name_equal(client
->query
.qname
, dns_rootname
))
3508 options
|= DNS_GETDB_NOEXACT
;
3509 result
= query_getdb(client
, client
->query
.qname
, qtype
, options
,
3510 &zone
, &db
, &version
, &is_zone
);
3511 if ((result
!= ISC_R_SUCCESS
|| !is_zone
) && !RECURSIONOK(client
) &&
3512 (options
& DNS_GETDB_NOEXACT
) != 0 && qtype
== dns_rdatatype_ds
) {
3514 * Look to see if we are authoritative for the
3515 * child zone if the query type is DS.
3517 dns_db_t
*tdb
= NULL
;
3518 dns_zone_t
*tzone
= NULL
;
3519 dns_dbversion_t
*tversion
= NULL
;
3520 isc_result_t tresult
;
3522 tresult
= query_getzonedb(client
, client
->query
.qname
, qtype
,
3523 DNS_GETDB_PARTIAL
, &tzone
, &tdb
,
3525 if (tresult
== ISC_R_SUCCESS
) {
3526 options
&= ~DNS_GETDB_NOEXACT
;
3527 query_putrdataset(client
, &rdataset
);
3531 dns_zone_detach(&zone
);
3536 result
= ISC_R_SUCCESS
;
3539 dns_db_detach(&tdb
);
3541 dns_zone_detach(&tzone
);
3544 if (result
!= ISC_R_SUCCESS
) {
3545 if (result
== DNS_R_REFUSED
) {
3546 if (WANTRECURSION(client
)) {
3548 dns_nsstatscounter_recurserej
);
3550 inc_stats(client
, dns_nsstatscounter_authrej
);
3551 if (!PARTIALANSWER(client
))
3552 QUERY_ERROR(DNS_R_REFUSED
);
3554 QUERY_ERROR(DNS_R_SERVFAIL
);
3559 authoritative
= ISC_TRUE
;
3561 if (event
== NULL
&& client
->query
.restarts
== 0) {
3566 * if is_zone = true, zone = NULL then this is
3567 * a DLZ zone. Don't attempt to attach zone.
3570 dns_zone_attach(zone
, &client
->query
.authzone
);
3574 dns_db_attach(db
, &client
->query
.authdb
);
3576 client
->query
.authdbset
= ISC_TRUE
;
3580 CTRACE("query_find: db_find");
3582 * We'll need some resources...
3584 dbuf
= query_getnamebuf(client
);
3586 QUERY_ERROR(DNS_R_SERVFAIL
);
3589 fname
= query_newname(client
, dbuf
, &b
);
3590 rdataset
= query_newrdataset(client
);
3591 if (fname
== NULL
|| rdataset
== NULL
) {
3592 QUERY_ERROR(DNS_R_SERVFAIL
);
3595 if (WANTDNSSEC(client
)) {
3596 sigrdataset
= query_newrdataset(client
);
3597 if (sigrdataset
== NULL
) {
3598 QUERY_ERROR(DNS_R_SERVFAIL
);
3604 * Now look for an answer in the database.
3606 result
= dns_db_find(db
, client
->query
.qname
, version
, type
,
3607 client
->query
.dboptions
, client
->now
,
3608 &node
, fname
, rdataset
, sigrdataset
);
3611 CTRACE("query_find: resume");
3615 * This case is handled in the main line below.
3621 * These cases are handled in the main line below.
3624 authoritative
= ISC_FALSE
;
3626 case ISC_R_NOTFOUND
:
3628 * The cache doesn't even have the root NS. Get them from
3635 if (client
->view
->hints
== NULL
) {
3636 /* We have no hints. */
3637 result
= ISC_R_FAILURE
;
3639 dns_db_attach(client
->view
->hints
, &db
);
3640 result
= dns_db_find(db
, dns_rootname
,
3641 NULL
, dns_rdatatype_ns
,
3642 0, client
->now
, &node
, fname
,
3643 rdataset
, sigrdataset
);
3645 if (result
!= ISC_R_SUCCESS
) {
3647 * Nonsensical root hints may require cleanup.
3649 if (dns_rdataset_isassociated(rdataset
))
3650 dns_rdataset_disassociate(rdataset
);
3651 if (sigrdataset
!= NULL
&&
3652 dns_rdataset_isassociated(sigrdataset
))
3653 dns_rdataset_disassociate(sigrdataset
);
3655 dns_db_detachnode(db
, &node
);
3658 * We don't have any root server hints, but
3659 * we may have working forwarders, so try to
3662 if (RECURSIONOK(client
)) {
3663 result
= query_recurse(client
, qtype
,
3664 NULL
, NULL
, resuming
);
3665 if (result
== ISC_R_SUCCESS
)
3666 client
->query
.attributes
|=
3667 NS_QUERYATTR_RECURSING
;
3668 else if (result
== DNS_R_DUPLICATE
||
3669 result
== DNS_R_DROP
) {
3670 /* Duplicate query. */
3671 QUERY_ERROR(result
);
3673 /* Unable to recurse. */
3674 QUERY_ERROR(DNS_R_SERVFAIL
);
3678 /* Unable to give root server referral. */
3679 QUERY_ERROR(DNS_R_SERVFAIL
);
3684 * XXXRTH We should trigger root server priming here.
3687 case DNS_R_DELEGATION
:
3688 authoritative
= ISC_FALSE
;
3691 * Look to see if we are authoritative for the
3692 * child zone if the query type is DS.
3694 if (!RECURSIONOK(client
) &&
3695 (options
& DNS_GETDB_NOEXACT
) != 0 &&
3696 qtype
== dns_rdatatype_ds
) {
3697 dns_db_t
*tdb
= NULL
;
3698 dns_zone_t
*tzone
= NULL
;
3699 dns_dbversion_t
*tversion
= NULL
;
3700 result
= query_getzonedb(client
,
3701 client
->query
.qname
,
3706 if (result
== ISC_R_SUCCESS
) {
3707 options
&= ~DNS_GETDB_NOEXACT
;
3708 query_putrdataset(client
, &rdataset
);
3709 if (sigrdataset
!= NULL
)
3710 query_putrdataset(client
,
3713 query_releasename(client
,
3716 dns_db_detachnode(db
, &node
);
3720 dns_zone_detach(&zone
);
3724 authoritative
= ISC_TRUE
;
3728 dns_db_detach(&tdb
);
3730 dns_zone_detach(&tzone
);
3733 * We're authoritative for an ancestor of QNAME.
3735 if (!USECACHE(client
) || !RECURSIONOK(client
)) {
3737 * If we don't have a cache, this is the best
3740 * If the client is making a nonrecursive
3741 * query we always give out the authoritative
3742 * delegation. This way even if we get
3743 * junk in our cache, we won't fail in our
3744 * role as the delegating authority if another
3745 * nameserver asks us about a delegated
3748 * We enable the retrieval of glue for this
3749 * database by setting client->query.gluedb.
3751 client
->query
.gluedb
= db
;
3752 client
->query
.isreferral
= ISC_TRUE
;
3754 * We must ensure NOADDITIONAL is off,
3755 * because the generation of
3756 * additional data is required in
3759 client
->query
.attributes
&=
3760 ~NS_QUERYATTR_NOADDITIONAL
;
3761 if (sigrdataset
!= NULL
)
3762 sigrdatasetp
= &sigrdataset
;
3764 sigrdatasetp
= NULL
;
3765 query_addrrset(client
, &fname
,
3766 &rdataset
, sigrdatasetp
,
3767 dbuf
, DNS_SECTION_AUTHORITY
);
3768 client
->query
.gluedb
= NULL
;
3769 if (WANTDNSSEC(client
) && dns_db_issecure(db
))
3770 query_addds(client
, db
, node
, version
);
3773 * We might have a better answer or delegation
3774 * in the cache. We'll remember the current
3775 * values of fname, rdataset, and sigrdataset.
3776 * We'll then go looking for QNAME in the
3777 * cache. If we find something better, we'll
3780 query_keepname(client
, fname
, dbuf
);
3784 zrdataset
= rdataset
;
3786 zsigrdataset
= sigrdataset
;
3788 dns_db_detachnode(db
, &node
);
3791 dns_db_attach(client
->view
->cachedb
, &db
);
3792 is_zone
= ISC_FALSE
;
3796 if (zfname
!= NULL
&&
3797 !dns_name_issubdomain(fname
, zfname
)) {
3799 * We've already got a delegation from
3800 * authoritative data, and it is better
3801 * than what we found in the cache. Use
3802 * it instead of the cache delegation.
3804 query_releasename(client
, &fname
);
3808 * We've already done query_keepname() on
3809 * zfname, so we must set dbuf to NULL to
3810 * prevent query_addrrset() from trying to
3811 * call query_keepname() again.
3814 query_putrdataset(client
, &rdataset
);
3815 if (sigrdataset
!= NULL
)
3816 query_putrdataset(client
,
3818 rdataset
= zrdataset
;
3820 sigrdataset
= zsigrdataset
;
3821 zsigrdataset
= NULL
;
3823 * We don't clean up zdb here because we
3824 * may still need it. It will get cleaned
3825 * up by the main cleanup code.
3829 if (RECURSIONOK(client
)) {
3833 if (dns_rdatatype_atparent(type
))
3834 result
= query_recurse(client
, qtype
,
3838 result
= query_recurse(client
, qtype
,
3841 if (result
== ISC_R_SUCCESS
)
3842 client
->query
.attributes
|=
3843 NS_QUERYATTR_RECURSING
;
3844 else if (result
== DNS_R_DUPLICATE
||
3845 result
== DNS_R_DROP
)
3846 QUERY_ERROR(result
);
3848 QUERY_ERROR(DNS_R_SERVFAIL
);
3851 * This is the best answer.
3853 client
->query
.attributes
|=
3854 NS_QUERYATTR_CACHEGLUEOK
;
3855 client
->query
.gluedb
= zdb
;
3856 client
->query
.isreferral
= ISC_TRUE
;
3858 * We must ensure NOADDITIONAL is off,
3859 * because the generation of
3860 * additional data is required in
3863 client
->query
.attributes
&=
3864 ~NS_QUERYATTR_NOADDITIONAL
;
3865 if (sigrdataset
!= NULL
)
3866 sigrdatasetp
= &sigrdataset
;
3868 sigrdatasetp
= NULL
;
3869 query_addrrset(client
, &fname
,
3870 &rdataset
, sigrdatasetp
,
3871 dbuf
, DNS_SECTION_AUTHORITY
);
3872 client
->query
.gluedb
= NULL
;
3873 client
->query
.attributes
&=
3874 ~NS_QUERYATTR_CACHEGLUEOK
;
3875 if (WANTDNSSEC(client
))
3876 query_addds(client
, db
, node
, version
);
3880 case DNS_R_EMPTYNAME
:
3881 result
= DNS_R_NXRRSET
;
3885 if (dns_rdataset_isassociated(rdataset
)) {
3887 * If we've got a NSEC record, we need to save the
3888 * name now because we're going call query_addsoa()
3889 * below, and it needs to use the name buffer.
3891 query_keepname(client
, fname
, dbuf
);
3894 * We're not going to use fname, and need to release
3895 * our hold on the name buffer so query_addsoa()
3898 query_releasename(client
, &fname
);
3903 result
= query_addsoa(client
, db
, version
, ISC_FALSE
);
3904 if (result
!= ISC_R_SUCCESS
) {
3905 QUERY_ERROR(result
);
3909 * Add NSEC record if we found one.
3911 if (WANTDNSSEC(client
)) {
3912 if (dns_rdataset_isassociated(rdataset
))
3913 query_addnxrrsetnsec(client
, db
, version
,
3918 case DNS_R_EMPTYWILD
:
3919 empty_wild
= ISC_TRUE
;
3921 case DNS_R_NXDOMAIN
:
3923 if (dns_rdataset_isassociated(rdataset
)) {
3925 * If we've got a NSEC record, we need to save the
3926 * name now because we're going call query_addsoa()
3927 * below, and it needs to use the name buffer.
3929 query_keepname(client
, fname
, dbuf
);
3932 * We're not going to use fname, and need to release
3933 * our hold on the name buffer so query_addsoa()
3936 query_releasename(client
, &fname
);
3939 * Add SOA. If the query was for a SOA record force the
3940 * ttl to zero so that it is possible for clients to find
3941 * the containing zone of an arbitrary name with a stub
3942 * resolver and not have it cached.
3944 if (qtype
== dns_rdatatype_soa
&&
3948 dns_zone_getzeronosoattl(zone
))
3949 result
= query_addsoa(client
, db
, version
, ISC_TRUE
);
3951 result
= query_addsoa(client
, db
, version
, ISC_FALSE
);
3952 if (result
!= ISC_R_SUCCESS
) {
3953 QUERY_ERROR(result
);
3957 * Add NSEC record if we found one.
3959 if (dns_rdataset_isassociated(rdataset
)) {
3960 if (WANTDNSSEC(client
)) {
3961 query_addrrset(client
, &fname
, &rdataset
,
3963 NULL
, DNS_SECTION_AUTHORITY
);
3964 query_addwildcardproof(client
, db
, version
,
3965 client
->query
.qname
,
3970 * Set message rcode.
3973 client
->message
->rcode
= dns_rcode_noerror
;
3975 client
->message
->rcode
= dns_rcode_nxdomain
;
3977 case DNS_R_NCACHENXDOMAIN
:
3978 case DNS_R_NCACHENXRRSET
:
3980 authoritative
= ISC_FALSE
;
3982 * Set message rcode, if required.
3984 if (result
== DNS_R_NCACHENXDOMAIN
)
3985 client
->message
->rcode
= dns_rcode_nxdomain
;
3987 * Look for RFC 1918 leakage from Internet.
3989 if (result
== DNS_R_NCACHENXDOMAIN
&&
3990 qtype
== dns_rdatatype_ptr
&&
3991 client
->message
->rdclass
== dns_rdataclass_in
&&
3992 dns_name_countlabels(fname
) == 7)
3993 warn_rfc1918(client
, fname
, rdataset
);
3995 * We don't call query_addrrset() because we don't need any
3996 * of its extra features (and things would probably break!).
3998 query_keepname(client
, fname
, dbuf
);
3999 dns_message_addname(client
->message
, fname
,
4000 DNS_SECTION_AUTHORITY
);
4001 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
4007 * Keep a copy of the rdataset. We have to do this because
4008 * query_addrrset may clear 'rdataset' (to prevent the
4009 * cleanup code from cleaning it up).
4011 trdataset
= rdataset
;
4013 * Add the CNAME to the answer section.
4015 if (sigrdataset
!= NULL
)
4016 sigrdatasetp
= &sigrdataset
;
4018 sigrdatasetp
= NULL
;
4019 if (WANTDNSSEC(client
) &&
4020 (fname
->attributes
& DNS_NAMEATTR_WILDCARD
) != 0)
4022 dns_fixedname_init(&wildcardname
);
4023 dns_name_copy(fname
, dns_fixedname_name(&wildcardname
),
4025 need_wildcardproof
= ISC_TRUE
;
4027 if ((rdataset
->attributes
& DNS_RDATASETATTR_NOQNAME
) != 0 &&
4032 query_addrrset(client
, &fname
, &rdataset
, sigrdatasetp
, dbuf
,
4033 DNS_SECTION_ANSWER
);
4034 if (noqname
!= NULL
)
4035 query_addnoqnameproof(client
, noqname
);
4037 * We set the PARTIALANSWER attribute so that if anything goes
4038 * wrong later on, we'll return what we've got so far.
4040 client
->query
.attributes
|= NS_QUERYATTR_PARTIALANSWER
;
4042 * Reset qname to be the target name of the CNAME and restart
4046 result
= dns_message_gettempname(client
->message
, &tname
);
4047 if (result
!= ISC_R_SUCCESS
)
4049 result
= dns_rdataset_first(trdataset
);
4050 if (result
!= ISC_R_SUCCESS
) {
4051 dns_message_puttempname(client
->message
, &tname
);
4054 dns_rdataset_current(trdataset
, &rdata
);
4055 result
= dns_rdata_tostruct(&rdata
, &cname
, NULL
);
4056 dns_rdata_reset(&rdata
);
4057 if (result
!= ISC_R_SUCCESS
) {
4058 dns_message_puttempname(client
->message
, &tname
);
4061 dns_name_init(tname
, NULL
);
4062 result
= dns_name_dup(&cname
.cname
, client
->mctx
, tname
);
4063 if (result
!= ISC_R_SUCCESS
) {
4064 dns_message_puttempname(client
->message
, &tname
);
4065 dns_rdata_freestruct(&cname
);
4068 dns_rdata_freestruct(&cname
);
4069 ns_client_qnamereplace(client
, tname
);
4070 want_restart
= ISC_TRUE
;
4071 if (!WANTRECURSION(client
))
4072 options
|= DNS_GETDB_NOLOG
;
4076 * Compare the current qname to the found name. We need
4077 * to know how many labels and bits are in common because
4078 * we're going to have to split qname later on.
4080 namereln
= dns_name_fullcompare(client
->query
.qname
, fname
,
4082 INSIST(namereln
== dns_namereln_subdomain
);
4084 * Keep a copy of the rdataset. We have to do this because
4085 * query_addrrset may clear 'rdataset' (to prevent the
4086 * cleanup code from cleaning it up).
4088 trdataset
= rdataset
;
4090 * Add the DNAME to the answer section.
4092 if (sigrdataset
!= NULL
)
4093 sigrdatasetp
= &sigrdataset
;
4095 sigrdatasetp
= NULL
;
4096 if (WANTDNSSEC(client
) &&
4097 (fname
->attributes
& DNS_NAMEATTR_WILDCARD
) != 0)
4099 dns_fixedname_init(&wildcardname
);
4100 dns_name_copy(fname
, dns_fixedname_name(&wildcardname
),
4102 need_wildcardproof
= ISC_TRUE
;
4104 query_addrrset(client
, &fname
, &rdataset
, sigrdatasetp
, dbuf
,
4105 DNS_SECTION_ANSWER
);
4107 * We set the PARTIALANSWER attribute so that if anything goes
4108 * wrong later on, we'll return what we've got so far.
4110 client
->query
.attributes
|= NS_QUERYATTR_PARTIALANSWER
;
4112 * Get the target name of the DNAME.
4115 result
= dns_message_gettempname(client
->message
, &tname
);
4116 if (result
!= ISC_R_SUCCESS
)
4118 result
= dns_rdataset_first(trdataset
);
4119 if (result
!= ISC_R_SUCCESS
) {
4120 dns_message_puttempname(client
->message
, &tname
);
4123 dns_rdataset_current(trdataset
, &rdata
);
4124 result
= dns_rdata_tostruct(&rdata
, &dname
, NULL
);
4125 dns_rdata_reset(&rdata
);
4126 if (result
!= ISC_R_SUCCESS
) {
4127 dns_message_puttempname(client
->message
, &tname
);
4130 dns_name_init(tname
, NULL
);
4131 dns_name_clone(&dname
.dname
, tname
);
4132 dns_rdata_freestruct(&dname
);
4134 * Construct the new qname.
4136 dns_fixedname_init(&fixed
);
4137 prefix
= dns_fixedname_name(&fixed
);
4138 dns_name_split(client
->query
.qname
, nlabels
, prefix
, NULL
);
4139 INSIST(fname
== NULL
);
4140 dbuf
= query_getnamebuf(client
);
4142 dns_message_puttempname(client
->message
, &tname
);
4145 fname
= query_newname(client
, dbuf
, &b
);
4146 if (fname
== NULL
) {
4147 dns_message_puttempname(client
->message
, &tname
);
4150 result
= dns_name_concatenate(prefix
, tname
, fname
, NULL
);
4151 if (result
!= ISC_R_SUCCESS
) {
4152 dns_message_puttempname(client
->message
, &tname
);
4153 if (result
== ISC_R_NOSPACE
) {
4155 * RFC2672, section 4.1, subsection 3c says
4156 * we should return YXDOMAIN if the constructed
4157 * name would be too long.
4159 client
->message
->rcode
= dns_rcode_yxdomain
;
4163 query_keepname(client
, fname
, dbuf
);
4165 * Synthesize a CNAME for this DNAME.
4167 * We want to synthesize a CNAME since if we don't
4168 * then older software that doesn't understand DNAME
4169 * will not chain like it should.
4171 * We do not try to synthesize a signature because we hope
4172 * that security aware servers will understand DNAME. Also,
4173 * even if we had an online key, making a signature
4174 * on-the-fly is costly, and not really legitimate anyway
4175 * since the synthesized CNAME is NOT in the zone.
4177 dns_name_init(tname
, NULL
);
4178 (void)query_addcnamelike(client
, client
->query
.qname
, fname
,
4179 trdataset
->trust
, &tname
,
4180 dns_rdatatype_cname
);
4182 dns_message_puttempname(client
->message
, &tname
);
4184 * Switch to the new qname and restart.
4186 ns_client_qnamereplace(client
, fname
);
4188 want_restart
= ISC_TRUE
;
4189 if (!WANTRECURSION(client
))
4190 options
|= DNS_GETDB_NOLOG
;
4194 * Something has gone wrong.
4196 QUERY_ERROR(DNS_R_SERVFAIL
);
4200 if (WANTDNSSEC(client
) &&
4201 (fname
->attributes
& DNS_NAMEATTR_WILDCARD
) != 0)
4203 dns_fixedname_init(&wildcardname
);
4204 dns_name_copy(fname
, dns_fixedname_name(&wildcardname
), NULL
);
4205 need_wildcardproof
= ISC_TRUE
;
4208 if (type
== dns_rdatatype_any
) {
4210 * XXXRTH Need to handle zonecuts with special case
4215 result
= dns_db_allrdatasets(db
, node
, version
, 0, &rdsiter
);
4216 if (result
!= ISC_R_SUCCESS
) {
4217 QUERY_ERROR(DNS_R_SERVFAIL
);
4221 * Calling query_addrrset() with a non-NULL dbuf is going
4222 * to either keep or release the name. We don't want it to
4223 * release fname, since we may have to call query_addrrset()
4224 * more than once. That means we have to call query_keepname()
4225 * now, and pass a NULL dbuf to query_addrrset().
4227 * If we do a query_addrrset() below, we must set fname to
4228 * NULL before leaving this block, otherwise we might try to
4229 * cleanup fname even though we're using it!
4231 query_keepname(client
, fname
, dbuf
);
4233 result
= dns_rdatasetiter_first(rdsiter
);
4234 while (result
== ISC_R_SUCCESS
) {
4235 dns_rdatasetiter_current(rdsiter
, rdataset
);
4236 if ((qtype
== dns_rdatatype_any
||
4237 rdataset
->type
== qtype
) && rdataset
->type
!= 0) {
4238 query_addrrset(client
,
4239 fname
!= NULL
? &fname
: &tname
,
4241 NULL
, DNS_SECTION_ANSWER
);
4243 INSIST(tname
!= NULL
);
4245 * rdataset is non-NULL only in certain pathological
4246 * cases involving DNAMEs.
4248 if (rdataset
!= NULL
)
4249 query_putrdataset(client
, &rdataset
);
4250 rdataset
= query_newrdataset(client
);
4251 if (rdataset
== NULL
)
4255 * We're not interested in this rdataset.
4257 dns_rdataset_disassociate(rdataset
);
4259 result
= dns_rdatasetiter_next(rdsiter
);
4263 dns_message_puttempname(client
->message
, &fname
);
4267 * We didn't match any rdatasets.
4269 if (qtype
== dns_rdatatype_rrsig
&&
4270 result
== ISC_R_NOMORE
) {
4272 * XXXRTH If this is a secure zone and we
4273 * didn't find any SIGs, we should generate
4274 * an error unless we were searching for
4278 authoritative
= ISC_FALSE
;
4279 dns_rdatasetiter_destroy(&rdsiter
);
4280 if (RECURSIONOK(client
)) {
4281 result
= query_recurse(client
,
4286 if (result
== ISC_R_SUCCESS
)
4287 client
->query
.attributes
|=
4288 NS_QUERYATTR_RECURSING
;
4290 QUERY_ERROR(DNS_R_SERVFAIL
); }
4294 * We were searching for SIG records in
4295 * a nonsecure zone. Send a "no error,
4296 * no data" response.
4301 result
= query_addsoa(client
, db
, version
,
4303 if (result
== ISC_R_SUCCESS
)
4304 result
= ISC_R_NOMORE
;
4307 * Something went wrong.
4309 result
= DNS_R_SERVFAIL
;
4312 dns_rdatasetiter_destroy(&rdsiter
);
4313 if (result
!= ISC_R_NOMORE
) {
4314 QUERY_ERROR(DNS_R_SERVFAIL
);
4319 * This is the "normal" case -- an ordinary question to which
4320 * we know the answer.
4322 if (sigrdataset
!= NULL
)
4323 sigrdatasetp
= &sigrdataset
;
4325 sigrdatasetp
= NULL
;
4326 if ((rdataset
->attributes
& DNS_RDATASETATTR_NOQNAME
) != 0 &&
4332 * BIND 8 priming queries need the additional section.
4334 if (is_zone
&& qtype
== dns_rdatatype_ns
&&
4335 dns_name_equal(client
->query
.qname
, dns_rootname
))
4336 client
->query
.attributes
&= ~NS_QUERYATTR_NOADDITIONAL
;
4338 query_addrrset(client
, &fname
, &rdataset
, sigrdatasetp
, dbuf
,
4339 DNS_SECTION_ANSWER
);
4340 if (noqname
!= NULL
)
4341 query_addnoqnameproof(client
, noqname
);
4343 * We shouldn't ever fail to add 'rdataset'
4344 * because it's already in the answer.
4346 INSIST(rdataset
== NULL
);
4350 CTRACE("query_find: addauth");
4352 * Add NS records to the authority section (if we haven't already
4353 * added them to the answer section).
4355 if (!want_restart
&& !NOAUTHORITY(client
)) {
4357 if (!((qtype
== dns_rdatatype_ns
||
4358 qtype
== dns_rdatatype_any
) &&
4359 dns_name_equal(client
->query
.qname
,
4360 dns_db_origin(db
))))
4361 (void)query_addns(client
, db
, version
);
4362 } else if (qtype
!= dns_rdatatype_ns
) {
4364 query_releasename(client
, &fname
);
4365 query_addbestns(client
);
4370 * Add NSEC records to the authority section if they're needed for
4371 * DNSSEC wildcard proofs.
4373 if (need_wildcardproof
&& dns_db_issecure(db
))
4374 query_addwildcardproof(client
, db
, version
,
4375 dns_fixedname_name(&wildcardname
),
4378 CTRACE("query_find: cleanup");
4382 if (rdataset
!= NULL
)
4383 query_putrdataset(client
, &rdataset
);
4384 if (sigrdataset
!= NULL
)
4385 query_putrdataset(client
, &sigrdataset
);
4387 query_releasename(client
, &fname
);
4389 dns_db_detachnode(db
, &node
);
4393 dns_zone_detach(&zone
);
4395 query_putrdataset(client
, &zrdataset
);
4396 if (zsigrdataset
!= NULL
)
4397 query_putrdataset(client
, &zsigrdataset
);
4399 query_releasename(client
, &zfname
);
4400 dns_db_detach(&zdb
);
4403 isc_event_free(ISC_EVENT_PTR(&event
));
4408 if (client
->query
.restarts
== 0 && !authoritative
) {
4410 * We're not authoritative, so we must ensure the AA bit
4413 client
->message
->flags
&= ~DNS_MESSAGEFLAG_AA
;
4417 * Restart the query?
4419 if (want_restart
&& client
->query
.restarts
< MAX_RESTARTS
) {
4420 client
->query
.restarts
++;
4424 if (eresult
!= ISC_R_SUCCESS
&&
4425 (!PARTIALANSWER(client
) || WANTRECURSION(client
))) {
4426 if (eresult
== DNS_R_DUPLICATE
|| eresult
== DNS_R_DROP
) {
4428 * This was a duplicate query that we are
4429 * recursing on. Don't send a response now.
4430 * The original query will still cause a response.
4432 query_next(client
, eresult
);
4435 * If we don't have any answer to give the client,
4436 * or if the client requested recursion and thus wanted
4437 * the complete answer, send an error response.
4440 query_error(client
, eresult
, line
);
4442 ns_client_detach(&client
);
4443 } else if (!RECURSING(client
)) {
4445 * We are done. Set up sortlist data for the message
4446 * rendering code, make a final tweak to the AA bit if the
4447 * auth-nxdomain config option says so, then render and
4448 * send the response.
4450 setup_query_sortlist(client
);
4453 * If this is a referral and the answer to the question
4454 * is in the glue sort it to the start of the additional
4457 if (ISC_LIST_EMPTY(client
->message
->sections
[DNS_SECTION_ANSWER
]) &&
4458 client
->message
->rcode
== dns_rcode_noerror
&&
4459 (qtype
== dns_rdatatype_a
|| qtype
== dns_rdatatype_aaaa
))
4460 answer_in_glue(client
, qtype
);
4462 if (client
->message
->rcode
== dns_rcode_nxdomain
&&
4463 client
->view
->auth_nxdomain
== ISC_TRUE
)
4464 client
->message
->flags
|= DNS_MESSAGEFLAG_AA
;
4467 * If the response is somehow unexpected for the client and this
4468 * is a result of recursion, return an error to the caller
4469 * to indicate it may need to be logged.
4472 (ISC_LIST_EMPTY(client
->message
->sections
[DNS_SECTION_ANSWER
]) ||
4473 client
->message
->rcode
!= dns_rcode_noerror
))
4474 eresult
= ISC_R_FAILURE
;
4477 ns_client_detach(&client
);
4479 CTRACE("query_find: done");
4485 log_query(ns_client_t
*client
, unsigned int flags
, unsigned int extflags
) {
4486 char namebuf
[DNS_NAME_FORMATSIZE
];
4487 char typename
[DNS_RDATATYPE_FORMATSIZE
];
4488 char classname
[DNS_RDATACLASS_FORMATSIZE
];
4489 dns_rdataset_t
*rdataset
;
4490 int level
= ISC_LOG_INFO
;
4492 if (! isc_log_wouldlog(ns_g_lctx
, level
))
4495 rdataset
= ISC_LIST_HEAD(client
->query
.qname
->list
);
4496 INSIST(rdataset
!= NULL
);
4497 dns_name_format(client
->query
.qname
, namebuf
, sizeof(namebuf
));
4498 dns_rdataclass_format(rdataset
->rdclass
, classname
, sizeof(classname
));
4499 dns_rdatatype_format(rdataset
->type
, typename
, sizeof(typename
));
4501 ns_client_log(client
, NS_LOGCATEGORY_QUERIES
, NS_LOGMODULE_QUERY
,
4502 level
, "query: %s %s %s %s%s%s%s%s", namebuf
, classname
,
4503 typename
, WANTRECURSION(client
) ? "+" : "-",
4504 (client
->signer
!= NULL
) ? "S": "",
4505 (client
->opt
!= NULL
) ? "E" : "",
4506 ((extflags
& DNS_MESSAGEEXTFLAG_DO
) != 0) ? "D" : "",
4507 ((flags
& DNS_MESSAGEFLAG_CD
) != 0) ? "C" : "");
4511 log_queryerror(ns_client_t
*client
, isc_result_t result
, int line
, int level
) {
4512 char namebuf
[DNS_NAME_FORMATSIZE
];
4513 char typename
[DNS_RDATATYPE_FORMATSIZE
];
4514 char classname
[DNS_RDATACLASS_FORMATSIZE
];
4515 const char *namep
, *typep
, *classp
, *sep1
, *sep2
;
4516 dns_rdataset_t
*rdataset
;
4518 if (!isc_log_wouldlog(ns_g_lctx
, level
))
4521 namep
= typep
= classp
= sep1
= sep2
= "";
4524 * Query errors can happen for various reasons. In some cases we cannot
4525 * even assume the query contains a valid question section, so we should
4526 * expect exceptional cases.
4528 if (client
->query
.origqname
!= NULL
) {
4529 dns_name_format(client
->query
.origqname
, namebuf
,
4534 rdataset
= ISC_LIST_HEAD(client
->query
.origqname
->list
);
4535 if (rdataset
!= NULL
) {
4536 dns_rdataclass_format(rdataset
->rdclass
, classname
,
4539 dns_rdatatype_format(rdataset
->type
, typename
,
4546 ns_client_log(client
, NS_LOGCATEGORY_QUERY_EERRORS
, NS_LOGMODULE_QUERY
,
4547 level
, "query failed (%s)%s%s%s%s%s%s at %s:%d",
4548 isc_result_totext(result
), sep1
, namep
, sep2
,
4549 classp
, sep2
, typep
, __FILE__
, line
);
4553 ns_query_start(ns_client_t
*client
) {
4554 isc_result_t result
;
4555 dns_message_t
*message
= client
->message
;
4556 dns_rdataset_t
*rdataset
;
4557 ns_client_t
*qclient
;
4558 dns_rdatatype_t qtype
;
4559 unsigned int saved_extflags
= client
->extflags
;
4560 unsigned int saved_flags
= client
->message
->flags
;
4561 isc_boolean_t want_ad
;
4563 CTRACE("ns_query_start");
4566 * Ensure that appropriate cleanups occur.
4568 client
->next
= query_next_callback
;
4571 * Behave as if we don't support DNSSEC if not enabled.
4573 if (!client
->view
->enablednssec
) {
4574 message
->flags
&= ~DNS_MESSAGEFLAG_CD
;
4575 client
->extflags
&= ~DNS_MESSAGEEXTFLAG_DO
;
4576 if (client
->opt
!= NULL
)
4577 client
->opt
->ttl
&= ~DNS_MESSAGEEXTFLAG_DO
;
4580 if ((message
->flags
& DNS_MESSAGEFLAG_RD
) != 0)
4581 client
->query
.attributes
|= NS_QUERYATTR_WANTRECURSION
;
4583 if ((client
->extflags
& DNS_MESSAGEEXTFLAG_DO
) != 0)
4584 client
->attributes
|= NS_CLIENTATTR_WANTDNSSEC
;
4586 if (client
->view
->minimalresponses
)
4587 client
->query
.attributes
|= (NS_QUERYATTR_NOAUTHORITY
|
4588 NS_QUERYATTR_NOADDITIONAL
);
4590 if ((client
->view
->cachedb
== NULL
)
4591 || (!client
->view
->additionalfromcache
)) {
4593 * We don't have a cache. Turn off cache support and
4596 client
->query
.attributes
&=
4597 ~(NS_QUERYATTR_RECURSIONOK
|NS_QUERYATTR_CACHEOK
);
4598 } else if ((client
->attributes
& NS_CLIENTATTR_RA
) == 0 ||
4599 (message
->flags
& DNS_MESSAGEFLAG_RD
) == 0) {
4601 * If the client isn't allowed to recurse (due to
4602 * "recursion no", the allow-recursion ACL, or the
4603 * lack of a resolver in this view), or if it
4604 * doesn't want recursion, turn recursion off.
4606 client
->query
.attributes
&= ~NS_QUERYATTR_RECURSIONOK
;
4610 * Get the question name.
4612 result
= dns_message_firstname(message
, DNS_SECTION_QUESTION
);
4613 if (result
!= ISC_R_SUCCESS
) {
4614 query_error(client
, result
, __LINE__
);
4617 dns_message_currentname(message
, DNS_SECTION_QUESTION
,
4618 &client
->query
.qname
);
4619 client
->query
.origqname
= client
->query
.qname
;
4620 result
= dns_message_nextname(message
, DNS_SECTION_QUESTION
);
4621 if (result
!= ISC_R_NOMORE
) {
4622 if (result
== ISC_R_SUCCESS
) {
4624 * There's more than one QNAME in the question
4627 query_error(client
, DNS_R_FORMERR
, __LINE__
);
4629 query_error(client
, result
, __LINE__
);
4633 if (ns_g_server
->log_queries
)
4634 log_query(client
, saved_flags
, saved_extflags
);
4637 * Check for multiple question queries, since edns1 is dead.
4639 if (message
->counts
[DNS_SECTION_QUESTION
] > 1) {
4640 query_error(client
, DNS_R_FORMERR
, __LINE__
);
4645 * Check for meta-queries like IXFR and AXFR.
4647 rdataset
= ISC_LIST_HEAD(client
->query
.qname
->list
);
4648 INSIST(rdataset
!= NULL
);
4649 qtype
= rdataset
->type
;
4650 dns_rdatatypestats_increment(ns_g_server
->rcvquerystats
, qtype
);
4651 if (dns_rdatatype_ismeta(qtype
)) {
4653 case dns_rdatatype_any
:
4654 break; /* Let query_find handle it. */
4655 case dns_rdatatype_ixfr
:
4656 case dns_rdatatype_axfr
:
4657 ns_xfr_start(client
, rdataset
->type
);
4659 case dns_rdatatype_maila
:
4660 case dns_rdatatype_mailb
:
4661 query_error(client
, DNS_R_NOTIMP
, __LINE__
);
4663 case dns_rdatatype_tkey
:
4664 result
= dns_tkey_processquery(client
->message
,
4665 ns_g_server
->tkeyctx
,
4666 client
->view
->dynamickeys
);
4667 if (result
== ISC_R_SUCCESS
)
4670 query_error(client
, result
, __LINE__
);
4672 default: /* TSIG, etc. */
4673 query_error(client
, DNS_R_FORMERR
, __LINE__
);
4679 * Turn on minimal response for DNSKEY and DS queries.
4681 if (qtype
== dns_rdatatype_dnskey
|| qtype
== dns_rdatatype_ds
)
4682 client
->query
.attributes
|= (NS_QUERYATTR_NOAUTHORITY
|
4683 NS_QUERYATTR_NOADDITIONAL
);
4686 * If the client has requested that DNSSEC checking be disabled,
4687 * allow lookups to return pending data and instruct the resolver
4688 * to return data before validation has completed.
4690 * We don't need to set DNS_DBFIND_PENDINGOK when validation is
4691 * disabled as there will be no pending data.
4693 if (message
->flags
& DNS_MESSAGEFLAG_CD
||
4694 qtype
== dns_rdatatype_rrsig
)
4696 client
->query
.dboptions
|= DNS_DBFIND_PENDINGOK
;
4697 client
->query
.fetchoptions
|= DNS_FETCHOPT_NOVALIDATE
;
4698 } else if (!client
->view
->enablevalidation
)
4699 client
->query
.fetchoptions
|= DNS_FETCHOPT_NOVALIDATE
;
4702 * Allow glue NS records to be added to the authority section
4703 * if the answer is secure.
4705 if (message
->flags
& DNS_MESSAGEFLAG_CD
)
4706 client
->query
.attributes
&= ~NS_QUERYATTR_SECURE
;
4709 * Set 'want_ad' if the client has set AD in the query.
4710 * This allows AD to be returned on queries without DO set.
4712 if ((message
->flags
& DNS_MESSAGEFLAG_AD
) != 0)
4715 want_ad
= ISC_FALSE
;
4718 * This is an ordinary query.
4720 result
= dns_message_reply(message
, ISC_TRUE
);
4721 if (result
!= ISC_R_SUCCESS
) {
4722 query_next(client
, result
);
4727 * Assume authoritative response until it is known to be
4730 message
->flags
|= DNS_MESSAGEFLAG_AA
;
4733 * Set AD. We must clear it if we add non-validated data to a
4736 if (WANTDNSSEC(client
) || want_ad
)
4737 message
->flags
|= DNS_MESSAGEFLAG_AD
;
4740 ns_client_attach(client
, &qclient
);
4741 (void)query_find(qclient
, NULL
, qtype
);