2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.198.2.13.4.43 2006/08/31 03:57:11 marka Exp $ */
28 #include <dns/byaddr.h>
30 #include <dns/events.h>
31 #include <dns/message.h>
32 #include <dns/order.h>
33 #include <dns/rdata.h>
34 #include <dns/rdataclass.h>
35 #include <dns/rdatalist.h>
36 #include <dns/rdataset.h>
37 #include <dns/rdatasetiter.h>
38 #include <dns/rdatastruct.h>
39 #include <dns/rdatatype.h>
40 #include <dns/resolver.h>
41 #include <dns/result.h>
42 #include <dns/stats.h>
48 #include <named/client.h>
49 #include <named/log.h>
50 #include <named/server.h>
51 #include <named/sortlist.h>
52 #include <named/xfrout.h>
54 #define PARTIALANSWER(c) (((c)->query.attributes & \
55 NS_QUERYATTR_PARTIALANSWER) != 0)
56 #define USECACHE(c) (((c)->query.attributes & \
57 NS_QUERYATTR_CACHEOK) != 0)
58 #define RECURSIONOK(c) (((c)->query.attributes & \
59 NS_QUERYATTR_RECURSIONOK) != 0)
60 #define RECURSING(c) (((c)->query.attributes & \
61 NS_QUERYATTR_RECURSING) != 0)
62 #define CACHEGLUEOK(c) (((c)->query.attributes & \
63 NS_QUERYATTR_CACHEGLUEOK) != 0)
64 #define WANTRECURSION(c) (((c)->query.attributes & \
65 NS_QUERYATTR_WANTRECURSION) != 0)
66 #define WANTDNSSEC(c) (((c)->attributes & \
67 NS_CLIENTATTR_WANTDNSSEC) != 0)
68 #define NOAUTHORITY(c) (((c)->query.attributes & \
69 NS_QUERYATTR_NOAUTHORITY) != 0)
70 #define NOADDITIONAL(c) (((c)->query.attributes & \
71 NS_QUERYATTR_NOADDITIONAL) != 0)
72 #define SECURE(c) (((c)->query.attributes & \
73 NS_QUERYATTR_SECURE) != 0)
76 #define CTRACE(m) isc_log_write(ns_g_lctx, \
77 NS_LOGCATEGORY_CLIENT, \
80 "client %p: %s", client, (m))
81 #define QTRACE(m) isc_log_write(ns_g_lctx, \
82 NS_LOGCATEGORY_GENERAL, \
85 "query %p: %s", query, (m))
87 #define CTRACE(m) ((void)m)
88 #define QTRACE(m) ((void)m)
91 #define DNS_GETDB_NOEXACT 0x01U
92 #define DNS_GETDB_NOLOG 0x02U
93 #define DNS_GETDB_PARTIAL 0x04U
96 query_find(ns_client_t
*client
, dns_fetchevent_t
*event
, dns_rdatatype_t qtype
);
99 * Increment query statistics counters.
102 inc_stats(ns_client_t
*client
, dns_statscounter_t counter
) {
103 dns_zone_t
*zone
= client
->query
.authzone
;
105 REQUIRE(counter
< DNS_STATS_NCOUNTERS
);
107 ns_g_server
->querystats
[counter
]++;
110 isc_uint64_t
*zonestats
= dns_zone_getstatscounters(zone
);
111 if (zonestats
!= NULL
)
112 zonestats
[counter
]++;
117 query_send(ns_client_t
*client
) {
118 dns_statscounter_t counter
;
119 if (client
->message
->rcode
== dns_rcode_noerror
) {
120 if (ISC_LIST_EMPTY(client
->message
->sections
[DNS_SECTION_ANSWER
])) {
121 if (client
->query
.isreferral
) {
122 counter
= dns_statscounter_referral
;
124 counter
= dns_statscounter_nxrrset
;
127 counter
= dns_statscounter_success
;
129 } else if (client
->message
->rcode
== dns_rcode_nxdomain
) {
130 counter
= dns_statscounter_nxdomain
;
132 /* We end up here in case of YXDOMAIN, and maybe others */
133 counter
= dns_statscounter_failure
;
135 inc_stats(client
, counter
);
136 ns_client_send(client
);
140 query_error(ns_client_t
*client
, isc_result_t result
) {
141 inc_stats(client
, dns_statscounter_failure
);
142 ns_client_error(client
, result
);
146 query_next(ns_client_t
*client
, isc_result_t result
) {
147 inc_stats(client
, dns_statscounter_failure
);
148 ns_client_next(client
, result
);
152 query_freefreeversions(ns_client_t
*client
, isc_boolean_t everything
) {
153 ns_dbversion_t
*dbversion
, *dbversion_next
;
156 for (dbversion
= ISC_LIST_HEAD(client
->query
.freeversions
), i
= 0;
158 dbversion
= dbversion_next
, i
++)
160 dbversion_next
= ISC_LIST_NEXT(dbversion
, link
);
162 * If we're not freeing everything, we keep the first three
163 * dbversions structures around.
165 if (i
> 3 || everything
) {
166 ISC_LIST_UNLINK(client
->query
.freeversions
, dbversion
,
168 isc_mem_put(client
->mctx
, dbversion
,
175 ns_query_cancel(ns_client_t
*client
) {
176 LOCK(&client
->query
.fetchlock
);
177 if (client
->query
.fetch
!= NULL
) {
178 dns_resolver_cancelfetch(client
->query
.fetch
);
180 client
->query
.fetch
= NULL
;
182 UNLOCK(&client
->query
.fetchlock
);
186 query_reset(ns_client_t
*client
, isc_boolean_t everything
) {
187 isc_buffer_t
*dbuf
, *dbuf_next
;
188 ns_dbversion_t
*dbversion
, *dbversion_next
;
191 * Reset the query state of a client to its default state.
195 * Cancel the fetch if it's running.
197 ns_query_cancel(client
);
200 * Cleanup any active versions.
202 for (dbversion
= ISC_LIST_HEAD(client
->query
.activeversions
);
204 dbversion
= dbversion_next
) {
205 dbversion_next
= ISC_LIST_NEXT(dbversion
, link
);
206 dns_db_closeversion(dbversion
->db
, &dbversion
->version
,
208 dns_db_detach(&dbversion
->db
);
209 ISC_LIST_INITANDAPPEND(client
->query
.freeversions
,
212 ISC_LIST_INIT(client
->query
.activeversions
);
214 if (client
->query
.authdb
!= NULL
)
215 dns_db_detach(&client
->query
.authdb
);
216 if (client
->query
.authzone
!= NULL
)
217 dns_zone_detach(&client
->query
.authzone
);
219 query_freefreeversions(client
, everything
);
221 for (dbuf
= ISC_LIST_HEAD(client
->query
.namebufs
);
224 dbuf_next
= ISC_LIST_NEXT(dbuf
, link
);
225 if (dbuf_next
!= NULL
|| everything
) {
226 ISC_LIST_UNLINK(client
->query
.namebufs
, dbuf
, link
);
227 isc_buffer_free(&dbuf
);
231 if (client
->query
.restarts
> 0) {
233 * client->query.qname was dynamically allocated.
235 dns_message_puttempname(client
->message
,
236 &client
->query
.qname
);
238 client
->query
.qname
= NULL
;
239 client
->query
.attributes
= (NS_QUERYATTR_RECURSIONOK
|
240 NS_QUERYATTR_CACHEOK
|
241 NS_QUERYATTR_SECURE
);
242 client
->query
.restarts
= 0;
243 client
->query
.timerset
= ISC_FALSE
;
244 client
->query
.origqname
= NULL
;
245 client
->query
.qname
= NULL
;
246 client
->query
.dboptions
= 0;
247 client
->query
.fetchoptions
= 0;
248 client
->query
.gluedb
= NULL
;
249 client
->query
.authdbset
= ISC_FALSE
;
250 client
->query
.isreferral
= ISC_FALSE
;
254 query_next_callback(ns_client_t
*client
) {
255 query_reset(client
, ISC_FALSE
);
259 ns_query_free(ns_client_t
*client
) {
260 query_reset(client
, ISC_TRUE
);
263 static inline isc_result_t
264 query_newnamebuf(ns_client_t
*client
) {
268 CTRACE("query_newnamebuf");
270 * Allocate a name buffer.
274 result
= isc_buffer_allocate(client
->mctx
, &dbuf
, 1024);
275 if (result
!= ISC_R_SUCCESS
) {
276 CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
279 ISC_LIST_APPEND(client
->query
.namebufs
, dbuf
, link
);
281 CTRACE("query_newnamebuf: done");
282 return (ISC_R_SUCCESS
);
285 static inline isc_buffer_t
*
286 query_getnamebuf(ns_client_t
*client
) {
291 CTRACE("query_getnamebuf");
293 * Return a name buffer with space for a maximal name, allocating
294 * a new one if necessary.
297 if (ISC_LIST_EMPTY(client
->query
.namebufs
)) {
298 result
= query_newnamebuf(client
);
299 if (result
!= ISC_R_SUCCESS
) {
300 CTRACE("query_getnamebuf: query_newnamebuf failed: done");
305 dbuf
= ISC_LIST_TAIL(client
->query
.namebufs
);
306 INSIST(dbuf
!= NULL
);
307 isc_buffer_availableregion(dbuf
, &r
);
308 if (r
.length
< 255) {
309 result
= query_newnamebuf(client
);
310 if (result
!= ISC_R_SUCCESS
) {
311 CTRACE("query_getnamebuf: query_newnamebuf failed: done");
315 dbuf
= ISC_LIST_TAIL(client
->query
.namebufs
);
316 isc_buffer_availableregion(dbuf
, &r
);
317 INSIST(r
.length
>= 255);
319 CTRACE("query_getnamebuf: done");
324 query_keepname(ns_client_t
*client
, dns_name_t
*name
, isc_buffer_t
*dbuf
) {
327 CTRACE("query_keepname");
329 * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
330 * adjusted to take account of that. We do the adjustment.
333 REQUIRE((client
->query
.attributes
& NS_QUERYATTR_NAMEBUFUSED
) != 0);
335 dns_name_toregion(name
, &r
);
336 isc_buffer_add(dbuf
, r
.length
);
337 dns_name_setbuffer(name
, NULL
);
338 client
->query
.attributes
&= ~NS_QUERYATTR_NAMEBUFUSED
;
342 query_releasename(ns_client_t
*client
, dns_name_t
**namep
) {
343 dns_name_t
*name
= *namep
;
346 * 'name' is no longer needed. Return it to our pool of temporary
347 * names. If it is using a name buffer, relinquish its exclusive
348 * rights on the buffer.
351 CTRACE("query_releasename");
352 if (dns_name_hasbuffer(name
)) {
353 INSIST((client
->query
.attributes
& NS_QUERYATTR_NAMEBUFUSED
)
355 client
->query
.attributes
&= ~NS_QUERYATTR_NAMEBUFUSED
;
357 dns_message_puttempname(client
->message
, namep
);
358 CTRACE("query_releasename: done");
361 static inline dns_name_t
*
362 query_newname(ns_client_t
*client
, isc_buffer_t
*dbuf
,
369 REQUIRE((client
->query
.attributes
& NS_QUERYATTR_NAMEBUFUSED
) == 0);
371 CTRACE("query_newname");
373 result
= dns_message_gettempname(client
->message
, &name
);
374 if (result
!= ISC_R_SUCCESS
) {
375 CTRACE("query_newname: dns_message_gettempname failed: done");
378 isc_buffer_availableregion(dbuf
, &r
);
379 isc_buffer_init(nbuf
, r
.base
, r
.length
);
380 dns_name_init(name
, NULL
);
381 dns_name_setbuffer(name
, nbuf
);
382 client
->query
.attributes
|= NS_QUERYATTR_NAMEBUFUSED
;
384 CTRACE("query_newname: done");
388 static inline dns_rdataset_t
*
389 query_newrdataset(ns_client_t
*client
) {
390 dns_rdataset_t
*rdataset
;
393 CTRACE("query_newrdataset");
395 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
396 if (result
!= ISC_R_SUCCESS
) {
397 CTRACE("query_newrdataset: "
398 "dns_message_gettemprdataset failed: done");
401 dns_rdataset_init(rdataset
);
403 CTRACE("query_newrdataset: done");
408 query_putrdataset(ns_client_t
*client
, dns_rdataset_t
**rdatasetp
) {
409 dns_rdataset_t
*rdataset
= *rdatasetp
;
411 CTRACE("query_putrdataset");
412 if (rdataset
!= NULL
) {
413 if (dns_rdataset_isassociated(rdataset
))
414 dns_rdataset_disassociate(rdataset
);
415 dns_message_puttemprdataset(client
->message
, rdatasetp
);
417 CTRACE("query_putrdataset: done");
421 static inline isc_result_t
422 query_newdbversion(ns_client_t
*client
, unsigned int n
) {
424 ns_dbversion_t
*dbversion
;
426 for (i
= 0; i
< n
; i
++) {
427 dbversion
= isc_mem_get(client
->mctx
, sizeof(*dbversion
));
428 if (dbversion
!= NULL
) {
429 dbversion
->db
= NULL
;
430 dbversion
->version
= NULL
;
431 ISC_LIST_INITANDAPPEND(client
->query
.freeversions
,
435 * We only return ISC_R_NOMEMORY if we couldn't
439 return (ISC_R_NOMEMORY
);
441 return (ISC_R_SUCCESS
);
445 return (ISC_R_SUCCESS
);
448 static inline ns_dbversion_t
*
449 query_getdbversion(ns_client_t
*client
) {
451 ns_dbversion_t
*dbversion
;
453 if (ISC_LIST_EMPTY(client
->query
.freeversions
)) {
454 result
= query_newdbversion(client
, 1);
455 if (result
!= ISC_R_SUCCESS
)
458 dbversion
= ISC_LIST_HEAD(client
->query
.freeversions
);
459 INSIST(dbversion
!= NULL
);
460 ISC_LIST_UNLINK(client
->query
.freeversions
, dbversion
, link
);
466 ns_query_init(ns_client_t
*client
) {
469 ISC_LIST_INIT(client
->query
.namebufs
);
470 ISC_LIST_INIT(client
->query
.activeversions
);
471 ISC_LIST_INIT(client
->query
.freeversions
);
472 client
->query
.restarts
= 0;
473 client
->query
.timerset
= ISC_FALSE
;
474 client
->query
.qname
= NULL
;
475 result
= isc_mutex_init(&client
->query
.fetchlock
);
476 if (result
!= ISC_R_SUCCESS
)
478 client
->query
.fetch
= NULL
;
479 client
->query
.authdb
= NULL
;
480 client
->query
.authzone
= NULL
;
481 client
->query
.authdbset
= ISC_FALSE
;
482 client
->query
.isreferral
= ISC_FALSE
;
483 query_reset(client
, ISC_FALSE
);
484 result
= query_newdbversion(client
, 3);
485 if (result
!= ISC_R_SUCCESS
) {
486 DESTROYLOCK(&client
->query
.fetchlock
);
489 result
= query_newnamebuf(client
);
490 if (result
!= ISC_R_SUCCESS
)
491 query_freefreeversions(client
, ISC_TRUE
);
496 static inline ns_dbversion_t
*
497 query_findversion(ns_client_t
*client
, dns_db_t
*db
,
498 isc_boolean_t
*newzonep
)
500 ns_dbversion_t
*dbversion
;
503 * We may already have done a query related to this
504 * database. If so, we must be sure to make subsequent
505 * queries from the same version.
507 for (dbversion
= ISC_LIST_HEAD(client
->query
.activeversions
);
509 dbversion
= ISC_LIST_NEXT(dbversion
, link
)) {
510 if (dbversion
->db
== db
)
514 if (dbversion
== NULL
) {
516 * This is a new zone for this query. Add it to
519 dbversion
= query_getdbversion(client
);
520 if (dbversion
== NULL
)
522 dns_db_attach(db
, &dbversion
->db
);
523 dns_db_currentversion(db
, &dbversion
->version
);
524 dbversion
->queryok
= ISC_FALSE
;
525 ISC_LIST_APPEND(client
->query
.activeversions
,
527 *newzonep
= ISC_TRUE
;
529 *newzonep
= ISC_FALSE
;
534 static inline isc_result_t
535 query_getzonedb(ns_client_t
*client
, dns_name_t
*name
, dns_rdatatype_t qtype
,
536 unsigned int options
, dns_zone_t
**zonep
, dns_db_t
**dbp
,
537 dns_dbversion_t
**versionp
)
540 isc_boolean_t check_acl
, new_zone
;
542 ns_dbversion_t
*dbversion
;
543 unsigned int ztoptions
;
544 dns_zone_t
*zone
= NULL
;
546 isc_boolean_t partial
= ISC_FALSE
;
548 REQUIRE(zonep
!= NULL
&& *zonep
== NULL
);
549 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
552 * Find a zone database to answer the query.
554 ztoptions
= ((options
& DNS_GETDB_NOEXACT
) != 0) ?
555 DNS_ZTFIND_NOEXACT
: 0;
557 result
= dns_zt_find(client
->view
->zonetable
, name
, ztoptions
, NULL
,
559 if (result
== DNS_R_PARTIALMATCH
)
561 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
562 result
= dns_zone_getdb(zone
, &db
);
564 if (result
!= ISC_R_SUCCESS
)
568 * This limits our searching to the zone where the first name
569 * (the query target) was looked for. This prevents following
570 * CNAMES or DNAMES into other zones and prevents returning
571 * additional data from other zones.
573 if (!client
->view
->additionalfromauth
&&
574 client
->query
.authdbset
&&
575 db
!= client
->query
.authdb
)
579 * If the zone has an ACL, we'll check it, otherwise
580 * we use the view's "allow-query" ACL. Each ACL is only checked
583 * Also, get the database version to use.
586 check_acl
= ISC_TRUE
; /* Keep compiler happy. */
590 * Get the current version of this database.
592 dbversion
= query_findversion(client
, db
, &new_zone
);
593 if (dbversion
== NULL
) {
594 result
= DNS_R_SERVFAIL
;
598 check_acl
= ISC_TRUE
;
599 } else if (!dbversion
->queryok
) {
602 check_acl
= ISC_FALSE
;
605 queryacl
= dns_zone_getqueryacl(zone
);
606 if (queryacl
== NULL
) {
607 queryacl
= client
->view
->queryacl
;
608 if ((client
->query
.attributes
&
609 NS_QUERYATTR_QUERYOKVALID
) != 0) {
611 * We've evaluated the view's queryacl already. If
612 * NS_QUERYATTR_QUERYOK is set, then the client is
613 * allowed to make queries, otherwise the query should
616 check_acl
= ISC_FALSE
;
617 if ((client
->query
.attributes
&
618 NS_QUERYATTR_QUERYOK
) == 0)
622 * We haven't evaluated the view's queryacl yet.
624 check_acl
= ISC_TRUE
;
629 isc_boolean_t log
= ISC_TF((options
& DNS_GETDB_NOLOG
) == 0);
631 result
= ns_client_checkaclsilent(client
, queryacl
, ISC_TRUE
);
633 char msg
[NS_CLIENT_ACLMSGSIZE("query")];
634 if (result
== ISC_R_SUCCESS
) {
635 if (isc_log_wouldlog(ns_g_lctx
,
638 ns_client_aclmsg("query", name
, qtype
,
639 client
->view
->rdclass
,
641 ns_client_log(client
,
642 DNS_LOGCATEGORY_SECURITY
,
648 ns_client_aclmsg("query", name
, qtype
,
649 client
->view
->rdclass
,
651 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
652 NS_LOGMODULE_QUERY
, ISC_LOG_INFO
,
657 if (queryacl
== client
->view
->queryacl
) {
658 if (result
== ISC_R_SUCCESS
) {
660 * We were allowed by the default
661 * "allow-query" ACL. Remember this so we
662 * don't have to check again.
664 client
->query
.attributes
|=
665 NS_QUERYATTR_QUERYOK
;
668 * We've now evaluated the view's query ACL, and
669 * the NS_QUERYATTR_QUERYOK attribute is now valid.
671 client
->query
.attributes
|= NS_QUERYATTR_QUERYOKVALID
;
674 if (result
!= ISC_R_SUCCESS
)
681 * Remember the result of the ACL check so we
682 * don't have to check again.
684 dbversion
->queryok
= ISC_TRUE
;
686 /* Transfer ownership. */
689 *versionp
= dbversion
->version
;
691 if (partial
&& (options
& DNS_GETDB_PARTIAL
) != 0)
692 return (DNS_R_PARTIALMATCH
);
693 return (ISC_R_SUCCESS
);
696 result
= DNS_R_REFUSED
;
699 dns_zone_detach(&zone
);
706 static inline isc_result_t
707 query_getcachedb(ns_client_t
*client
, dns_name_t
*name
, dns_rdatatype_t qtype
,
708 dns_db_t
**dbp
, unsigned int options
)
711 isc_boolean_t check_acl
;
714 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
717 * Find a cache database to answer the query.
718 * This may fail with DNS_R_REFUSED if the client
719 * is not allowed to use the cache.
722 if (!USECACHE(client
))
723 return (DNS_R_REFUSED
);
724 dns_db_attach(client
->view
->cachedb
, &db
);
726 if ((client
->query
.attributes
&
727 NS_QUERYATTR_QUERYOKVALID
) != 0) {
729 * We've evaluated the view's queryacl already. If
730 * NS_QUERYATTR_QUERYOK is set, then the client is
731 * allowed to make queries, otherwise the query should
734 check_acl
= ISC_FALSE
;
735 if ((client
->query
.attributes
&
736 NS_QUERYATTR_QUERYOK
) == 0)
740 * We haven't evaluated the view's queryacl yet.
742 check_acl
= ISC_TRUE
;
746 isc_boolean_t log
= ISC_TF((options
& DNS_GETDB_NOLOG
) == 0);
747 char msg
[NS_CLIENT_ACLMSGSIZE("query (cache)")];
749 result
= ns_client_checkaclsilent(client
,
750 client
->view
->queryacl
,
752 if (result
== ISC_R_SUCCESS
) {
754 * We were allowed by the default
755 * "allow-query" ACL. Remember this so we
756 * don't have to check again.
758 client
->query
.attributes
|=
759 NS_QUERYATTR_QUERYOK
;
760 if (log
&& isc_log_wouldlog(ns_g_lctx
,
763 ns_client_aclmsg("query (cache)", name
, qtype
,
764 client
->view
->rdclass
,
766 ns_client_log(client
,
767 DNS_LOGCATEGORY_SECURITY
,
773 ns_client_aclmsg("query (cache)", name
, qtype
,
774 client
->view
->rdclass
, msg
,
776 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
777 NS_LOGMODULE_QUERY
, ISC_LOG_INFO
,
781 * We've now evaluated the view's query ACL, and
782 * the NS_QUERYATTR_QUERYOK attribute is now valid.
784 client
->query
.attributes
|= NS_QUERYATTR_QUERYOKVALID
;
786 if (result
!= ISC_R_SUCCESS
)
792 /* Transfer ownership. */
795 return (ISC_R_SUCCESS
);
798 result
= DNS_R_REFUSED
;
807 static inline isc_result_t
808 query_getdb(ns_client_t
*client
, dns_name_t
*name
, dns_rdatatype_t qtype
,
809 unsigned int options
, dns_zone_t
**zonep
, dns_db_t
**dbp
,
810 dns_dbversion_t
**versionp
, isc_boolean_t
*is_zonep
)
814 result
= query_getzonedb(client
, name
, qtype
, options
,
815 zonep
, dbp
, versionp
);
816 if (result
== ISC_R_SUCCESS
) {
817 *is_zonep
= ISC_TRUE
;
818 } else if (result
== ISC_R_NOTFOUND
) {
819 result
= query_getcachedb(client
, name
, qtype
, dbp
, options
);
820 *is_zonep
= ISC_FALSE
;
825 static inline isc_boolean_t
826 query_isduplicate(ns_client_t
*client
, dns_name_t
*name
,
827 dns_rdatatype_t type
, dns_name_t
**mnamep
)
829 dns_section_t section
;
830 dns_name_t
*mname
= NULL
;
833 CTRACE("query_isduplicate");
835 for (section
= DNS_SECTION_ANSWER
;
836 section
<= DNS_SECTION_ADDITIONAL
;
838 result
= dns_message_findname(client
->message
, section
,
839 name
, type
, 0, &mname
, NULL
);
840 if (result
== ISC_R_SUCCESS
) {
842 * We've already got this RRset in the response.
844 CTRACE("query_isduplicate: true: done");
846 } else if (result
== DNS_R_NXRRSET
) {
848 * The name exists, but the rdataset does not.
850 if (section
== DNS_SECTION_ADDITIONAL
)
853 RUNTIME_CHECK(result
== DNS_R_NXDOMAIN
);
858 * If the dns_name_t we're looking up is already in the message,
859 * we don't want to trigger the caller's name replacement logic.
866 CTRACE("query_isduplicate: false: done");
871 query_addadditional(void *arg
, dns_name_t
*name
, dns_rdatatype_t qtype
) {
872 ns_client_t
*client
= arg
;
873 isc_result_t result
, eresult
;
876 dns_name_t
*fname
, *mname
;
877 dns_rdataset_t
*rdataset
, *sigrdataset
, *trdataset
;
880 dns_dbversion_t
*version
;
881 isc_boolean_t added_something
, need_addname
;
883 dns_rdatatype_t type
;
885 REQUIRE(NS_CLIENT_VALID(client
));
886 REQUIRE(qtype
!= dns_rdatatype_any
);
888 if (!WANTDNSSEC(client
) && dns_rdatatype_isdnssec(qtype
))
889 return (ISC_R_SUCCESS
);
891 CTRACE("query_addadditional");
896 eresult
= ISC_R_SUCCESS
;
904 added_something
= ISC_FALSE
;
905 need_addname
= ISC_FALSE
;
909 * We treat type A additional section processing as if it
910 * were "any address type" additional section processing.
911 * To avoid multiple lookups, we do an 'any' database
912 * lookup and iterate over the node.
914 if (qtype
== dns_rdatatype_a
)
915 type
= dns_rdatatype_any
;
920 * Get some resources.
922 dbuf
= query_getnamebuf(client
);
925 fname
= query_newname(client
, dbuf
, &b
);
926 rdataset
= query_newrdataset(client
);
927 if (fname
== NULL
|| rdataset
== NULL
)
929 if (WANTDNSSEC(client
)) {
930 sigrdataset
= query_newrdataset(client
);
931 if (sigrdataset
== NULL
)
936 * Look for a zone database that might contain authoritative
939 result
= query_getzonedb(client
, name
, qtype
, DNS_GETDB_NOLOG
,
940 &zone
, &db
, &version
);
941 if (result
!= ISC_R_SUCCESS
)
944 CTRACE("query_addadditional: db_find");
947 * Since we are looking for authoritative data, we do not set
948 * the GLUEOK flag. Glue will be looked for later, but not
949 * necessarily in the same database.
952 result
= dns_db_find(db
, name
, version
, type
, client
->query
.dboptions
,
953 client
->now
, &node
, fname
, rdataset
,
955 if (result
== ISC_R_SUCCESS
)
958 if (dns_rdataset_isassociated(rdataset
))
959 dns_rdataset_disassociate(rdataset
);
960 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
))
961 dns_rdataset_disassociate(sigrdataset
);
963 dns_db_detachnode(db
, &node
);
968 * No authoritative data was found. The cache is our next best bet.
972 result
= query_getcachedb(client
, name
, qtype
, &db
, DNS_GETDB_NOLOG
);
973 if (result
!= ISC_R_SUCCESS
)
975 * Most likely the client isn't allowed to query the cache.
979 result
= dns_db_find(db
, name
, version
, type
, client
->query
.dboptions
,
980 client
->now
, &node
, fname
, rdataset
,
982 if (result
== ISC_R_SUCCESS
)
985 if (dns_rdataset_isassociated(rdataset
))
986 dns_rdataset_disassociate(rdataset
);
987 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
))
988 dns_rdataset_disassociate(sigrdataset
);
990 dns_db_detachnode(db
, &node
);
995 * No cached data was found. Glue is our last chance.
998 * NS records cause both the usual additional section
999 * processing to locate a type A record, and, when used
1000 * in a referral, a special search of the zone in which
1001 * they reside for glue information.
1003 * This is the "special search". Note that we must search
1004 * the zone where the NS record resides, not the zone it
1005 * points to, and that we only do the search in the delegation
1006 * case (identified by client->query.gluedb being set).
1009 if (client
->query
.gluedb
== NULL
)
1013 * Don't poision caches using the bailiwick protection model.
1015 if (!dns_name_issubdomain(name
, dns_db_origin(client
->query
.gluedb
)))
1018 dns_db_attach(client
->query
.gluedb
, &db
);
1019 result
= dns_db_find(db
, name
, version
, type
,
1020 client
->query
.dboptions
| DNS_DBFIND_GLUEOK
,
1021 client
->now
, &node
, fname
, rdataset
,
1023 if (!(result
== ISC_R_SUCCESS
||
1024 result
== DNS_R_ZONECUT
||
1025 result
== DNS_R_GLUE
))
1030 * We have found a potential additional data rdataset, or
1031 * at least a node to iterate over.
1033 query_keepname(client
, fname
, dbuf
);
1036 * If we have an rdataset, add it to the additional data
1040 if (dns_rdataset_isassociated(rdataset
) &&
1041 !query_isduplicate(client
, fname
, type
, &mname
)) {
1042 if (mname
!= NULL
) {
1043 query_releasename(client
, &fname
);
1046 need_addname
= ISC_TRUE
;
1047 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1048 trdataset
= rdataset
;
1050 added_something
= ISC_TRUE
;
1052 * Note: we only add SIGs if we've added the type they cover,
1053 * so we do not need to check if the SIG rdataset is already
1056 if (sigrdataset
!= NULL
&&
1057 dns_rdataset_isassociated(sigrdataset
))
1059 ISC_LIST_APPEND(fname
->list
, sigrdataset
, link
);
1064 if (qtype
== dns_rdatatype_a
) {
1066 * We now go looking for A and AAAA records, along with
1069 * XXXRTH This code could be more efficient.
1071 if (rdataset
!= NULL
) {
1072 if (dns_rdataset_isassociated(rdataset
))
1073 dns_rdataset_disassociate(rdataset
);
1075 rdataset
= query_newrdataset(client
);
1076 if (rdataset
== NULL
)
1079 if (sigrdataset
!= NULL
) {
1080 if (dns_rdataset_isassociated(sigrdataset
))
1081 dns_rdataset_disassociate(sigrdataset
);
1082 } else if (WANTDNSSEC(client
)) {
1083 sigrdataset
= query_newrdataset(client
);
1084 if (sigrdataset
== NULL
)
1087 result
= dns_db_findrdataset(db
, node
, version
,
1089 client
->now
, rdataset
,
1091 if (result
== DNS_R_NCACHENXDOMAIN
)
1093 if (result
== DNS_R_NCACHENXRRSET
) {
1094 dns_rdataset_disassociate(rdataset
);
1096 * Negative cache entries don't have sigrdatasets.
1098 INSIST(sigrdataset
== NULL
||
1099 ! dns_rdataset_isassociated(sigrdataset
));
1101 if (result
== ISC_R_SUCCESS
) {
1103 if (!query_isduplicate(client
, fname
,
1104 dns_rdatatype_a
, &mname
)) {
1105 if (mname
!= NULL
) {
1106 query_releasename(client
, &fname
);
1109 need_addname
= ISC_TRUE
;
1110 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1111 added_something
= ISC_TRUE
;
1112 if (sigrdataset
!= NULL
&&
1113 dns_rdataset_isassociated(sigrdataset
))
1115 ISC_LIST_APPEND(fname
->list
,
1118 query_newrdataset(client
);
1120 rdataset
= query_newrdataset(client
);
1121 if (rdataset
== NULL
)
1123 if (WANTDNSSEC(client
) && sigrdataset
== NULL
)
1126 dns_rdataset_disassociate(rdataset
);
1127 if (sigrdataset
!= NULL
&&
1128 dns_rdataset_isassociated(sigrdataset
))
1129 dns_rdataset_disassociate(sigrdataset
);
1132 result
= dns_db_findrdataset(db
, node
, version
,
1133 dns_rdatatype_aaaa
, 0,
1134 client
->now
, rdataset
,
1136 if (result
== DNS_R_NCACHENXDOMAIN
)
1138 if (result
== DNS_R_NCACHENXRRSET
) {
1139 dns_rdataset_disassociate(rdataset
);
1140 INSIST(sigrdataset
== NULL
||
1141 ! dns_rdataset_isassociated(sigrdataset
));
1143 if (result
== ISC_R_SUCCESS
) {
1145 if (!query_isduplicate(client
, fname
,
1146 dns_rdatatype_aaaa
, &mname
)) {
1147 if (mname
!= NULL
) {
1148 query_releasename(client
, &fname
);
1151 need_addname
= ISC_TRUE
;
1152 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1153 added_something
= ISC_TRUE
;
1154 if (sigrdataset
!= NULL
&&
1155 dns_rdataset_isassociated(sigrdataset
))
1157 ISC_LIST_APPEND(fname
->list
,
1167 CTRACE("query_addadditional: addname");
1169 * If we haven't added anything, then we're done.
1171 if (!added_something
)
1175 * We may have added our rdatasets to an existing name, if so, then
1176 * need_addname will be ISC_FALSE. Whether we used an existing name
1177 * or a new one, we must set fname to NULL to prevent cleanup.
1180 dns_message_addname(client
->message
, fname
,
1181 DNS_SECTION_ADDITIONAL
);
1185 * In a few cases, we want to add additional data for additional
1186 * data. It's simpler to just deal with special cases here than
1187 * to try to create a general purpose mechanism and allow the
1188 * rdata implementations to do it themselves.
1190 * This involves recursion, but the depth is limited. The
1191 * most complex case is adding a SRV rdataset, which involves
1192 * recursing to add address records, which in turn can cause
1193 * recursion to add KEYs.
1195 if (type
== dns_rdatatype_srv
&& trdataset
!= NULL
) {
1197 * If we're adding SRV records to the additional data
1198 * section, it's helpful if we add the SRV additional data
1201 eresult
= dns_rdataset_additionaldata(trdataset
,
1202 query_addadditional
,
1207 CTRACE("query_addadditional: cleanup");
1208 query_putrdataset(client
, &rdataset
);
1209 if (sigrdataset
!= NULL
)
1210 query_putrdataset(client
, &sigrdataset
);
1212 query_releasename(client
, &fname
);
1214 dns_db_detachnode(db
, &node
);
1218 dns_zone_detach(&zone
);
1220 CTRACE("query_addadditional: done");
1225 query_addrdataset(ns_client_t
*client
, dns_name_t
*fname
,
1226 dns_rdataset_t
*rdataset
)
1229 * Add 'rdataset' and any pertinent additional data to
1230 * 'fname', a name in the response message for 'client'.
1233 CTRACE("query_addrdataset");
1235 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1237 if (client
->view
->order
!= NULL
)
1238 rdataset
->attributes
|= dns_order_find(client
->view
->order
,
1239 fname
, rdataset
->type
,
1241 if (NOADDITIONAL(client
))
1245 * Add additional data.
1247 * We don't care if dns_rdataset_additionaldata() fails.
1249 (void)dns_rdataset_additionaldata(rdataset
,
1250 query_addadditional
, client
);
1251 CTRACE("query_addrdataset: done");
1255 query_addrrset(ns_client_t
*client
, dns_name_t
**namep
,
1256 dns_rdataset_t
**rdatasetp
, dns_rdataset_t
**sigrdatasetp
,
1257 isc_buffer_t
*dbuf
, dns_section_t section
)
1259 dns_name_t
*name
, *mname
;
1260 dns_rdataset_t
*rdataset
, *mrdataset
, *sigrdataset
;
1261 isc_result_t result
;
1264 * To the current response for 'client', add the answer RRset
1265 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
1266 * owner name '*namep', to section 'section', unless they are
1267 * already there. Also add any pertinent additional data.
1269 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
1270 * stored in 'dbuf'. In this case, query_addrrset() guarantees that
1271 * when it returns the name will either have been kept or released.
1273 CTRACE("query_addrrset");
1275 rdataset
= *rdatasetp
;
1276 if (sigrdatasetp
!= NULL
)
1277 sigrdataset
= *sigrdatasetp
;
1282 result
= dns_message_findname(client
->message
, section
,
1283 name
, rdataset
->type
, rdataset
->covers
,
1284 &mname
, &mrdataset
);
1285 if (result
== ISC_R_SUCCESS
) {
1287 * We've already got an RRset of the given name and type.
1288 * There's nothing else to do;
1290 CTRACE("query_addrrset: dns_message_findname succeeded: done");
1292 query_releasename(client
, namep
);
1294 } else if (result
== DNS_R_NXDOMAIN
) {
1296 * The name doesn't exist.
1299 query_keepname(client
, name
, dbuf
);
1300 dns_message_addname(client
->message
, name
, section
);
1304 RUNTIME_CHECK(result
== DNS_R_NXRRSET
);
1306 query_releasename(client
, namep
);
1309 if (rdataset
->trust
!= dns_trust_secure
&&
1310 (section
== DNS_SECTION_ANSWER
||
1311 section
== DNS_SECTION_AUTHORITY
))
1312 client
->query
.attributes
&= ~NS_QUERYATTR_SECURE
;
1314 * Note: we only add SIGs if we've added the type they cover, so
1315 * we do not need to check if the SIG rdataset is already in the
1318 query_addrdataset(client
, mname
, rdataset
);
1320 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
)) {
1322 * We have a signature. Add it to the response.
1324 ISC_LIST_APPEND(mname
->list
, sigrdataset
, link
);
1325 *sigrdatasetp
= NULL
;
1327 CTRACE("query_addrrset: done");
1330 static inline isc_result_t
1331 query_addsoa(ns_client_t
*client
, dns_db_t
*db
, isc_boolean_t zero_ttl
) {
1332 dns_name_t
*name
, *fname
;
1334 isc_result_t result
, eresult
;
1335 dns_fixedname_t foundname
;
1336 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
1337 dns_rdataset_t
**sigrdatasetp
= NULL
;
1339 CTRACE("query_addsoa");
1343 eresult
= ISC_R_SUCCESS
;
1347 dns_fixedname_init(&foundname
);
1348 fname
= dns_fixedname_name(&foundname
);
1351 * Get resources and make 'name' be the database origin.
1353 result
= dns_message_gettempname(client
->message
, &name
);
1354 if (result
!= ISC_R_SUCCESS
)
1356 dns_name_init(name
, NULL
);
1357 dns_name_clone(dns_db_origin(db
), name
);
1358 rdataset
= query_newrdataset(client
);
1359 if (rdataset
== NULL
) {
1360 eresult
= DNS_R_SERVFAIL
;
1363 if (WANTDNSSEC(client
)) {
1364 sigrdataset
= query_newrdataset(client
);
1365 if (sigrdataset
== NULL
) {
1366 eresult
= DNS_R_SERVFAIL
;
1374 result
= dns_db_find(db
, name
, NULL
, dns_rdatatype_soa
,
1375 client
->query
.dboptions
, 0, &node
,
1376 fname
, rdataset
, sigrdataset
);
1377 if (result
!= ISC_R_SUCCESS
) {
1379 * This is bad. We tried to get the SOA RR at the zone top
1380 * and it didn't work!
1382 eresult
= DNS_R_SERVFAIL
;
1385 * Extract the SOA MINIMUM.
1387 dns_rdata_soa_t soa
;
1388 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1389 result
= dns_rdataset_first(rdataset
);
1390 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1391 dns_rdataset_current(rdataset
, &rdata
);
1392 result
= dns_rdata_tostruct(&rdata
, &soa
, NULL
);
1393 if (result
!= ISC_R_SUCCESS
)
1398 if (sigrdataset
!= NULL
)
1399 sigrdataset
->ttl
= 0;
1403 * Add the SOA and its SIG to the response, with the
1404 * TTLs adjusted per RFC2308 section 3.
1406 if (rdataset
->ttl
> soa
.minimum
)
1407 rdataset
->ttl
= soa
.minimum
;
1408 if (sigrdataset
!= NULL
&& sigrdataset
->ttl
> soa
.minimum
)
1409 sigrdataset
->ttl
= soa
.minimum
;
1411 if (sigrdataset
!= NULL
)
1412 sigrdatasetp
= &sigrdataset
;
1414 sigrdatasetp
= NULL
;
1415 query_addrrset(client
, &name
, &rdataset
, sigrdatasetp
, NULL
,
1416 DNS_SECTION_AUTHORITY
);
1420 query_putrdataset(client
, &rdataset
);
1421 if (sigrdataset
!= NULL
)
1422 query_putrdataset(client
, &sigrdataset
);
1424 query_releasename(client
, &name
);
1426 dns_db_detachnode(db
, &node
);
1431 static inline isc_result_t
1432 query_addns(ns_client_t
*client
, dns_db_t
*db
) {
1433 dns_name_t
*name
, *fname
;
1435 isc_result_t result
, eresult
;
1436 dns_fixedname_t foundname
;
1437 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
1438 dns_rdataset_t
**sigrdatasetp
= NULL
;
1440 CTRACE("query_addns");
1444 eresult
= ISC_R_SUCCESS
;
1448 dns_fixedname_init(&foundname
);
1449 fname
= dns_fixedname_name(&foundname
);
1452 * Get resources and make 'name' be the database origin.
1454 result
= dns_message_gettempname(client
->message
, &name
);
1455 if (result
!= ISC_R_SUCCESS
) {
1456 CTRACE("query_addns: dns_message_gettempname failed: done");
1459 dns_name_init(name
, NULL
);
1460 dns_name_clone(dns_db_origin(db
), name
);
1461 rdataset
= query_newrdataset(client
);
1462 if (rdataset
== NULL
) {
1463 CTRACE("query_addns: query_newrdataset failed");
1464 eresult
= DNS_R_SERVFAIL
;
1467 if (WANTDNSSEC(client
)) {
1468 sigrdataset
= query_newrdataset(client
);
1469 if (sigrdataset
== NULL
) {
1470 CTRACE("query_addns: query_newrdataset failed");
1471 eresult
= DNS_R_SERVFAIL
;
1477 * Find the NS rdataset.
1479 CTRACE("query_addns: calling dns_db_find");
1480 result
= dns_db_find(db
, name
, NULL
, dns_rdatatype_ns
,
1481 client
->query
.dboptions
, 0, &node
,
1482 fname
, rdataset
, sigrdataset
);
1483 CTRACE("query_addns: dns_db_find complete");
1484 if (result
!= ISC_R_SUCCESS
) {
1485 CTRACE("query_addns: dns_db_find failed");
1487 * This is bad. We tried to get the NS rdataset at the zone
1488 * top and it didn't work!
1490 eresult
= DNS_R_SERVFAIL
;
1492 if (sigrdataset
!= NULL
)
1493 sigrdatasetp
= &sigrdataset
;
1495 sigrdatasetp
= NULL
;
1496 query_addrrset(client
, &name
, &rdataset
, sigrdatasetp
, NULL
,
1497 DNS_SECTION_AUTHORITY
);
1501 CTRACE("query_addns: cleanup");
1502 query_putrdataset(client
, &rdataset
);
1503 if (sigrdataset
!= NULL
)
1504 query_putrdataset(client
, &sigrdataset
);
1506 query_releasename(client
, &name
);
1508 dns_db_detachnode(db
, &node
);
1510 CTRACE("query_addns: done");
1514 static inline isc_result_t
1515 query_addcnamelike(ns_client_t
*client
, dns_name_t
*qname
, dns_name_t
*tname
,
1516 dns_trust_t trust
, dns_name_t
**anamep
, dns_rdatatype_t type
)
1518 dns_rdataset_t
*rdataset
;
1519 dns_rdatalist_t
*rdatalist
;
1521 isc_result_t result
;
1525 * We assume the name data referred to by tname won't go away.
1528 REQUIRE(anamep
!= NULL
);
1531 result
= dns_message_gettemprdatalist(client
->message
, &rdatalist
);
1532 if (result
!= ISC_R_SUCCESS
)
1535 result
= dns_message_gettemprdata(client
->message
, &rdata
);
1536 if (result
!= ISC_R_SUCCESS
)
1539 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
1540 if (result
!= ISC_R_SUCCESS
)
1542 dns_rdataset_init(rdataset
);
1543 result
= dns_name_dup(qname
, client
->mctx
, *anamep
);
1544 if (result
!= ISC_R_SUCCESS
) {
1545 dns_message_puttemprdataset(client
->message
, &rdataset
);
1549 rdatalist
->type
= type
;
1550 rdatalist
->covers
= 0;
1551 rdatalist
->rdclass
= client
->message
->rdclass
;
1554 dns_name_toregion(tname
, &r
);
1555 rdata
->data
= r
.base
;
1556 rdata
->length
= r
.length
;
1557 rdata
->rdclass
= client
->message
->rdclass
;
1560 ISC_LIST_INIT(rdatalist
->rdata
);
1561 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1562 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
, rdataset
)
1564 rdataset
->trust
= trust
;
1566 query_addrrset(client
, anamep
, &rdataset
, NULL
, NULL
,
1567 DNS_SECTION_ANSWER
);
1569 if (rdataset
!= NULL
) {
1570 if (dns_rdataset_isassociated(rdataset
))
1571 dns_rdataset_disassociate(rdataset
);
1572 dns_message_puttemprdataset(client
->message
, &rdataset
);
1575 return (ISC_R_SUCCESS
);
1579 query_addbestns(ns_client_t
*client
) {
1582 dns_name_t
*fname
, *zfname
;
1583 dns_rdataset_t
*rdataset
, *sigrdataset
, *zrdataset
, *zsigrdataset
;
1584 isc_boolean_t is_zone
, use_zone
;
1586 isc_result_t result
;
1587 dns_dbversion_t
*version
;
1591 CTRACE("query_addbestns");
1597 zsigrdataset
= NULL
;
1603 is_zone
= ISC_FALSE
;
1604 use_zone
= ISC_FALSE
;
1607 * Find the right database.
1609 result
= query_getdb(client
, client
->query
.qname
, dns_rdatatype_ns
, 0,
1610 &zone
, &db
, &version
, &is_zone
);
1611 if (result
!= ISC_R_SUCCESS
)
1616 * We'll need some resources...
1618 dbuf
= query_getnamebuf(client
);
1621 fname
= query_newname(client
, dbuf
, &b
);
1622 rdataset
= query_newrdataset(client
);
1623 if (fname
== NULL
|| rdataset
== NULL
)
1625 if (WANTDNSSEC(client
)) {
1626 sigrdataset
= query_newrdataset(client
);
1627 if (sigrdataset
== NULL
)
1632 * Now look for the zonecut.
1635 result
= dns_db_find(db
, client
->query
.qname
, version
,
1636 dns_rdatatype_ns
, client
->query
.dboptions
,
1637 client
->now
, &node
, fname
,
1638 rdataset
, sigrdataset
);
1639 if (result
!= DNS_R_DELEGATION
)
1641 if (USECACHE(client
)) {
1642 query_keepname(client
, fname
, dbuf
);
1646 zrdataset
= rdataset
;
1648 zsigrdataset
= sigrdataset
;
1650 dns_db_detachnode(db
, &node
);
1653 dns_db_attach(client
->view
->cachedb
, &db
);
1654 is_zone
= ISC_FALSE
;
1658 result
= dns_db_findzonecut(db
, client
->query
.qname
,
1659 client
->query
.dboptions
,
1660 client
->now
, &node
, fname
,
1661 rdataset
, sigrdataset
);
1662 if (result
== ISC_R_SUCCESS
) {
1663 if (zfname
!= NULL
&&
1664 !dns_name_issubdomain(fname
, zfname
)) {
1666 * We found a zonecut in the cache, but our
1667 * zone delegation is better.
1669 use_zone
= ISC_TRUE
;
1671 } else if (result
== ISC_R_NOTFOUND
&& zfname
!= NULL
) {
1673 * We didn't find anything in the cache, but we
1674 * have a zone delegation, so use it.
1676 use_zone
= ISC_TRUE
;
1682 query_releasename(client
, &fname
);
1686 * We've already done query_keepname() on
1687 * zfname, so we must set dbuf to NULL to
1688 * prevent query_addrrset() from trying to
1689 * call query_keepname() again.
1692 query_putrdataset(client
, &rdataset
);
1693 if (sigrdataset
!= NULL
)
1694 query_putrdataset(client
, &sigrdataset
);
1695 rdataset
= zrdataset
;
1697 sigrdataset
= zsigrdataset
;
1698 zsigrdataset
= NULL
;
1701 if ((client
->query
.dboptions
& DNS_DBFIND_PENDINGOK
) == 0 &&
1702 (rdataset
->trust
== dns_trust_pending
||
1703 (sigrdataset
!= NULL
&& sigrdataset
->trust
== dns_trust_pending
)))
1706 if (WANTDNSSEC(client
) && SECURE(client
) &&
1707 (rdataset
->trust
== dns_trust_glue
||
1708 (sigrdataset
!= NULL
&& sigrdataset
->trust
== dns_trust_glue
)))
1711 query_addrrset(client
, &fname
, &rdataset
, &sigrdataset
, dbuf
,
1712 DNS_SECTION_AUTHORITY
);
1715 if (rdataset
!= NULL
)
1716 query_putrdataset(client
, &rdataset
);
1717 if (sigrdataset
!= NULL
)
1718 query_putrdataset(client
, &sigrdataset
);
1720 query_releasename(client
, &fname
);
1722 dns_db_detachnode(db
, &node
);
1726 dns_zone_detach(&zone
);
1728 query_putrdataset(client
, &zrdataset
);
1729 if (zsigrdataset
!= NULL
)
1730 query_putrdataset(client
, &zsigrdataset
);
1732 query_releasename(client
, &zfname
);
1733 dns_db_detach(&zdb
);
1738 query_addds(ns_client_t
*client
, dns_db_t
*db
, dns_dbnode_t
*node
) {
1740 dns_rdataset_t
*rdataset
, *sigrdataset
;
1741 isc_result_t result
;
1743 CTRACE("query_addds");
1749 * We'll need some resources...
1751 rdataset
= query_newrdataset(client
);
1752 sigrdataset
= query_newrdataset(client
);
1753 if (rdataset
== NULL
|| sigrdataset
== NULL
)
1757 * Look for the DS record, which may or may not be present.
1759 result
= dns_db_findrdataset(db
, node
, NULL
, dns_rdatatype_ds
, 0,
1760 client
->now
, rdataset
, sigrdataset
);
1762 * If we didn't find it, look for an NSEC. */
1763 if (result
== ISC_R_NOTFOUND
)
1764 result
= dns_db_findrdataset(db
, node
, NULL
,
1765 dns_rdatatype_nsec
, 0, client
->now
,
1766 rdataset
, sigrdataset
);
1767 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOTFOUND
)
1769 if (!dns_rdataset_isassociated(rdataset
) ||
1770 !dns_rdataset_isassociated(sigrdataset
))
1774 * We've already added the NS record, so if the name's not there,
1775 * we have other problems. Use this name rather than calling
1778 result
= dns_message_firstname(client
->message
, DNS_SECTION_AUTHORITY
);
1779 if (result
!= ISC_R_SUCCESS
)
1783 dns_message_currentname(client
->message
, DNS_SECTION_AUTHORITY
,
1785 result
= dns_message_findtype(rname
, dns_rdatatype_ns
, 0, NULL
);
1786 if (result
!= ISC_R_SUCCESS
)
1789 ISC_LIST_APPEND(rname
->list
, rdataset
, link
);
1790 ISC_LIST_APPEND(rname
->list
, sigrdataset
, link
);
1795 if (rdataset
!= NULL
)
1796 query_putrdataset(client
, &rdataset
);
1797 if (sigrdataset
!= NULL
)
1798 query_putrdataset(client
, &sigrdataset
);
1802 query_addwildcardproof(ns_client_t
*client
, dns_db_t
*db
,
1803 dns_name_t
*name
, isc_boolean_t ispositive
)
1805 isc_buffer_t
*dbuf
, b
;
1807 dns_rdataset_t
*rdataset
, *sigrdataset
;
1808 dns_fixedname_t wfixed
;
1811 unsigned int options
;
1812 unsigned int olabels
, nlabels
;
1813 isc_result_t result
;
1814 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1815 dns_rdata_nsec_t nsec
;
1816 isc_boolean_t have_wname
;
1819 CTRACE("query_addwildcardproof");
1826 * Get the NOQNAME proof then if !ispositve
1827 * get the NOWILDCARD proof.
1829 * DNS_DBFIND_NOWILD finds the NSEC records that covers the
1830 * name ignoring any wildcard. From the owner and next names
1831 * of this record you can compute which wildcard (if it exists)
1832 * will match by finding the longest common suffix of the
1833 * owner name and next names with the qname and prefixing that
1834 * with the wildcard label.
1839 * example NSEC b.example
1841 * b.example NSEC a.d.example
1843 * a.d.example NSEC g.f.example
1845 * g.f.example NSEC z.i.example
1847 * z.i.example NSEC example
1850 * a.example -> example NSEC b.example
1851 * owner common example
1852 * next common example
1854 * d.b.example -> b.example NSEC a.d.example
1855 * owner common b.example
1856 * next common example
1858 * a.f.example -> a.d.example NSEC g.f.example
1859 * owner common example
1860 * next common f.example
1862 * j.example -> z.i.example NSEC example
1863 * owner common example
1864 * next common example
1867 options
= client
->query
.dboptions
| DNS_DBFIND_NOWILD
;
1868 dns_fixedname_init(&wfixed
);
1869 wname
= dns_fixedname_name(&wfixed
);
1871 have_wname
= ISC_FALSE
;
1873 * We'll need some resources...
1875 dbuf
= query_getnamebuf(client
);
1878 fname
= query_newname(client
, dbuf
, &b
);
1879 rdataset
= query_newrdataset(client
);
1880 sigrdataset
= query_newrdataset(client
);
1881 if (fname
== NULL
|| rdataset
== NULL
|| sigrdataset
== NULL
)
1884 result
= dns_db_find(db
, name
, NULL
, dns_rdatatype_nsec
, options
,
1885 0, &node
, fname
, rdataset
, sigrdataset
);
1887 dns_db_detachnode(db
, &node
);
1888 if (result
== DNS_R_NXDOMAIN
) {
1890 result
= dns_rdataset_first(rdataset
);
1891 if (result
== ISC_R_SUCCESS
) {
1892 dns_rdataset_current(rdataset
, &rdata
);
1893 result
= dns_rdata_tostruct(&rdata
, &nsec
, NULL
);
1895 if (result
== ISC_R_SUCCESS
) {
1896 (void)dns_name_fullcompare(name
, fname
, &order
,
1898 (void)dns_name_fullcompare(name
, &nsec
.next
, &order
,
1900 if (olabels
> nlabels
)
1901 dns_name_split(name
, olabels
, NULL
, wname
);
1903 dns_name_split(name
, nlabels
, NULL
, wname
);
1904 result
= dns_name_concatenate(dns_wildcardname
,
1905 wname
, wname
, NULL
);
1906 if (result
== ISC_R_SUCCESS
)
1907 have_wname
= ISC_TRUE
;
1908 dns_rdata_freestruct(&nsec
);
1910 query_addrrset(client
, &fname
, &rdataset
, &sigrdataset
,
1911 dbuf
, DNS_SECTION_AUTHORITY
);
1913 if (rdataset
!= NULL
)
1914 query_putrdataset(client
, &rdataset
);
1915 if (sigrdataset
!= NULL
)
1916 query_putrdataset(client
, &sigrdataset
);
1918 query_releasename(client
, &fname
);
1920 ispositive
= ISC_TRUE
; /* prevent loop */
1921 if (!dns_name_equal(name
, wname
)) {
1927 if (rdataset
!= NULL
)
1928 query_putrdataset(client
, &rdataset
);
1929 if (sigrdataset
!= NULL
)
1930 query_putrdataset(client
, &sigrdataset
);
1932 query_releasename(client
, &fname
);
1936 query_addnxrrsetnsec(ns_client_t
*client
, dns_db_t
*db
, dns_name_t
**namep
,
1937 dns_rdataset_t
**rdatasetp
, dns_rdataset_t
**sigrdatasetp
)
1940 dns_rdataset_t
*sigrdataset
;
1941 dns_rdata_t sigrdata
;
1942 dns_rdata_rrsig_t sig
;
1943 unsigned int labels
;
1944 isc_buffer_t
*dbuf
, b
;
1946 isc_result_t result
;
1949 if ((name
->attributes
& DNS_NAMEATTR_WILDCARD
) == 0) {
1950 query_addrrset(client
, namep
, rdatasetp
, sigrdatasetp
,
1951 NULL
, DNS_SECTION_AUTHORITY
);
1955 if (sigrdatasetp
== NULL
)
1957 sigrdataset
= *sigrdatasetp
;
1958 if (sigrdataset
== NULL
|| !dns_rdataset_isassociated(sigrdataset
))
1960 result
= dns_rdataset_first(sigrdataset
);
1961 if (result
!= ISC_R_SUCCESS
)
1963 dns_rdata_init(&sigrdata
);
1964 dns_rdataset_current(sigrdataset
, &sigrdata
);
1965 result
= dns_rdata_tostruct(&sigrdata
, &sig
, NULL
);
1966 if (result
!= ISC_R_SUCCESS
)
1969 labels
= dns_name_countlabels(name
);
1970 if ((unsigned int)sig
.labels
+ 1 >= labels
)
1974 query_addwildcardproof(client
, db
,
1975 client
->query
.qname
,
1979 * We'll need some resources...
1981 dbuf
= query_getnamebuf(client
);
1984 fname
= query_newname(client
, dbuf
, &b
);
1987 dns_name_split(name
, sig
.labels
+ 1, NULL
, fname
);
1988 /* This will succeed, since we've stripped labels. */
1989 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname
, fname
, fname
,
1990 NULL
) == ISC_R_SUCCESS
);
1991 query_addrrset(client
, &fname
, rdatasetp
, sigrdatasetp
,
1992 dbuf
, DNS_SECTION_AUTHORITY
);
1996 query_resume(isc_task_t
*task
, isc_event_t
*event
) {
1997 dns_fetchevent_t
*devent
= (dns_fetchevent_t
*)event
;
1998 ns_client_t
*client
;
1999 isc_boolean_t fetch_cancelled
, client_shuttingdown
;
2002 * Resume a query after recursion.
2007 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
2008 client
= devent
->ev_arg
;
2009 REQUIRE(NS_CLIENT_VALID(client
));
2010 REQUIRE(task
== client
->task
);
2011 REQUIRE(RECURSING(client
));
2013 LOCK(&client
->query
.fetchlock
);
2014 if (client
->query
.fetch
!= NULL
) {
2016 * This is the fetch we've been waiting for.
2018 INSIST(devent
->fetch
== client
->query
.fetch
);
2019 client
->query
.fetch
= NULL
;
2020 fetch_cancelled
= ISC_FALSE
;
2022 * Update client->now.
2024 isc_stdtime_get(&client
->now
);
2027 * This is a fetch completion event for a cancelled fetch.
2028 * Clean up and don't resume the find.
2030 fetch_cancelled
= ISC_TRUE
;
2032 UNLOCK(&client
->query
.fetchlock
);
2033 INSIST(client
->query
.fetch
== NULL
);
2035 client
->query
.attributes
&= ~NS_QUERYATTR_RECURSING
;
2036 dns_resolver_destroyfetch(&devent
->fetch
);
2039 * If this client is shutting down, or this transaction
2040 * has timed out, do not resume the find.
2042 client_shuttingdown
= ns_client_shuttingdown(client
);
2043 if (fetch_cancelled
|| client_shuttingdown
) {
2044 if (devent
->node
!= NULL
)
2045 dns_db_detachnode(devent
->db
, &devent
->node
);
2046 if (devent
->db
!= NULL
)
2047 dns_db_detach(&devent
->db
);
2048 query_putrdataset(client
, &devent
->rdataset
);
2049 if (devent
->sigrdataset
!= NULL
)
2050 query_putrdataset(client
, &devent
->sigrdataset
);
2051 isc_event_free(&event
);
2052 if (fetch_cancelled
)
2053 query_error(client
, DNS_R_SERVFAIL
);
2055 query_next(client
, ISC_R_CANCELED
);
2057 * This may destroy the client.
2059 ns_client_detach(&client
);
2061 query_find(client
, devent
, 0);
2066 query_recurse(ns_client_t
*client
, dns_rdatatype_t qtype
, dns_name_t
*qdomain
,
2067 dns_rdataset_t
*nameservers
)
2069 isc_result_t result
;
2070 dns_rdataset_t
*rdataset
, *sigrdataset
;
2072 inc_stats(client
, dns_statscounter_recursion
);
2075 * We are about to recurse, which means that this client will
2076 * be unavailable for serving new requests for an indeterminate
2077 * amount of time. If this client is currently responsible
2078 * for handling incoming queries, set up a new client
2079 * object to handle them while we are waiting for a
2080 * response. There is no need to replace TCP clients
2081 * because those have already been replaced when the
2082 * connection was accepted (if allowed by the TCP quota).
2084 if (client
->recursionquota
== NULL
) {
2085 result
= isc_quota_attach(&ns_g_server
->recursionquota
,
2086 &client
->recursionquota
);
2087 if (result
== ISC_R_SOFTQUOTA
) {
2088 static isc_stdtime_t last
= 0;
2090 isc_stdtime_get(&now
);
2093 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2096 "recursive-clients soft limit "
2097 "exceeded, aborting oldest query");
2099 ns_client_killoldestquery(client
);
2100 result
= ISC_R_SUCCESS
;
2101 } else if (result
== ISC_R_QUOTA
) {
2102 static isc_stdtime_t last
= 0;
2104 isc_stdtime_get(&now
);
2107 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2110 "no more recursive clients: %s",
2111 isc_result_totext(result
));
2113 ns_client_killoldestquery(client
);
2115 if (result
== ISC_R_SUCCESS
&& !client
->mortal
&&
2116 (client
->attributes
& NS_CLIENTATTR_TCP
) == 0) {
2117 result
= ns_client_replace(client
);
2118 if (result
!= ISC_R_SUCCESS
) {
2119 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2122 "ns_client_replace() failed: %s",
2123 isc_result_totext(result
));
2124 isc_quota_detach(&client
->recursionquota
);
2127 if (result
!= ISC_R_SUCCESS
)
2129 ns_client_recursing(client
);
2133 * Invoke the resolver.
2135 REQUIRE(nameservers
== NULL
|| nameservers
->type
== dns_rdatatype_ns
);
2136 REQUIRE(client
->query
.fetch
== NULL
);
2138 rdataset
= query_newrdataset(client
);
2139 if (rdataset
== NULL
)
2140 return (ISC_R_NOMEMORY
);
2141 if (WANTDNSSEC(client
)) {
2142 sigrdataset
= query_newrdataset(client
);
2143 if (sigrdataset
== NULL
) {
2144 query_putrdataset(client
, &rdataset
);
2145 return (ISC_R_NOMEMORY
);
2150 if (client
->query
.timerset
== ISC_FALSE
)
2151 ns_client_settimeout(client
, 60);
2152 result
= dns_resolver_createfetch(client
->view
->resolver
,
2153 client
->query
.qname
,
2154 qtype
, qdomain
, nameservers
,
2155 NULL
, client
->query
.fetchoptions
,
2157 query_resume
, client
,
2158 rdataset
, sigrdataset
,
2159 &client
->query
.fetch
);
2161 if (result
== ISC_R_SUCCESS
) {
2163 * Record that we're waiting for an event. A client which
2164 * is shutting down will not be destroyed until all the
2165 * events have been received.
2168 query_putrdataset(client
, &rdataset
);
2169 if (sigrdataset
!= NULL
)
2170 query_putrdataset(client
, &sigrdataset
);
2176 #define MAX_RESTARTS 16
2178 #define QUERY_ERROR(r) \
2181 want_restart = ISC_FALSE; \
2185 * Extract a network address from the RDATA of an A or AAAA
2190 * ISC_R_NOTIMPLEMENTED The rdata is not a known address type.
2193 rdata_tonetaddr(const dns_rdata_t
*rdata
, isc_netaddr_t
*netaddr
) {
2195 struct in6_addr in6a
;
2197 switch (rdata
->type
) {
2198 case dns_rdatatype_a
:
2199 INSIST(rdata
->length
== 4);
2200 memcpy(&ina
.s_addr
, rdata
->data
, 4);
2201 isc_netaddr_fromin(netaddr
, &ina
);
2202 return (ISC_R_SUCCESS
);
2203 case dns_rdatatype_aaaa
:
2204 INSIST(rdata
->length
== 16);
2205 memcpy(in6a
.s6_addr
, rdata
->data
, 16);
2206 isc_netaddr_fromin6(netaddr
, &in6a
);
2207 return (ISC_R_SUCCESS
);
2209 return (ISC_R_NOTIMPLEMENTED
);
2214 * Find the sort order of 'rdata' in the topology-like
2215 * ACL forming the second element in a 2-element top-level
2216 * sortlist statement.
2219 query_sortlist_order_2element(const dns_rdata_t
*rdata
, const void *arg
) {
2220 isc_netaddr_t netaddr
;
2222 if (rdata_tonetaddr(rdata
, &netaddr
) != ISC_R_SUCCESS
)
2224 return (ns_sortlist_addrorder2(&netaddr
, arg
));
2228 * Find the sort order of 'rdata' in the matching element
2229 * of a 1-element top-level sortlist statement.
2232 query_sortlist_order_1element(const dns_rdata_t
*rdata
, const void *arg
) {
2233 isc_netaddr_t netaddr
;
2235 if (rdata_tonetaddr(rdata
, &netaddr
) != ISC_R_SUCCESS
)
2237 return (ns_sortlist_addrorder1(&netaddr
, arg
));
2241 * Find the sortlist statement that applies to 'client' and set up
2242 * the sortlist info in in client->message appropriately.
2245 setup_query_sortlist(ns_client_t
*client
) {
2246 isc_netaddr_t netaddr
;
2247 dns_rdatasetorderfunc_t order
= NULL
;
2248 const void *order_arg
= NULL
;
2250 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
2251 switch (ns_sortlist_setup(client
->view
->sortlist
,
2252 &netaddr
, &order_arg
)) {
2253 case NS_SORTLISTTYPE_1ELEMENT
:
2254 order
= query_sortlist_order_1element
;
2256 case NS_SORTLISTTYPE_2ELEMENT
:
2257 order
= query_sortlist_order_2element
;
2259 case NS_SORTLISTTYPE_NONE
:
2266 dns_message_setsortorder(client
->message
, order
, order_arg
);
2270 query_addnoqnameproof(ns_client_t
*client
, dns_rdataset_t
*rdataset
) {
2271 isc_buffer_t
*dbuf
, b
;
2273 dns_rdataset_t
*nsec
, *nsecsig
;
2274 isc_result_t result
= ISC_R_NOMEMORY
;
2276 CTRACE("query_addnoqnameproof");
2282 dbuf
= query_getnamebuf(client
);
2285 fname
= query_newname(client
, dbuf
, &b
);
2286 nsec
= query_newrdataset(client
);
2287 nsecsig
= query_newrdataset(client
);
2288 if (fname
== NULL
|| nsec
== NULL
|| nsecsig
== NULL
)
2291 result
= dns_rdataset_getnoqname(rdataset
, fname
, nsec
, nsecsig
);
2292 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2294 query_addrrset(client
, &fname
, &nsec
, &nsecsig
, dbuf
,
2295 DNS_SECTION_AUTHORITY
);
2299 query_putrdataset(client
, &nsec
);
2300 if (nsecsig
!= NULL
)
2301 query_putrdataset(client
, &nsecsig
);
2303 query_releasename(client
, &fname
);
2307 answer_in_glue(ns_client_t
*client
, dns_rdatatype_t qtype
) {
2310 dns_section_t section
= DNS_SECTION_ADDITIONAL
;
2311 dns_rdataset_t
*rdataset
= NULL
;
2313 msg
= client
->message
;
2314 for (name
= ISC_LIST_HEAD(msg
->sections
[section
]);
2316 name
= ISC_LIST_NEXT(name
, link
))
2317 if (dns_name_equal(name
, client
->query
.qname
)) {
2318 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2320 rdataset
= ISC_LIST_NEXT(rdataset
, link
))
2321 if (rdataset
->type
== qtype
)
2325 if (rdataset
!= NULL
) {
2326 ISC_LIST_UNLINK(msg
->sections
[section
], name
, link
);
2327 ISC_LIST_PREPEND(msg
->sections
[section
], name
, link
);
2328 ISC_LIST_UNLINK(name
->list
, rdataset
, link
);
2329 ISC_LIST_PREPEND(name
->list
, rdataset
, link
);
2330 rdataset
->attributes
|= DNS_RDATASETATTR_REQUIREDGLUE
;
2335 * Do the bulk of query processing for the current query of 'client'.
2336 * If 'event' is non-NULL, we are returning from recursion and 'qtype'
2337 * is ignored. Otherwise, 'qtype' is the query type.
2340 query_find(ns_client_t
*client
, dns_fetchevent_t
*event
, dns_rdatatype_t qtype
)
2344 dns_rdatatype_t type
;
2345 dns_name_t
*fname
, *zfname
, *tname
, *prefix
;
2346 dns_rdataset_t
*rdataset
, *trdataset
;
2347 dns_rdataset_t
*sigrdataset
, *zrdataset
, *zsigrdataset
;
2348 dns_rdataset_t
**sigrdatasetp
;
2349 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2350 dns_rdatasetiter_t
*rdsiter
;
2351 isc_boolean_t want_restart
, authoritative
, is_zone
, need_wildcardproof
;
2352 unsigned int n
, nlabels
;
2353 dns_namereln_t namereln
;
2357 isc_result_t result
, eresult
;
2358 dns_fixedname_t fixed
;
2359 dns_fixedname_t wildcardname
;
2360 dns_dbversion_t
*version
;
2362 dns_rdata_cname_t cname
;
2363 dns_rdata_dname_t dname
;
2364 unsigned int options
;
2365 isc_boolean_t empty_wild
;
2366 dns_rdataset_t
*noqname
;
2368 CTRACE("query_find");
2371 * One-time initialization.
2373 * It's especially important to initialize anything that the cleanup
2374 * code might cleanup.
2377 eresult
= ISC_R_SUCCESS
;
2383 zsigrdataset
= NULL
;
2389 need_wildcardproof
= ISC_FALSE
;
2390 empty_wild
= ISC_FALSE
;
2393 if (event
!= NULL
) {
2395 * We're returning from recursion. Restore the query context
2399 want_restart
= ISC_FALSE
;
2400 authoritative
= ISC_FALSE
;
2401 is_zone
= ISC_FALSE
;
2403 qtype
= event
->qtype
;
2404 if (qtype
== dns_rdatatype_rrsig
|| qtype
== dns_rdatatype_sig
)
2405 type
= dns_rdatatype_any
;
2410 rdataset
= event
->rdataset
;
2411 sigrdataset
= event
->sigrdataset
;
2414 * We'll need some resources...
2416 dbuf
= query_getnamebuf(client
);
2418 QUERY_ERROR(DNS_R_SERVFAIL
);
2421 fname
= query_newname(client
, dbuf
, &b
);
2422 if (fname
== NULL
) {
2423 QUERY_ERROR(DNS_R_SERVFAIL
);
2426 tname
= dns_fixedname_name(&event
->foundname
);
2427 result
= dns_name_copy(tname
, fname
, NULL
);
2428 if (result
!= ISC_R_SUCCESS
) {
2429 QUERY_ERROR(DNS_R_SERVFAIL
);
2433 result
= event
->result
;
2439 * Not returning from recursion.
2443 * If it's a SIG query, we'll iterate the node.
2445 if (qtype
== dns_rdatatype_rrsig
|| qtype
== dns_rdatatype_sig
)
2446 type
= dns_rdatatype_any
;
2451 CTRACE("query_find: restart");
2452 want_restart
= ISC_FALSE
;
2453 authoritative
= ISC_FALSE
;
2455 need_wildcardproof
= ISC_FALSE
;
2457 if (client
->view
->checknames
&&
2458 !dns_rdata_checkowner(client
->query
.qname
,
2459 client
->message
->rdclass
,
2460 qtype
, ISC_FALSE
)) {
2461 char namebuf
[DNS_NAME_FORMATSIZE
];
2462 char typename
[DNS_RDATATYPE_FORMATSIZE
];
2463 char classname
[DNS_RDATACLASS_FORMATSIZE
];
2465 dns_name_format(client
->query
.qname
, namebuf
, sizeof(namebuf
));
2466 dns_rdatatype_format(qtype
, typename
, sizeof(typename
));
2467 dns_rdataclass_format(client
->message
->rdclass
, classname
,
2469 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2470 NS_LOGMODULE_QUERY
, ISC_LOG_ERROR
,
2471 "check-names failure %s/%s/%s", namebuf
,
2472 typename
, classname
);
2473 QUERY_ERROR(DNS_R_REFUSED
);
2478 * First we must find the right database.
2480 options
&= DNS_GETDB_NOLOG
; /* Preserve DNS_GETDB_NOLOG. */
2481 if (dns_rdatatype_atparent(qtype
) &&
2482 !dns_name_equal(client
->query
.qname
, dns_rootname
))
2483 options
|= DNS_GETDB_NOEXACT
;
2484 result
= query_getdb(client
, client
->query
.qname
, qtype
, options
,
2485 &zone
, &db
, &version
, &is_zone
);
2486 if ((result
!= ISC_R_SUCCESS
|| !is_zone
) && !RECURSIONOK(client
) &&
2487 (options
& DNS_GETDB_NOEXACT
) != 0 && qtype
== dns_rdatatype_ds
) {
2489 * Look to see if we are authoritative for the
2490 * child zone if the query type is DS.
2492 dns_db_t
*tdb
= NULL
;
2493 dns_zone_t
*tzone
= NULL
;
2494 dns_dbversion_t
*tversion
= NULL
;
2495 isc_result_t tresult
;
2497 tresult
= query_getzonedb(client
, client
->query
.qname
, qtype
,
2498 DNS_GETDB_PARTIAL
, &tzone
, &tdb
,
2500 if (tresult
== ISC_R_SUCCESS
) {
2501 options
&= ~DNS_GETDB_NOEXACT
;
2502 query_putrdataset(client
, &rdataset
);
2506 dns_zone_detach(&zone
);
2511 result
= ISC_R_SUCCESS
;
2514 dns_db_detach(&tdb
);
2516 dns_zone_detach(&tzone
);
2519 if (result
!= ISC_R_SUCCESS
) {
2520 if (result
== DNS_R_REFUSED
) {
2521 if (!PARTIALANSWER(client
))
2522 QUERY_ERROR(DNS_R_REFUSED
);
2524 QUERY_ERROR(DNS_R_SERVFAIL
);
2529 authoritative
= ISC_TRUE
;
2531 if (event
== NULL
&& client
->query
.restarts
== 0) {
2533 dns_zone_attach(zone
, &client
->query
.authzone
);
2534 dns_db_attach(db
, &client
->query
.authdb
);
2536 client
->query
.authdbset
= ISC_TRUE
;
2540 CTRACE("query_find: db_find");
2542 * We'll need some resources...
2544 dbuf
= query_getnamebuf(client
);
2546 QUERY_ERROR(DNS_R_SERVFAIL
);
2549 fname
= query_newname(client
, dbuf
, &b
);
2550 rdataset
= query_newrdataset(client
);
2551 if (fname
== NULL
|| rdataset
== NULL
) {
2552 QUERY_ERROR(DNS_R_SERVFAIL
);
2555 if (WANTDNSSEC(client
)) {
2556 sigrdataset
= query_newrdataset(client
);
2557 if (sigrdataset
== NULL
) {
2558 QUERY_ERROR(DNS_R_SERVFAIL
);
2564 * Now look for an answer in the database.
2566 result
= dns_db_find(db
, client
->query
.qname
, version
, type
,
2567 client
->query
.dboptions
, client
->now
,
2568 &node
, fname
, rdataset
, sigrdataset
);
2571 CTRACE("query_find: resume");
2575 * This case is handled in the main line below.
2581 * These cases are handled in the main line below.
2584 authoritative
= ISC_FALSE
;
2586 case ISC_R_NOTFOUND
:
2588 * The cache doesn't even have the root NS. Get them from
2595 if (client
->view
->hints
== NULL
) {
2596 /* We have no hints. */
2597 result
= ISC_R_FAILURE
;
2599 dns_db_attach(client
->view
->hints
, &db
);
2600 result
= dns_db_find(db
, dns_rootname
,
2601 NULL
, dns_rdatatype_ns
,
2602 0, client
->now
, &node
, fname
,
2603 rdataset
, sigrdataset
);
2605 if (result
!= ISC_R_SUCCESS
) {
2607 * Nonsensical root hints may require cleanup.
2609 if (dns_rdataset_isassociated(rdataset
))
2610 dns_rdataset_disassociate(rdataset
);
2611 if (sigrdataset
!= NULL
&&
2612 dns_rdataset_isassociated(sigrdataset
))
2613 dns_rdataset_disassociate(sigrdataset
);
2615 dns_db_detachnode(db
, &node
);
2618 * We don't have any root server hints, but
2619 * we may have working forwarders, so try to
2622 if (RECURSIONOK(client
)) {
2623 result
= query_recurse(client
, qtype
,
2625 if (result
== ISC_R_SUCCESS
)
2626 client
->query
.attributes
|=
2627 NS_QUERYATTR_RECURSING
;
2629 /* Unable to recurse. */
2630 QUERY_ERROR(DNS_R_SERVFAIL
);
2634 /* Unable to give root server referral. */
2635 QUERY_ERROR(DNS_R_SERVFAIL
);
2640 * XXXRTH We should trigger root server priming here.
2643 case DNS_R_DELEGATION
:
2644 authoritative
= ISC_FALSE
;
2647 * Look to see if we are authoritative for the
2648 * child zone if the query type is DS.
2650 if (!RECURSIONOK(client
) &&
2651 (options
& DNS_GETDB_NOEXACT
) != 0 &&
2652 qtype
== dns_rdatatype_ds
) {
2653 dns_db_t
*tdb
= NULL
;
2654 dns_zone_t
*tzone
= NULL
;
2655 dns_dbversion_t
*tversion
= NULL
;
2656 result
= query_getzonedb(client
,
2657 client
->query
.qname
,
2662 if (result
== ISC_R_SUCCESS
) {
2663 options
&= ~DNS_GETDB_NOEXACT
;
2664 query_putrdataset(client
, &rdataset
);
2665 if (sigrdataset
!= NULL
)
2666 query_putrdataset(client
,
2669 query_releasename(client
,
2672 dns_db_detachnode(db
, &node
);
2676 dns_zone_detach(&zone
);
2680 authoritative
= ISC_TRUE
;
2684 dns_db_detach(&tdb
);
2686 dns_zone_detach(&tzone
);
2689 * We're authoritative for an ancestor of QNAME.
2691 if (!USECACHE(client
) || !RECURSIONOK(client
)) {
2693 * If we don't have a cache, this is the best
2696 * If the client is making a nonrecursive
2697 * query we always give out the authoritative
2698 * delegation. This way even if we get
2699 * junk in our cache, we won't fail in our
2700 * role as the delegating authority if another
2701 * nameserver asks us about a delegated
2704 * We enable the retrieval of glue for this
2705 * database by setting client->query.gluedb.
2707 client
->query
.gluedb
= db
;
2708 client
->query
.isreferral
= ISC_TRUE
;
2710 * We must ensure NOADDITIONAL is off,
2711 * because the generation of
2712 * additional data is required in
2715 client
->query
.attributes
&=
2716 ~NS_QUERYATTR_NOADDITIONAL
;
2717 if (sigrdataset
!= NULL
)
2718 sigrdatasetp
= &sigrdataset
;
2720 sigrdatasetp
= NULL
;
2721 query_addrrset(client
, &fname
,
2722 &rdataset
, sigrdatasetp
,
2723 dbuf
, DNS_SECTION_AUTHORITY
);
2724 client
->query
.gluedb
= NULL
;
2725 if (WANTDNSSEC(client
) && dns_db_issecure(db
))
2726 query_addds(client
, db
, node
);
2729 * We might have a better answer or delegation
2730 * in the cache. We'll remember the current
2731 * values of fname, rdataset, and sigrdataset.
2732 * We'll then go looking for QNAME in the
2733 * cache. If we find something better, we'll
2736 query_keepname(client
, fname
, dbuf
);
2740 zrdataset
= rdataset
;
2742 zsigrdataset
= sigrdataset
;
2744 dns_db_detachnode(db
, &node
);
2747 dns_db_attach(client
->view
->cachedb
, &db
);
2748 is_zone
= ISC_FALSE
;
2752 if (zfname
!= NULL
&&
2753 !dns_name_issubdomain(fname
, zfname
)) {
2755 * We've already got a delegation from
2756 * authoritative data, and it is better
2757 * than what we found in the cache. Use
2758 * it instead of the cache delegation.
2760 query_releasename(client
, &fname
);
2764 * We've already done query_keepname() on
2765 * zfname, so we must set dbuf to NULL to
2766 * prevent query_addrrset() from trying to
2767 * call query_keepname() again.
2770 query_putrdataset(client
, &rdataset
);
2771 if (sigrdataset
!= NULL
)
2772 query_putrdataset(client
,
2774 rdataset
= zrdataset
;
2776 sigrdataset
= zsigrdataset
;
2777 zsigrdataset
= NULL
;
2779 * We don't clean up zdb here because we
2780 * may still need it. It will get cleaned
2781 * up by the main cleanup code.
2785 if (RECURSIONOK(client
)) {
2789 if (dns_rdatatype_atparent(type
))
2790 result
= query_recurse(client
, qtype
,
2793 result
= query_recurse(client
, qtype
,
2795 if (result
== ISC_R_SUCCESS
)
2796 client
->query
.attributes
|=
2797 NS_QUERYATTR_RECURSING
;
2799 QUERY_ERROR(DNS_R_SERVFAIL
);
2802 * This is the best answer.
2804 client
->query
.attributes
|=
2805 NS_QUERYATTR_CACHEGLUEOK
;
2806 client
->query
.gluedb
= zdb
;
2807 client
->query
.isreferral
= ISC_TRUE
;
2809 * We must ensure NOADDITIONAL is off,
2810 * because the generation of
2811 * additional data is required in
2814 client
->query
.attributes
&=
2815 ~NS_QUERYATTR_NOADDITIONAL
;
2816 if (sigrdataset
!= NULL
)
2817 sigrdatasetp
= &sigrdataset
;
2819 sigrdatasetp
= NULL
;
2820 query_addrrset(client
, &fname
,
2821 &rdataset
, sigrdatasetp
,
2822 dbuf
, DNS_SECTION_AUTHORITY
);
2823 client
->query
.gluedb
= NULL
;
2824 client
->query
.attributes
&=
2825 ~NS_QUERYATTR_CACHEGLUEOK
;
2826 if (WANTDNSSEC(client
))
2827 query_addds(client
, db
, node
);
2831 case DNS_R_EMPTYNAME
:
2832 result
= DNS_R_NXRRSET
;
2836 if (dns_rdataset_isassociated(rdataset
)) {
2838 * If we've got a NSEC record, we need to save the
2839 * name now because we're going call query_addsoa()
2840 * below, and it needs to use the name buffer.
2842 query_keepname(client
, fname
, dbuf
);
2845 * We're not going to use fname, and need to release
2846 * our hold on the name buffer so query_addsoa()
2849 query_releasename(client
, &fname
);
2854 result
= query_addsoa(client
, db
, ISC_FALSE
);
2855 if (result
!= ISC_R_SUCCESS
) {
2856 QUERY_ERROR(result
);
2860 * Add NSEC record if we found one.
2862 if (WANTDNSSEC(client
)) {
2863 if (dns_rdataset_isassociated(rdataset
))
2864 query_addnxrrsetnsec(client
, db
, &fname
,
2865 &rdataset
, &sigrdataset
);
2868 case DNS_R_EMPTYWILD
:
2869 empty_wild
= ISC_TRUE
;
2871 case DNS_R_NXDOMAIN
:
2873 if (dns_rdataset_isassociated(rdataset
)) {
2875 * If we've got a NSEC record, we need to save the
2876 * name now because we're going call query_addsoa()
2877 * below, and it needs to use the name buffer.
2879 query_keepname(client
, fname
, dbuf
);
2882 * We're not going to use fname, and need to release
2883 * our hold on the name buffer so query_addsoa()
2886 query_releasename(client
, &fname
);
2889 * Add SOA. If the query was for a SOA record force the
2890 * ttl to zero so that it is possible for clients to find
2891 * the containing zone of an arbitrary name with a stub
2892 * resolver and not have it cached.
2894 if (qtype
== dns_rdatatype_soa
)
2895 result
= query_addsoa(client
, db
, ISC_TRUE
);
2897 result
= query_addsoa(client
, db
, ISC_FALSE
);
2898 if (result
!= ISC_R_SUCCESS
) {
2899 QUERY_ERROR(result
);
2903 * Add NSEC record if we found one.
2905 if (dns_rdataset_isassociated(rdataset
)) {
2906 if (WANTDNSSEC(client
)) {
2907 query_addrrset(client
, &fname
, &rdataset
,
2909 NULL
, DNS_SECTION_AUTHORITY
);
2910 query_addwildcardproof(client
, db
,
2911 client
->query
.qname
,
2916 * Set message rcode.
2919 client
->message
->rcode
= dns_rcode_noerror
;
2921 client
->message
->rcode
= dns_rcode_nxdomain
;
2923 case DNS_R_NCACHENXDOMAIN
:
2924 case DNS_R_NCACHENXRRSET
:
2926 authoritative
= ISC_FALSE
;
2928 * Set message rcode, if required.
2930 if (result
== DNS_R_NCACHENXDOMAIN
)
2931 client
->message
->rcode
= dns_rcode_nxdomain
;
2933 * We don't call query_addrrset() because we don't need any
2934 * of its extra features (and things would probably break!).
2936 query_keepname(client
, fname
, dbuf
);
2937 dns_message_addname(client
->message
, fname
,
2938 DNS_SECTION_AUTHORITY
);
2939 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
2945 * Keep a copy of the rdataset. We have to do this because
2946 * query_addrrset may clear 'rdataset' (to prevent the
2947 * cleanup code from cleaning it up).
2949 trdataset
= rdataset
;
2951 * Add the CNAME to the answer section.
2953 if (sigrdataset
!= NULL
)
2954 sigrdatasetp
= &sigrdataset
;
2956 sigrdatasetp
= NULL
;
2957 if (WANTDNSSEC(client
) &&
2958 (fname
->attributes
& DNS_NAMEATTR_WILDCARD
) != 0)
2960 dns_fixedname_init(&wildcardname
);
2961 dns_name_copy(fname
, dns_fixedname_name(&wildcardname
),
2963 need_wildcardproof
= ISC_TRUE
;
2965 if ((rdataset
->attributes
& DNS_RDATASETATTR_NOQNAME
) != 0 &&
2970 query_addrrset(client
, &fname
, &rdataset
, sigrdatasetp
, dbuf
,
2971 DNS_SECTION_ANSWER
);
2972 if (noqname
!= NULL
)
2973 query_addnoqnameproof(client
, noqname
);
2975 * We set the PARTIALANSWER attribute so that if anything goes
2976 * wrong later on, we'll return what we've got so far.
2978 client
->query
.attributes
|= NS_QUERYATTR_PARTIALANSWER
;
2980 * Reset qname to be the target name of the CNAME and restart
2984 result
= dns_message_gettempname(client
->message
, &tname
);
2985 if (result
!= ISC_R_SUCCESS
)
2987 result
= dns_rdataset_first(trdataset
);
2988 if (result
!= ISC_R_SUCCESS
) {
2989 dns_message_puttempname(client
->message
, &tname
);
2992 dns_rdataset_current(trdataset
, &rdata
);
2993 result
= dns_rdata_tostruct(&rdata
, &cname
, NULL
);
2994 dns_rdata_reset(&rdata
);
2995 if (result
!= ISC_R_SUCCESS
) {
2996 dns_message_puttempname(client
->message
, &tname
);
2999 dns_name_init(tname
, NULL
);
3000 result
= dns_name_dup(&cname
.cname
, client
->mctx
, tname
);
3001 if (result
!= ISC_R_SUCCESS
) {
3002 dns_message_puttempname(client
->message
, &tname
);
3003 dns_rdata_freestruct(&cname
);
3006 dns_rdata_freestruct(&cname
);
3007 ns_client_qnamereplace(client
, tname
);
3008 want_restart
= ISC_TRUE
;
3009 if (!WANTRECURSION(client
))
3010 options
|= DNS_GETDB_NOLOG
;
3014 * Compare the current qname to the found name. We need
3015 * to know how many labels and bits are in common because
3016 * we're going to have to split qname later on.
3018 namereln
= dns_name_fullcompare(client
->query
.qname
, fname
,
3020 INSIST(namereln
== dns_namereln_subdomain
);
3022 * Keep a copy of the rdataset. We have to do this because
3023 * query_addrrset may clear 'rdataset' (to prevent the
3024 * cleanup code from cleaning it up).
3026 trdataset
= rdataset
;
3028 * Add the DNAME to the answer section.
3030 if (sigrdataset
!= NULL
)
3031 sigrdatasetp
= &sigrdataset
;
3033 sigrdatasetp
= NULL
;
3034 if (WANTDNSSEC(client
) &&
3035 (fname
->attributes
& DNS_NAMEATTR_WILDCARD
) != 0)
3037 dns_fixedname_init(&wildcardname
);
3038 dns_name_copy(fname
, dns_fixedname_name(&wildcardname
),
3040 need_wildcardproof
= ISC_TRUE
;
3042 query_addrrset(client
, &fname
, &rdataset
, sigrdatasetp
, dbuf
,
3043 DNS_SECTION_ANSWER
);
3045 * We set the PARTIALANSWER attribute so that if anything goes
3046 * wrong later on, we'll return what we've got so far.
3048 client
->query
.attributes
|= NS_QUERYATTR_PARTIALANSWER
;
3050 * Get the target name of the DNAME.
3053 result
= dns_message_gettempname(client
->message
, &tname
);
3054 if (result
!= ISC_R_SUCCESS
)
3056 result
= dns_rdataset_first(trdataset
);
3057 if (result
!= ISC_R_SUCCESS
) {
3058 dns_message_puttempname(client
->message
, &tname
);
3061 dns_rdataset_current(trdataset
, &rdata
);
3062 result
= dns_rdata_tostruct(&rdata
, &dname
, NULL
);
3063 dns_rdata_reset(&rdata
);
3064 if (result
!= ISC_R_SUCCESS
) {
3065 dns_message_puttempname(client
->message
, &tname
);
3068 dns_name_init(tname
, NULL
);
3069 dns_name_clone(&dname
.dname
, tname
);
3070 dns_rdata_freestruct(&dname
);
3072 * Construct the new qname.
3074 dns_fixedname_init(&fixed
);
3075 prefix
= dns_fixedname_name(&fixed
);
3076 dns_name_split(client
->query
.qname
, nlabels
, prefix
, NULL
);
3077 INSIST(fname
== NULL
);
3078 dbuf
= query_getnamebuf(client
);
3080 dns_message_puttempname(client
->message
, &tname
);
3083 fname
= query_newname(client
, dbuf
, &b
);
3084 if (fname
== NULL
) {
3085 dns_message_puttempname(client
->message
, &tname
);
3088 result
= dns_name_concatenate(prefix
, tname
, fname
, NULL
);
3089 if (result
!= ISC_R_SUCCESS
) {
3090 dns_message_puttempname(client
->message
, &tname
);
3091 if (result
== ISC_R_NOSPACE
) {
3093 * RFC 2672, section 4.1, subsection 3c says
3094 * we should return YXDOMAIN if the constructed
3095 * name would be too long.
3097 client
->message
->rcode
= dns_rcode_yxdomain
;
3101 query_keepname(client
, fname
, dbuf
);
3103 * Synthesize a CNAME for this DNAME.
3105 * We want to synthesize a CNAME since if we don't
3106 * then older software that doesn't understand DNAME
3107 * will not chain like it should.
3109 * We do not try to synthesize a signature because we hope
3110 * that security aware servers will understand DNAME. Also,
3111 * even if we had an online key, making a signature
3112 * on-the-fly is costly, and not really legitimate anyway
3113 * since the synthesized CNAME is NOT in the zone.
3115 dns_name_init(tname
, NULL
);
3116 (void)query_addcnamelike(client
, client
->query
.qname
, fname
,
3117 trdataset
->trust
, &tname
,
3118 dns_rdatatype_cname
);
3120 dns_message_puttempname(client
->message
, &tname
);
3122 * Switch to the new qname and restart.
3124 ns_client_qnamereplace(client
, fname
);
3126 want_restart
= ISC_TRUE
;
3127 if (!WANTRECURSION(client
))
3128 options
|= DNS_GETDB_NOLOG
;
3132 * Something has gone wrong.
3134 QUERY_ERROR(DNS_R_SERVFAIL
);
3138 if (WANTDNSSEC(client
) &&
3139 (fname
->attributes
& DNS_NAMEATTR_WILDCARD
) != 0)
3141 dns_fixedname_init(&wildcardname
);
3142 dns_name_copy(fname
, dns_fixedname_name(&wildcardname
), NULL
);
3143 need_wildcardproof
= ISC_TRUE
;
3146 if (type
== dns_rdatatype_any
) {
3148 * XXXRTH Need to handle zonecuts with special case
3153 result
= dns_db_allrdatasets(db
, node
, version
, 0, &rdsiter
);
3154 if (result
!= ISC_R_SUCCESS
) {
3155 QUERY_ERROR(DNS_R_SERVFAIL
);
3159 * Calling query_addrrset() with a non-NULL dbuf is going
3160 * to either keep or release the name. We don't want it to
3161 * release fname, since we may have to call query_addrrset()
3162 * more than once. That means we have to call query_keepname()
3163 * now, and pass a NULL dbuf to query_addrrset().
3165 * If we do a query_addrrset() below, we must set fname to
3166 * NULL before leaving this block, otherwise we might try to
3167 * cleanup fname even though we're using it!
3169 query_keepname(client
, fname
, dbuf
);
3171 result
= dns_rdatasetiter_first(rdsiter
);
3172 while (result
== ISC_R_SUCCESS
) {
3173 dns_rdatasetiter_current(rdsiter
, rdataset
);
3174 if ((qtype
== dns_rdatatype_any
||
3175 rdataset
->type
== qtype
) && rdataset
->type
!= 0) {
3176 query_addrrset(client
,
3177 fname
!= NULL
? &fname
: &tname
,
3179 NULL
, DNS_SECTION_ANSWER
);
3181 INSIST(tname
!= NULL
);
3183 * rdataset is non-NULL only in certain pathological
3184 * cases involving DNAMEs.
3186 if (rdataset
!= NULL
)
3187 query_putrdataset(client
, &rdataset
);
3188 rdataset
= query_newrdataset(client
);
3189 if (rdataset
== NULL
)
3193 * We're not interested in this rdataset.
3195 dns_rdataset_disassociate(rdataset
);
3197 result
= dns_rdatasetiter_next(rdsiter
);
3201 dns_message_puttempname(client
->message
, &fname
);
3205 * We didn't match any rdatasets.
3207 if (qtype
== dns_rdatatype_rrsig
&&
3208 result
== ISC_R_NOMORE
) {
3210 * XXXRTH If this is a secure zone and we
3211 * didn't find any SIGs, we should generate
3212 * an error unless we were searching for
3216 * We were searching for SIG records in
3217 * a nonsecure zone. Send a "no error,
3218 * no data" response.
3223 result
= query_addsoa(client
, db
, ISC_FALSE
);
3224 if (result
== ISC_R_SUCCESS
)
3225 result
= ISC_R_NOMORE
;
3228 * Something went wrong.
3230 result
= DNS_R_SERVFAIL
;
3233 dns_rdatasetiter_destroy(&rdsiter
);
3234 if (result
!= ISC_R_NOMORE
) {
3235 QUERY_ERROR(DNS_R_SERVFAIL
);
3240 * This is the "normal" case -- an ordinary question to which
3241 * we know the answer.
3243 if (sigrdataset
!= NULL
)
3244 sigrdatasetp
= &sigrdataset
;
3246 sigrdatasetp
= NULL
;
3247 if ((rdataset
->attributes
& DNS_RDATASETATTR_NOQNAME
) != 0 &&
3252 query_addrrset(client
, &fname
, &rdataset
, sigrdatasetp
, dbuf
,
3253 DNS_SECTION_ANSWER
);
3254 if (noqname
!= NULL
)
3255 query_addnoqnameproof(client
, noqname
);
3257 * We shouldn't ever fail to add 'rdataset'
3258 * because it's already in the answer.
3260 INSIST(rdataset
== NULL
);
3264 CTRACE("query_find: addauth");
3266 * Add NS records to the authority section (if we haven't already
3267 * added them to the answer section).
3269 if (!want_restart
&& !NOAUTHORITY(client
)) {
3271 if (!((qtype
== dns_rdatatype_ns
||
3272 qtype
== dns_rdatatype_any
) &&
3273 dns_name_equal(client
->query
.qname
,
3274 dns_db_origin(db
))))
3275 (void)query_addns(client
, db
);
3276 } else if (qtype
!= dns_rdatatype_ns
) {
3278 query_releasename(client
, &fname
);
3279 query_addbestns(client
);
3284 * Add NSEC records to the authority section if they're needed for
3285 * DNSSEC wildcard proofs.
3287 if (need_wildcardproof
&& dns_db_issecure(db
))
3288 query_addwildcardproof(client
, db
,
3289 dns_fixedname_name(&wildcardname
),
3292 CTRACE("query_find: cleanup");
3296 if (rdataset
!= NULL
)
3297 query_putrdataset(client
, &rdataset
);
3298 if (sigrdataset
!= NULL
)
3299 query_putrdataset(client
, &sigrdataset
);
3301 query_releasename(client
, &fname
);
3303 dns_db_detachnode(db
, &node
);
3307 dns_zone_detach(&zone
);
3309 query_putrdataset(client
, &zrdataset
);
3310 if (zsigrdataset
!= NULL
)
3311 query_putrdataset(client
, &zsigrdataset
);
3313 query_releasename(client
, &zfname
);
3314 dns_db_detach(&zdb
);
3317 isc_event_free(ISC_EVENT_PTR(&event
));
3322 if (client
->query
.restarts
== 0 && !authoritative
) {
3324 * We're not authoritative, so we must ensure the AA bit
3327 client
->message
->flags
&= ~DNS_MESSAGEFLAG_AA
;
3331 * Restart the query?
3333 if (want_restart
&& client
->query
.restarts
< MAX_RESTARTS
) {
3334 client
->query
.restarts
++;
3338 if (eresult
!= ISC_R_SUCCESS
&&
3339 (!PARTIALANSWER(client
) || WANTRECURSION(client
))) {
3341 * If we don't have any answer to give the client,
3342 * or if the client requested recursion and thus wanted
3343 * the complete answer, send an error response.
3345 query_error(client
, eresult
);
3346 ns_client_detach(&client
);
3347 } else if (!RECURSING(client
)) {
3349 * We are done. Set up sortlist data for the message
3350 * rendering code, make a final tweak to the AA bit if the
3351 * auth-nxdomain config option says so, then render and
3352 * send the response.
3354 setup_query_sortlist(client
);
3357 * If this is a referral and the answer to the question
3358 * is in the glue sort it to the start of the additional
3361 if (client
->message
->counts
[DNS_SECTION_ANSWER
] == 0 &&
3362 client
->message
->rcode
== dns_rcode_noerror
&&
3363 (qtype
== dns_rdatatype_a
|| qtype
== dns_rdatatype_aaaa
))
3364 answer_in_glue(client
, qtype
);
3366 if (client
->message
->rcode
== dns_rcode_nxdomain
&&
3367 client
->view
->auth_nxdomain
== ISC_TRUE
)
3368 client
->message
->flags
|= DNS_MESSAGEFLAG_AA
;
3371 ns_client_detach(&client
);
3373 CTRACE("query_find: done");
3377 log_query(ns_client_t
*client
) {
3378 char namebuf
[DNS_NAME_FORMATSIZE
];
3379 char typename
[DNS_RDATATYPE_FORMATSIZE
];
3380 char classname
[DNS_RDATACLASS_FORMATSIZE
];
3381 dns_rdataset_t
*rdataset
;
3382 int level
= ISC_LOG_INFO
;
3384 if (! isc_log_wouldlog(ns_g_lctx
, level
))
3387 rdataset
= ISC_LIST_HEAD(client
->query
.qname
->list
);
3388 INSIST(rdataset
!= NULL
);
3389 dns_name_format(client
->query
.qname
, namebuf
, sizeof(namebuf
));
3390 dns_rdataclass_format(rdataset
->rdclass
, classname
, sizeof(classname
));
3391 dns_rdatatype_format(rdataset
->type
, typename
, sizeof(typename
));
3393 ns_client_log(client
, NS_LOGCATEGORY_QUERIES
, NS_LOGMODULE_QUERY
,
3394 level
, "query: %s %s %s %s%s%s", namebuf
, classname
,
3395 typename
, WANTRECURSION(client
) ? "+" : "-",
3396 (client
->signer
!= NULL
) ? "S": "",
3397 (client
->opt
!= NULL
) ? "E" : "");
3401 ns_query_start(ns_client_t
*client
) {
3402 isc_result_t result
;
3403 dns_message_t
*message
= client
->message
;
3404 dns_rdataset_t
*rdataset
;
3405 ns_client_t
*qclient
;
3406 dns_rdatatype_t qtype
;
3408 CTRACE("ns_query_start");
3411 * Ensure that appropriate cleanups occur.
3413 client
->next
= query_next_callback
;
3416 * Behave as if we don't support DNSSEC if not enabled.
3418 if (!client
->view
->enablednssec
) {
3419 message
->flags
&= ~DNS_MESSAGEFLAG_CD
;
3420 client
->extflags
&= ~DNS_MESSAGEEXTFLAG_DO
;
3423 if ((message
->flags
& DNS_MESSAGEFLAG_RD
) != 0)
3424 client
->query
.attributes
|= NS_QUERYATTR_WANTRECURSION
;
3426 if ((client
->extflags
& DNS_MESSAGEEXTFLAG_DO
) != 0)
3427 client
->attributes
|= NS_CLIENTATTR_WANTDNSSEC
;
3429 if (client
->view
->minimalresponses
)
3430 client
->query
.attributes
|= (NS_QUERYATTR_NOAUTHORITY
|
3431 NS_QUERYATTR_NOADDITIONAL
);
3433 if ((client
->view
->cachedb
== NULL
)
3434 || (!client
->view
->additionalfromcache
)) {
3436 * We don't have a cache. Turn off cache support and
3439 client
->query
.attributes
&=
3440 ~(NS_QUERYATTR_RECURSIONOK
|NS_QUERYATTR_CACHEOK
);
3441 } else if ((client
->attributes
& NS_CLIENTATTR_RA
) == 0 ||
3442 (message
->flags
& DNS_MESSAGEFLAG_RD
) == 0) {
3444 * If the client isn't allowed to recurse (due to
3445 * "recursion no", the allow-recursion ACL, or the
3446 * lack of a resolver in this view), or if it
3447 * doesn't want recursion, turn recursion off.
3449 client
->query
.attributes
&= ~NS_QUERYATTR_RECURSIONOK
;
3453 * Get the question name.
3455 result
= dns_message_firstname(message
, DNS_SECTION_QUESTION
);
3456 if (result
!= ISC_R_SUCCESS
) {
3457 query_error(client
, result
);
3460 dns_message_currentname(message
, DNS_SECTION_QUESTION
,
3461 &client
->query
.qname
);
3462 client
->query
.origqname
= client
->query
.qname
;
3463 result
= dns_message_nextname(message
, DNS_SECTION_QUESTION
);
3464 if (result
!= ISC_R_NOMORE
) {
3465 if (result
== ISC_R_SUCCESS
) {
3467 * There's more than one QNAME in the question
3470 query_error(client
, DNS_R_FORMERR
);
3472 query_error(client
, result
);
3476 if (ns_g_server
->log_queries
)
3480 * Check for multiple question queries, since edns1 is dead.
3482 if (message
->counts
[DNS_SECTION_QUESTION
] > 1) {
3483 query_error(client
, DNS_R_FORMERR
);
3488 * Check for meta-queries like IXFR and AXFR.
3490 rdataset
= ISC_LIST_HEAD(client
->query
.qname
->list
);
3491 INSIST(rdataset
!= NULL
);
3492 qtype
= rdataset
->type
;
3493 if (dns_rdatatype_ismeta(qtype
)) {
3495 case dns_rdatatype_any
:
3496 break; /* Let query_find handle it. */
3497 case dns_rdatatype_ixfr
:
3498 case dns_rdatatype_axfr
:
3499 ns_xfr_start(client
, rdataset
->type
);
3501 case dns_rdatatype_maila
:
3502 case dns_rdatatype_mailb
:
3503 query_error(client
, DNS_R_NOTIMP
);
3505 case dns_rdatatype_tkey
:
3506 result
= dns_tkey_processquery(client
->message
,
3507 ns_g_server
->tkeyctx
,
3508 client
->view
->dynamickeys
);
3509 if (result
== ISC_R_SUCCESS
)
3512 query_error(client
, result
);
3514 default: /* TSIG, etc. */
3515 query_error(client
, DNS_R_FORMERR
);
3521 * If the client has requested that DNSSEC checking be disabled,
3522 * allow lookups to return pending data and instruct the resolver
3523 * to return data before validation has completed.
3525 if (message
->flags
& DNS_MESSAGEFLAG_CD
||
3526 qtype
== dns_rdatatype_rrsig
)
3528 client
->query
.dboptions
|= DNS_DBFIND_PENDINGOK
;
3529 client
->query
.fetchoptions
|= DNS_FETCHOPT_NOVALIDATE
;
3533 * Allow glue NS records to be added to the authority section
3534 * if the answer is secure.
3536 if (message
->flags
& DNS_MESSAGEFLAG_CD
)
3537 client
->query
.attributes
&= ~NS_QUERYATTR_SECURE
;
3540 * This is an ordinary query.
3542 result
= dns_message_reply(message
, ISC_TRUE
);
3543 if (result
!= ISC_R_SUCCESS
) {
3544 query_next(client
, result
);
3549 * Assume authoritative response until it is known to be
3552 message
->flags
|= DNS_MESSAGEFLAG_AA
;
3555 * Set AD. We must clear it if we add non-validated data to a
3558 if (client
->view
->enablednssec
)
3559 message
->flags
|= DNS_MESSAGEFLAG_AD
;
3562 ns_client_attach(client
, &qclient
);
3563 query_find(qclient
, NULL
, qtype
);