2 * Copyright (C) 2004, 2005 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.36.6.1 2006/08/17 07:12:31 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_maybeputqname(ns_client_t *client) {
153 if (client->query.restarts > 0) {
155 * client->query.qname was dynamically allocated.
157 dns_message_puttempname(client->message,
158 &client->query.qname);
159 client->query.qname = NULL;
164 query_freefreeversions(ns_client_t *client, isc_boolean_t everything) {
165 ns_dbversion_t *dbversion, *dbversion_next;
168 for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
170 dbversion = dbversion_next, i++)
172 dbversion_next = ISC_LIST_NEXT(dbversion, link);
174 * If we're not freeing everything, we keep the first three
175 * dbversions structures around.
177 if (i > 3 || everything) {
178 ISC_LIST_UNLINK(client->query.freeversions, dbversion,
180 isc_mem_put(client->mctx, dbversion,
187 ns_query_cancel(ns_client_t *client) {
188 LOCK(&client->query.fetchlock);
189 if (client->query.fetch != NULL) {
190 dns_resolver_cancelfetch(client->query.fetch);
192 client->query.fetch = NULL;
194 UNLOCK(&client->query.fetchlock);
198 query_reset(ns_client_t *client, isc_boolean_t everything) {
199 isc_buffer_t *dbuf, *dbuf_next;
200 ns_dbversion_t *dbversion, *dbversion_next;
203 * Reset the query state of a client to its default state.
207 * Cancel the fetch if it's running.
209 ns_query_cancel(client);
212 * Cleanup any active versions.
214 for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
216 dbversion = dbversion_next) {
217 dbversion_next = ISC_LIST_NEXT(dbversion, link);
218 dns_db_closeversion(dbversion->db, &dbversion->version,
220 dns_db_detach(&dbversion->db);
221 ISC_LIST_INITANDAPPEND(client->query.freeversions,
224 ISC_LIST_INIT(client->query.activeversions);
226 if (client->query.authdb != NULL)
227 dns_db_detach(&client->query.authdb);
228 if (client->query.authzone != NULL)
229 dns_zone_detach(&client->query.authzone);
231 query_freefreeversions(client, everything);
233 for (dbuf = ISC_LIST_HEAD(client->query.namebufs);
236 dbuf_next = ISC_LIST_NEXT(dbuf, link);
237 if (dbuf_next != NULL || everything) {
238 ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
239 isc_buffer_free(&dbuf);
243 query_maybeputqname(client);
245 client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
246 NS_QUERYATTR_CACHEOK |
247 NS_QUERYATTR_SECURE);
248 client->query.restarts = 0;
249 client->query.timerset = ISC_FALSE;
250 client->query.origqname = NULL;
251 client->query.qname = NULL;
252 client->query.dboptions = 0;
253 client->query.fetchoptions = 0;
254 client->query.gluedb = NULL;
255 client->query.authdbset = ISC_FALSE;
256 client->query.isreferral = ISC_FALSE;
260 query_next_callback(ns_client_t *client) {
261 query_reset(client, ISC_FALSE);
265 ns_query_free(ns_client_t *client) {
266 query_reset(client, ISC_TRUE);
269 static inline isc_result_t
270 query_newnamebuf(ns_client_t *client) {
274 CTRACE("query_newnamebuf");
276 * Allocate a name buffer.
280 result = isc_buffer_allocate(client->mctx, &dbuf, 1024);
281 if (result != ISC_R_SUCCESS) {
282 CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
285 ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
287 CTRACE("query_newnamebuf: done");
288 return (ISC_R_SUCCESS);
291 static inline isc_buffer_t *
292 query_getnamebuf(ns_client_t *client) {
297 CTRACE("query_getnamebuf");
299 * Return a name buffer with space for a maximal name, allocating
300 * a new one if necessary.
303 if (ISC_LIST_EMPTY(client->query.namebufs)) {
304 result = query_newnamebuf(client);
305 if (result != ISC_R_SUCCESS) {
306 CTRACE("query_getnamebuf: query_newnamebuf failed: done");
311 dbuf = ISC_LIST_TAIL(client->query.namebufs);
312 INSIST(dbuf != NULL);
313 isc_buffer_availableregion(dbuf, &r);
314 if (r.length < 255) {
315 result = query_newnamebuf(client);
316 if (result != ISC_R_SUCCESS) {
317 CTRACE("query_getnamebuf: query_newnamebuf failed: done");
321 dbuf = ISC_LIST_TAIL(client->query.namebufs);
322 isc_buffer_availableregion(dbuf, &r);
323 INSIST(r.length >= 255);
325 CTRACE("query_getnamebuf: done");
330 query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
333 CTRACE("query_keepname");
335 * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
336 * adjusted to take account of that. We do the adjustment.
339 REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
341 dns_name_toregion(name, &r);
342 isc_buffer_add(dbuf, r.length);
343 dns_name_setbuffer(name, NULL);
344 client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
348 query_releasename(ns_client_t *client, dns_name_t **namep) {
349 dns_name_t *name = *namep;
352 * 'name' is no longer needed. Return it to our pool of temporary
353 * names. If it is using a name buffer, relinquish its exclusive
354 * rights on the buffer.
357 CTRACE("query_releasename");
358 if (dns_name_hasbuffer(name)) {
359 INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
361 client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
363 dns_message_puttempname(client->message, namep);
364 CTRACE("query_releasename: done");
367 static inline dns_name_t *
368 query_newname(ns_client_t *client, isc_buffer_t *dbuf,
375 REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
377 CTRACE("query_newname");
379 result = dns_message_gettempname(client->message, &name);
380 if (result != ISC_R_SUCCESS) {
381 CTRACE("query_newname: dns_message_gettempname failed: done");
384 isc_buffer_availableregion(dbuf, &r);
385 isc_buffer_init(nbuf, r.base, r.length);
386 dns_name_init(name, NULL);
387 dns_name_setbuffer(name, nbuf);
388 client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
390 CTRACE("query_newname: done");
394 static inline dns_rdataset_t *
395 query_newrdataset(ns_client_t *client) {
396 dns_rdataset_t *rdataset;
399 CTRACE("query_newrdataset");
401 result = dns_message_gettemprdataset(client->message, &rdataset);
402 if (result != ISC_R_SUCCESS) {
403 CTRACE("query_newrdataset: "
404 "dns_message_gettemprdataset failed: done");
407 dns_rdataset_init(rdataset);
409 CTRACE("query_newrdataset: done");
414 query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
415 dns_rdataset_t *rdataset = *rdatasetp;
417 CTRACE("query_putrdataset");
418 if (rdataset != NULL) {
419 if (dns_rdataset_isassociated(rdataset))
420 dns_rdataset_disassociate(rdataset);
421 dns_message_puttemprdataset(client->message, rdatasetp);
423 CTRACE("query_putrdataset: done");
427 static inline isc_result_t
428 query_newdbversion(ns_client_t *client, unsigned int n) {
430 ns_dbversion_t *dbversion;
432 for (i = 0; i < n; i++) {
433 dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
434 if (dbversion != NULL) {
435 dbversion->db = NULL;
436 dbversion->version = NULL;
437 ISC_LIST_INITANDAPPEND(client->query.freeversions,
441 * We only return ISC_R_NOMEMORY if we couldn't
445 return (ISC_R_NOMEMORY);
447 return (ISC_R_SUCCESS);
451 return (ISC_R_SUCCESS);
454 static inline ns_dbversion_t *
455 query_getdbversion(ns_client_t *client) {
457 ns_dbversion_t *dbversion;
459 if (ISC_LIST_EMPTY(client->query.freeversions)) {
460 result = query_newdbversion(client, 1);
461 if (result != ISC_R_SUCCESS)
464 dbversion = ISC_LIST_HEAD(client->query.freeversions);
465 INSIST(dbversion != NULL);
466 ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
472 ns_query_init(ns_client_t *client) {
475 ISC_LIST_INIT(client->query.namebufs);
476 ISC_LIST_INIT(client->query.activeversions);
477 ISC_LIST_INIT(client->query.freeversions);
478 client->query.restarts = 0;
479 client->query.timerset = ISC_FALSE;
480 client->query.qname = NULL;
481 result = isc_mutex_init(&client->query.fetchlock);
482 if (result != ISC_R_SUCCESS)
484 client->query.fetch = NULL;
485 client->query.authdb = NULL;
486 client->query.authzone = NULL;
487 client->query.authdbset = ISC_FALSE;
488 client->query.isreferral = ISC_FALSE;
489 query_reset(client, ISC_FALSE);
490 result = query_newdbversion(client, 3);
491 if (result != ISC_R_SUCCESS) {
492 DESTROYLOCK(&client->query.fetchlock);
495 result = query_newnamebuf(client);
496 if (result != ISC_R_SUCCESS)
497 query_freefreeversions(client, ISC_TRUE);
502 static inline ns_dbversion_t *
503 query_findversion(ns_client_t *client, dns_db_t *db,
504 isc_boolean_t *newzonep)
506 ns_dbversion_t *dbversion;
509 * We may already have done a query related to this
510 * database. If so, we must be sure to make subsequent
511 * queries from the same version.
513 for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
515 dbversion = ISC_LIST_NEXT(dbversion, link)) {
516 if (dbversion->db == db)
520 if (dbversion == NULL) {
522 * This is a new zone for this query. Add it to
525 dbversion = query_getdbversion(client);
526 if (dbversion == NULL)
528 dns_db_attach(db, &dbversion->db);
529 dns_db_currentversion(db, &dbversion->version);
530 dbversion->queryok = ISC_FALSE;
531 ISC_LIST_APPEND(client->query.activeversions,
533 *newzonep = ISC_TRUE;
535 *newzonep = ISC_FALSE;
540 static inline isc_result_t
541 query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
542 unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
543 dns_dbversion_t **versionp)
546 isc_boolean_t check_acl, new_zone;
548 ns_dbversion_t *dbversion;
549 unsigned int ztoptions;
550 dns_zone_t *zone = NULL;
552 isc_boolean_t partial = ISC_FALSE;
554 REQUIRE(zonep != NULL && *zonep == NULL);
555 REQUIRE(dbp != NULL && *dbp == NULL);
558 * Find a zone database to answer the query.
560 ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?
561 DNS_ZTFIND_NOEXACT : 0;
563 result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
565 if (result == DNS_R_PARTIALMATCH)
567 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
568 result = dns_zone_getdb(zone, &db);
570 if (result != ISC_R_SUCCESS)
574 * This limits our searching to the zone where the first name
575 * (the query target) was looked for. This prevents following
576 * CNAMES or DNAMES into other zones and prevents returning
577 * additional data from other zones.
579 if (!client->view->additionalfromauth &&
580 client->query.authdbset &&
581 db != client->query.authdb)
585 * If the zone has an ACL, we'll check it, otherwise
586 * we use the view's "allow-query" ACL. Each ACL is only checked
589 * Also, get the database version to use.
592 check_acl = ISC_TRUE; /* Keep compiler happy. */
596 * Get the current version of this database.
598 dbversion = query_findversion(client, db, &new_zone);
599 if (dbversion == NULL) {
600 result = DNS_R_SERVFAIL;
604 check_acl = ISC_TRUE;
605 } else if (!dbversion->queryok) {
608 check_acl = ISC_FALSE;
611 queryacl = dns_zone_getqueryacl(zone);
612 if (queryacl == NULL) {
613 queryacl = client->view->queryacl;
614 if ((client->query.attributes &
615 NS_QUERYATTR_QUERYOKVALID) != 0) {
617 * We've evaluated the view's queryacl already. If
618 * NS_QUERYATTR_QUERYOK is set, then the client is
619 * allowed to make queries, otherwise the query should
622 check_acl = ISC_FALSE;
623 if ((client->query.attributes &
624 NS_QUERYATTR_QUERYOK) == 0)
628 * We haven't evaluated the view's queryacl yet.
630 check_acl = ISC_TRUE;
635 isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);
637 result = ns_client_checkaclsilent(client, queryacl, ISC_TRUE);
639 char msg[NS_CLIENT_ACLMSGSIZE("query")];
640 if (result == ISC_R_SUCCESS) {
641 if (isc_log_wouldlog(ns_g_lctx,
644 ns_client_aclmsg("query", name, qtype,
645 client->view->rdclass,
647 ns_client_log(client,
648 DNS_LOGCATEGORY_SECURITY,
654 ns_client_aclmsg("query", name, qtype,
655 client->view->rdclass,
657 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
658 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
663 if (queryacl == client->view->queryacl) {
664 if (result == ISC_R_SUCCESS) {
666 * We were allowed by the default
667 * "allow-query" ACL. Remember this so we
668 * don't have to check again.
670 client->query.attributes |=
671 NS_QUERYATTR_QUERYOK;
674 * We've now evaluated the view's query ACL, and
675 * the NS_QUERYATTR_QUERYOK attribute is now valid.
677 client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
680 if (result != ISC_R_SUCCESS)
687 * Remember the result of the ACL check so we
688 * don't have to check again.
690 dbversion->queryok = ISC_TRUE;
692 /* Transfer ownership. */
695 *versionp = dbversion->version;
697 if (partial && (options & DNS_GETDB_PARTIAL) != 0)
698 return (DNS_R_PARTIALMATCH);
699 return (ISC_R_SUCCESS);
702 result = DNS_R_REFUSED;
705 dns_zone_detach(&zone);
712 static inline isc_result_t
713 query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
714 dns_db_t **dbp, unsigned int options)
717 isc_boolean_t check_acl;
720 REQUIRE(dbp != NULL && *dbp == NULL);
723 * Find a cache database to answer the query.
724 * This may fail with DNS_R_REFUSED if the client
725 * is not allowed to use the cache.
728 if (!USECACHE(client))
729 return (DNS_R_REFUSED);
730 dns_db_attach(client->view->cachedb, &db);
732 if ((client->query.attributes &
733 NS_QUERYATTR_QUERYOKVALID) != 0) {
735 * We've evaluated the view's queryacl already. If
736 * NS_QUERYATTR_QUERYOK is set, then the client is
737 * allowed to make queries, otherwise the query should
740 check_acl = ISC_FALSE;
741 if ((client->query.attributes &
742 NS_QUERYATTR_QUERYOK) == 0)
746 * We haven't evaluated the view's queryacl yet.
748 check_acl = ISC_TRUE;
752 isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);
753 char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
755 result = ns_client_checkaclsilent(client,
756 client->view->queryacl,
758 if (result == ISC_R_SUCCESS) {
760 * We were allowed by the default
761 * "allow-query" ACL. Remember this so we
762 * don't have to check again.
764 client->query.attributes |=
765 NS_QUERYATTR_QUERYOK;
766 if (log && isc_log_wouldlog(ns_g_lctx,
769 ns_client_aclmsg("query (cache)", name, qtype,
770 client->view->rdclass,
772 ns_client_log(client,
773 DNS_LOGCATEGORY_SECURITY,
779 ns_client_aclmsg("query (cache)", name, qtype,
780 client->view->rdclass, msg,
782 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
783 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
787 * We've now evaluated the view's query ACL, and
788 * the NS_QUERYATTR_QUERYOK attribute is now valid.
790 client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
792 if (result != ISC_R_SUCCESS)
798 /* Transfer ownership. */
801 return (ISC_R_SUCCESS);
804 result = DNS_R_REFUSED;
813 static inline isc_result_t
814 query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
815 unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
816 dns_dbversion_t **versionp, isc_boolean_t *is_zonep)
820 result = query_getzonedb(client, name, qtype, options,
821 zonep, dbp, versionp);
822 if (result == ISC_R_SUCCESS) {
823 *is_zonep = ISC_TRUE;
824 } else if (result == ISC_R_NOTFOUND) {
825 result = query_getcachedb(client, name, qtype, dbp, options);
826 *is_zonep = ISC_FALSE;
831 static inline isc_boolean_t
832 query_isduplicate(ns_client_t *client, dns_name_t *name,
833 dns_rdatatype_t type, dns_name_t **mnamep)
835 dns_section_t section;
836 dns_name_t *mname = NULL;
839 CTRACE("query_isduplicate");
841 for (section = DNS_SECTION_ANSWER;
842 section <= DNS_SECTION_ADDITIONAL;
844 result = dns_message_findname(client->message, section,
845 name, type, 0, &mname, NULL);
846 if (result == ISC_R_SUCCESS) {
848 * We've already got this RRset in the response.
850 CTRACE("query_isduplicate: true: done");
852 } else if (result == DNS_R_NXRRSET) {
854 * The name exists, but the rdataset does not.
856 if (section == DNS_SECTION_ADDITIONAL)
859 RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
864 * If the dns_name_t we're looking up is already in the message,
865 * we don't want to trigger the caller's name replacement logic.
872 CTRACE("query_isduplicate: false: done");
877 query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
878 ns_client_t *client = arg;
879 isc_result_t result, eresult;
882 dns_name_t *fname, *mname;
883 dns_rdataset_t *rdataset, *sigrdataset, *trdataset;
886 dns_dbversion_t *version;
887 isc_boolean_t added_something, need_addname;
889 dns_rdatatype_t type;
891 REQUIRE(NS_CLIENT_VALID(client));
892 REQUIRE(qtype != dns_rdatatype_any);
894 if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))
895 return (ISC_R_SUCCESS);
897 CTRACE("query_addadditional");
902 eresult = ISC_R_SUCCESS;
910 added_something = ISC_FALSE;
911 need_addname = ISC_FALSE;
915 * We treat type A additional section processing as if it
916 * were "any address type" additional section processing.
917 * To avoid multiple lookups, we do an 'any' database
918 * lookup and iterate over the node.
920 if (qtype == dns_rdatatype_a)
921 type = dns_rdatatype_any;
926 * Get some resources.
928 dbuf = query_getnamebuf(client);
931 fname = query_newname(client, dbuf, &b);
932 rdataset = query_newrdataset(client);
933 if (fname == NULL || rdataset == NULL)
935 if (WANTDNSSEC(client)) {
936 sigrdataset = query_newrdataset(client);
937 if (sigrdataset == NULL)
942 * Look for a zone database that might contain authoritative
945 result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
946 &zone, &db, &version);
947 if (result != ISC_R_SUCCESS)
950 CTRACE("query_addadditional: db_find");
953 * Since we are looking for authoritative data, we do not set
954 * the GLUEOK flag. Glue will be looked for later, but not
955 * necessarily in the same database.
958 result = dns_db_find(db, name, version, type, client->query.dboptions,
959 client->now, &node, fname, rdataset,
961 if (result == ISC_R_SUCCESS)
964 if (dns_rdataset_isassociated(rdataset))
965 dns_rdataset_disassociate(rdataset);
966 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
967 dns_rdataset_disassociate(sigrdataset);
969 dns_db_detachnode(db, &node);
974 * No authoritative data was found. The cache is our next best bet.
978 result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
979 if (result != ISC_R_SUCCESS)
981 * Most likely the client isn't allowed to query the cache.
985 result = dns_db_find(db, name, version, type, client->query.dboptions,
986 client->now, &node, fname, rdataset,
988 if (result == ISC_R_SUCCESS)
991 if (dns_rdataset_isassociated(rdataset))
992 dns_rdataset_disassociate(rdataset);
993 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
994 dns_rdataset_disassociate(sigrdataset);
996 dns_db_detachnode(db, &node);
1001 * No cached data was found. Glue is our last chance.
1004 * NS records cause both the usual additional section
1005 * processing to locate a type A record, and, when used
1006 * in a referral, a special search of the zone in which
1007 * they reside for glue information.
1009 * This is the "special search". Note that we must search
1010 * the zone where the NS record resides, not the zone it
1011 * points to, and that we only do the search in the delegation
1012 * case (identified by client->query.gluedb being set).
1015 if (client->query.gluedb == NULL)
1019 * Don't poision caches using the bailiwick protection model.
1021 if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
1024 dns_db_attach(client->query.gluedb, &db);
1025 result = dns_db_find(db, name, version, type,
1026 client->query.dboptions | DNS_DBFIND_GLUEOK,
1027 client->now, &node, fname, rdataset,
1029 if (!(result == ISC_R_SUCCESS ||
1030 result == DNS_R_ZONECUT ||
1031 result == DNS_R_GLUE))
1036 * We have found a potential additional data rdataset, or
1037 * at least a node to iterate over.
1039 query_keepname(client, fname, dbuf);
1042 * If we have an rdataset, add it to the additional data
1046 if (dns_rdataset_isassociated(rdataset) &&
1047 !query_isduplicate(client, fname, type, &mname)) {
1048 if (mname != NULL) {
1049 query_releasename(client, &fname);
1052 need_addname = ISC_TRUE;
1053 ISC_LIST_APPEND(fname->list, rdataset, link);
1054 trdataset = rdataset;
1056 added_something = ISC_TRUE;
1058 * Note: we only add SIGs if we've added the type they cover,
1059 * so we do not need to check if the SIG rdataset is already
1062 if (sigrdataset != NULL &&
1063 dns_rdataset_isassociated(sigrdataset))
1065 ISC_LIST_APPEND(fname->list, sigrdataset, link);
1070 if (qtype == dns_rdatatype_a) {
1072 * We now go looking for A and AAAA records, along with
1075 * XXXRTH This code could be more efficient.
1077 if (rdataset != NULL) {
1078 if (dns_rdataset_isassociated(rdataset))
1079 dns_rdataset_disassociate(rdataset);
1081 rdataset = query_newrdataset(client);
1082 if (rdataset == NULL)
1085 if (sigrdataset != NULL) {
1086 if (dns_rdataset_isassociated(sigrdataset))
1087 dns_rdataset_disassociate(sigrdataset);
1088 } else if (WANTDNSSEC(client)) {
1089 sigrdataset = query_newrdataset(client);
1090 if (sigrdataset == NULL)
1093 result = dns_db_findrdataset(db, node, version,
1095 client->now, rdataset,
1097 if (result == DNS_R_NCACHENXDOMAIN)
1099 if (result == DNS_R_NCACHENXRRSET) {
1100 dns_rdataset_disassociate(rdataset);
1102 * Negative cache entries don't have sigrdatasets.
1104 INSIST(sigrdataset == NULL ||
1105 ! dns_rdataset_isassociated(sigrdataset));
1107 if (result == ISC_R_SUCCESS) {
1109 if (!query_isduplicate(client, fname,
1110 dns_rdatatype_a, &mname)) {
1111 if (mname != NULL) {
1112 query_releasename(client, &fname);
1115 need_addname = ISC_TRUE;
1116 ISC_LIST_APPEND(fname->list, rdataset, link);
1117 added_something = ISC_TRUE;
1118 if (sigrdataset != NULL &&
1119 dns_rdataset_isassociated(sigrdataset))
1121 ISC_LIST_APPEND(fname->list,
1124 query_newrdataset(client);
1126 rdataset = query_newrdataset(client);
1127 if (rdataset == NULL)
1129 if (WANTDNSSEC(client) && sigrdataset == NULL)
1132 dns_rdataset_disassociate(rdataset);
1133 if (sigrdataset != NULL &&
1134 dns_rdataset_isassociated(sigrdataset))
1135 dns_rdataset_disassociate(sigrdataset);
1138 result = dns_db_findrdataset(db, node, version,
1139 dns_rdatatype_aaaa, 0,
1140 client->now, rdataset,
1142 if (result == DNS_R_NCACHENXDOMAIN)
1144 if (result == DNS_R_NCACHENXRRSET) {
1145 dns_rdataset_disassociate(rdataset);
1146 INSIST(sigrdataset == NULL ||
1147 ! dns_rdataset_isassociated(sigrdataset));
1149 if (result == ISC_R_SUCCESS) {
1151 if (!query_isduplicate(client, fname,
1152 dns_rdatatype_aaaa, &mname)) {
1153 if (mname != NULL) {
1154 query_releasename(client, &fname);
1157 need_addname = ISC_TRUE;
1158 ISC_LIST_APPEND(fname->list, rdataset, link);
1159 added_something = ISC_TRUE;
1160 if (sigrdataset != NULL &&
1161 dns_rdataset_isassociated(sigrdataset))
1163 ISC_LIST_APPEND(fname->list,
1173 CTRACE("query_addadditional: addname");
1175 * If we haven't added anything, then we're done.
1177 if (!added_something)
1181 * We may have added our rdatasets to an existing name, if so, then
1182 * need_addname will be ISC_FALSE. Whether we used an existing name
1183 * or a new one, we must set fname to NULL to prevent cleanup.
1186 dns_message_addname(client->message, fname,
1187 DNS_SECTION_ADDITIONAL);
1191 * In a few cases, we want to add additional data for additional
1192 * data. It's simpler to just deal with special cases here than
1193 * to try to create a general purpose mechanism and allow the
1194 * rdata implementations to do it themselves.
1196 * This involves recursion, but the depth is limited. The
1197 * most complex case is adding a SRV rdataset, which involves
1198 * recursing to add address records, which in turn can cause
1199 * recursion to add KEYs.
1201 if (type == dns_rdatatype_srv && trdataset != NULL) {
1203 * If we're adding SRV records to the additional data
1204 * section, it's helpful if we add the SRV additional data
1207 eresult = dns_rdataset_additionaldata(trdataset,
1208 query_addadditional,
1213 CTRACE("query_addadditional: cleanup");
1214 query_putrdataset(client, &rdataset);
1215 if (sigrdataset != NULL)
1216 query_putrdataset(client, &sigrdataset);
1218 query_releasename(client, &fname);
1220 dns_db_detachnode(db, &node);
1224 dns_zone_detach(&zone);
1226 CTRACE("query_addadditional: done");
1231 query_addrdataset(ns_client_t *client, dns_name_t *fname,
1232 dns_rdataset_t *rdataset)
1235 * Add 'rdataset' and any pertinent additional data to
1236 * 'fname', a name in the response message for 'client'.
1239 CTRACE("query_addrdataset");
1241 ISC_LIST_APPEND(fname->list, rdataset, link);
1243 if (client->view->order != NULL)
1244 rdataset->attributes |= dns_order_find(client->view->order,
1245 fname, rdataset->type,
1247 if (NOADDITIONAL(client))
1251 * Add additional data.
1253 * We don't care if dns_rdataset_additionaldata() fails.
1255 (void)dns_rdataset_additionaldata(rdataset,
1256 query_addadditional, client);
1257 CTRACE("query_addrdataset: done");
1261 query_addrrset(ns_client_t *client, dns_name_t **namep,
1262 dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
1263 isc_buffer_t *dbuf, dns_section_t section)
1265 dns_name_t *name, *mname;
1266 dns_rdataset_t *rdataset, *mrdataset, *sigrdataset;
1267 isc_result_t result;
1270 * To the current response for 'client', add the answer RRset
1271 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
1272 * owner name '*namep', to section 'section', unless they are
1273 * already there. Also add any pertinent additional data.
1275 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
1276 * stored in 'dbuf'. In this case, query_addrrset() guarantees that
1277 * when it returns the name will either have been kept or released.
1279 CTRACE("query_addrrset");
1281 rdataset = *rdatasetp;
1282 if (sigrdatasetp != NULL)
1283 sigrdataset = *sigrdatasetp;
1288 result = dns_message_findname(client->message, section,
1289 name, rdataset->type, rdataset->covers,
1290 &mname, &mrdataset);
1291 if (result == ISC_R_SUCCESS) {
1293 * We've already got an RRset of the given name and type.
1294 * There's nothing else to do;
1296 CTRACE("query_addrrset: dns_message_findname succeeded: done");
1298 query_releasename(client, namep);
1300 } else if (result == DNS_R_NXDOMAIN) {
1302 * The name doesn't exist.
1305 query_keepname(client, name, dbuf);
1306 dns_message_addname(client->message, name, section);
1310 RUNTIME_CHECK(result == DNS_R_NXRRSET);
1312 query_releasename(client, namep);
1315 if (rdataset->trust != dns_trust_secure &&
1316 (section == DNS_SECTION_ANSWER ||
1317 section == DNS_SECTION_AUTHORITY))
1318 client->query.attributes &= ~NS_QUERYATTR_SECURE;
1320 * Note: we only add SIGs if we've added the type they cover, so
1321 * we do not need to check if the SIG rdataset is already in the
1324 query_addrdataset(client, mname, rdataset);
1326 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
1328 * We have a signature. Add it to the response.
1330 ISC_LIST_APPEND(mname->list, sigrdataset, link);
1331 *sigrdatasetp = NULL;
1333 CTRACE("query_addrrset: done");
1336 static inline isc_result_t
1337 query_addsoa(ns_client_t *client, dns_db_t *db, isc_boolean_t zero_ttl) {
1338 dns_name_t *name, *fname;
1340 isc_result_t result, eresult;
1341 dns_fixedname_t foundname;
1342 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
1343 dns_rdataset_t **sigrdatasetp = NULL;
1345 CTRACE("query_addsoa");
1349 eresult = ISC_R_SUCCESS;
1353 dns_fixedname_init(&foundname);
1354 fname = dns_fixedname_name(&foundname);
1357 * Get resources and make 'name' be the database origin.
1359 result = dns_message_gettempname(client->message, &name);
1360 if (result != ISC_R_SUCCESS)
1362 dns_name_init(name, NULL);
1363 dns_name_clone(dns_db_origin(db), name);
1364 rdataset = query_newrdataset(client);
1365 if (rdataset == NULL) {
1366 eresult = DNS_R_SERVFAIL;
1369 if (WANTDNSSEC(client)) {
1370 sigrdataset = query_newrdataset(client);
1371 if (sigrdataset == NULL) {
1372 eresult = DNS_R_SERVFAIL;
1380 result = dns_db_find(db, name, NULL, dns_rdatatype_soa,
1381 client->query.dboptions, 0, &node,
1382 fname, rdataset, sigrdataset);
1383 if (result != ISC_R_SUCCESS) {
1385 * This is bad. We tried to get the SOA RR at the zone top
1386 * and it didn't work!
1388 eresult = DNS_R_SERVFAIL;
1391 * Extract the SOA MINIMUM.
1393 dns_rdata_soa_t soa;
1394 dns_rdata_t rdata = DNS_RDATA_INIT;
1395 result = dns_rdataset_first(rdataset);
1396 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1397 dns_rdataset_current(rdataset, &rdata);
1398 result = dns_rdata_tostruct(&rdata, &soa, NULL);
1399 if (result != ISC_R_SUCCESS)
1404 if (sigrdataset != NULL)
1405 sigrdataset->ttl = 0;
1409 * Add the SOA and its SIG to the response, with the
1410 * TTLs adjusted per RFC2308 section 3.
1412 if (rdataset->ttl > soa.minimum)
1413 rdataset->ttl = soa.minimum;
1414 if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum)
1415 sigrdataset->ttl = soa.minimum;
1417 if (sigrdataset != NULL)
1418 sigrdatasetp = &sigrdataset;
1420 sigrdatasetp = NULL;
1421 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
1422 DNS_SECTION_AUTHORITY);
1426 query_putrdataset(client, &rdataset);
1427 if (sigrdataset != NULL)
1428 query_putrdataset(client, &sigrdataset);
1430 query_releasename(client, &name);
1432 dns_db_detachnode(db, &node);
1437 static inline isc_result_t
1438 query_addns(ns_client_t *client, dns_db_t *db) {
1439 dns_name_t *name, *fname;
1441 isc_result_t result, eresult;
1442 dns_fixedname_t foundname;
1443 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
1444 dns_rdataset_t **sigrdatasetp = NULL;
1446 CTRACE("query_addns");
1450 eresult = ISC_R_SUCCESS;
1454 dns_fixedname_init(&foundname);
1455 fname = dns_fixedname_name(&foundname);
1458 * Get resources and make 'name' be the database origin.
1460 result = dns_message_gettempname(client->message, &name);
1461 if (result != ISC_R_SUCCESS) {
1462 CTRACE("query_addns: dns_message_gettempname failed: done");
1465 dns_name_init(name, NULL);
1466 dns_name_clone(dns_db_origin(db), name);
1467 rdataset = query_newrdataset(client);
1468 if (rdataset == NULL) {
1469 CTRACE("query_addns: query_newrdataset failed");
1470 eresult = DNS_R_SERVFAIL;
1473 if (WANTDNSSEC(client)) {
1474 sigrdataset = query_newrdataset(client);
1475 if (sigrdataset == NULL) {
1476 CTRACE("query_addns: query_newrdataset failed");
1477 eresult = DNS_R_SERVFAIL;
1483 * Find the NS rdataset.
1485 CTRACE("query_addns: calling dns_db_find");
1486 result = dns_db_find(db, name, NULL, dns_rdatatype_ns,
1487 client->query.dboptions, 0, &node,
1488 fname, rdataset, sigrdataset);
1489 CTRACE("query_addns: dns_db_find complete");
1490 if (result != ISC_R_SUCCESS) {
1491 CTRACE("query_addns: dns_db_find failed");
1493 * This is bad. We tried to get the NS rdataset at the zone
1494 * top and it didn't work!
1496 eresult = DNS_R_SERVFAIL;
1498 if (sigrdataset != NULL)
1499 sigrdatasetp = &sigrdataset;
1501 sigrdatasetp = NULL;
1502 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
1503 DNS_SECTION_AUTHORITY);
1507 CTRACE("query_addns: cleanup");
1508 query_putrdataset(client, &rdataset);
1509 if (sigrdataset != NULL)
1510 query_putrdataset(client, &sigrdataset);
1512 query_releasename(client, &name);
1514 dns_db_detachnode(db, &node);
1516 CTRACE("query_addns: done");
1520 static inline isc_result_t
1521 query_addcnamelike(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
1522 dns_trust_t trust, dns_name_t **anamep, dns_rdatatype_t type)
1524 dns_rdataset_t *rdataset;
1525 dns_rdatalist_t *rdatalist;
1527 isc_result_t result;
1531 * We assume the name data referred to by tname won't go away.
1534 REQUIRE(anamep != NULL);
1537 result = dns_message_gettemprdatalist(client->message, &rdatalist);
1538 if (result != ISC_R_SUCCESS)
1541 result = dns_message_gettemprdata(client->message, &rdata);
1542 if (result != ISC_R_SUCCESS)
1545 result = dns_message_gettemprdataset(client->message, &rdataset);
1546 if (result != ISC_R_SUCCESS)
1548 dns_rdataset_init(rdataset);
1549 result = dns_name_dup(qname, client->mctx, *anamep);
1550 if (result != ISC_R_SUCCESS) {
1551 dns_message_puttemprdataset(client->message, &rdataset);
1555 rdatalist->type = type;
1556 rdatalist->covers = 0;
1557 rdatalist->rdclass = client->message->rdclass;
1560 dns_name_toregion(tname, &r);
1561 rdata->data = r.base;
1562 rdata->length = r.length;
1563 rdata->rdclass = client->message->rdclass;
1566 ISC_LIST_INIT(rdatalist->rdata);
1567 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1568 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
1570 rdataset->trust = trust;
1572 query_addrrset(client, anamep, &rdataset, NULL, NULL,
1573 DNS_SECTION_ANSWER);
1575 if (rdataset != NULL) {
1576 if (dns_rdataset_isassociated(rdataset))
1577 dns_rdataset_disassociate(rdataset);
1578 dns_message_puttemprdataset(client->message, &rdataset);
1581 return (ISC_R_SUCCESS);
1585 query_addbestns(ns_client_t *client) {
1588 dns_name_t *fname, *zfname;
1589 dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset;
1590 isc_boolean_t is_zone, use_zone;
1592 isc_result_t result;
1593 dns_dbversion_t *version;
1597 CTRACE("query_addbestns");
1603 zsigrdataset = NULL;
1609 is_zone = ISC_FALSE;
1610 use_zone = ISC_FALSE;
1613 * Find the right database.
1615 result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0,
1616 &zone, &db, &version, &is_zone);
1617 if (result != ISC_R_SUCCESS)
1622 * We'll need some resources...
1624 dbuf = query_getnamebuf(client);
1627 fname = query_newname(client, dbuf, &b);
1628 rdataset = query_newrdataset(client);
1629 if (fname == NULL || rdataset == NULL)
1631 if (WANTDNSSEC(client)) {
1632 sigrdataset = query_newrdataset(client);
1633 if (sigrdataset == NULL)
1638 * Now look for the zonecut.
1641 result = dns_db_find(db, client->query.qname, version,
1642 dns_rdatatype_ns, client->query.dboptions,
1643 client->now, &node, fname,
1644 rdataset, sigrdataset);
1645 if (result != DNS_R_DELEGATION)
1647 if (USECACHE(client)) {
1648 query_keepname(client, fname, dbuf);
1652 zrdataset = rdataset;
1654 zsigrdataset = sigrdataset;
1656 dns_db_detachnode(db, &node);
1659 dns_db_attach(client->view->cachedb, &db);
1660 is_zone = ISC_FALSE;
1664 result = dns_db_findzonecut(db, client->query.qname,
1665 client->query.dboptions,
1666 client->now, &node, fname,
1667 rdataset, sigrdataset);
1668 if (result == ISC_R_SUCCESS) {
1669 if (zfname != NULL &&
1670 !dns_name_issubdomain(fname, zfname)) {
1672 * We found a zonecut in the cache, but our
1673 * zone delegation is better.
1675 use_zone = ISC_TRUE;
1677 } else if (result == ISC_R_NOTFOUND && zfname != NULL) {
1679 * We didn't find anything in the cache, but we
1680 * have a zone delegation, so use it.
1682 use_zone = ISC_TRUE;
1688 query_releasename(client, &fname);
1692 * We've already done query_keepname() on
1693 * zfname, so we must set dbuf to NULL to
1694 * prevent query_addrrset() from trying to
1695 * call query_keepname() again.
1698 query_putrdataset(client, &rdataset);
1699 if (sigrdataset != NULL)
1700 query_putrdataset(client, &sigrdataset);
1701 rdataset = zrdataset;
1703 sigrdataset = zsigrdataset;
1704 zsigrdataset = NULL;
1707 if ((client->query.dboptions & DNS_DBFIND_PENDINGOK) == 0 &&
1708 (rdataset->trust == dns_trust_pending ||
1709 (sigrdataset != NULL && sigrdataset->trust == dns_trust_pending)))
1712 if (WANTDNSSEC(client) && SECURE(client) &&
1713 (rdataset->trust == dns_trust_glue ||
1714 (sigrdataset != NULL && sigrdataset->trust == dns_trust_glue)))
1717 query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
1718 DNS_SECTION_AUTHORITY);
1721 if (rdataset != NULL)
1722 query_putrdataset(client, &rdataset);
1723 if (sigrdataset != NULL)
1724 query_putrdataset(client, &sigrdataset);
1726 query_releasename(client, &fname);
1728 dns_db_detachnode(db, &node);
1732 dns_zone_detach(&zone);
1734 query_putrdataset(client, &zrdataset);
1735 if (zsigrdataset != NULL)
1736 query_putrdataset(client, &zsigrdataset);
1738 query_releasename(client, &zfname);
1739 dns_db_detach(&zdb);
1744 query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node) {
1746 dns_rdataset_t *rdataset, *sigrdataset;
1747 isc_result_t result;
1749 CTRACE("query_addds");
1755 * We'll need some resources...
1757 rdataset = query_newrdataset(client);
1758 sigrdataset = query_newrdataset(client);
1759 if (rdataset == NULL || sigrdataset == NULL)
1763 * Look for the DS record, which may or may not be present.
1765 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0,
1766 client->now, rdataset, sigrdataset);
1768 * If we didn't find it, look for an NSEC. */
1769 if (result == ISC_R_NOTFOUND)
1770 result = dns_db_findrdataset(db, node, NULL,
1771 dns_rdatatype_nsec, 0, client->now,
1772 rdataset, sigrdataset);
1773 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1775 if (!dns_rdataset_isassociated(rdataset) ||
1776 !dns_rdataset_isassociated(sigrdataset))
1780 * We've already added the NS record, so if the name's not there,
1781 * we have other problems. Use this name rather than calling
1784 result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
1785 if (result != ISC_R_SUCCESS)
1789 dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
1791 result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
1792 if (result != ISC_R_SUCCESS)
1795 ISC_LIST_APPEND(rname->list, rdataset, link);
1796 ISC_LIST_APPEND(rname->list, sigrdataset, link);
1801 if (rdataset != NULL)
1802 query_putrdataset(client, &rdataset);
1803 if (sigrdataset != NULL)
1804 query_putrdataset(client, &sigrdataset);
1808 query_addwildcardproof(ns_client_t *client, dns_db_t *db,
1809 dns_name_t *name, isc_boolean_t ispositive)
1811 isc_buffer_t *dbuf, b;
1813 dns_rdataset_t *rdataset, *sigrdataset;
1814 dns_fixedname_t wfixed;
1817 unsigned int options;
1818 unsigned int olabels, nlabels;
1819 isc_result_t result;
1820 dns_rdata_t rdata = DNS_RDATA_INIT;
1821 dns_rdata_nsec_t nsec;
1822 isc_boolean_t have_wname;
1825 CTRACE("query_addwildcardproof");
1832 * Get the NOQNAME proof then if !ispositve
1833 * get the NOWILDCARD proof.
1835 * DNS_DBFIND_NOWILD finds the NSEC records that covers the
1836 * name ignoring any wildcard. From the owner and next names
1837 * of this record you can compute which wildcard (if it exists)
1838 * will match by finding the longest common suffix of the
1839 * owner name and next names with the qname and prefixing that
1840 * with the wildcard label.
1845 * example NSEC b.example
1847 * b.example NSEC a.d.example
1849 * a.d.example NSEC g.f.example
1851 * g.f.example NSEC z.i.example
1853 * z.i.example NSEC example
1856 * a.example -> example NSEC b.example
1857 * owner common example
1858 * next common example
1860 * d.b.example -> b.example NSEC a.d.example
1861 * owner common b.example
1862 * next common example
1864 * a.f.example -> a.d.example NSEC g.f.example
1865 * owner common example
1866 * next common f.example
1868 * j.example -> z.i.example NSEC example
1869 * owner common example
1870 * next common example
1873 options = client->query.dboptions | DNS_DBFIND_NOWILD;
1874 dns_fixedname_init(&wfixed);
1875 wname = dns_fixedname_name(&wfixed);
1877 have_wname = ISC_FALSE;
1879 * We'll need some resources...
1881 dbuf = query_getnamebuf(client);
1884 fname = query_newname(client, dbuf, &b);
1885 rdataset = query_newrdataset(client);
1886 sigrdataset = query_newrdataset(client);
1887 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
1890 result = dns_db_find(db, name, NULL, dns_rdatatype_nsec, options,
1891 0, &node, fname, rdataset, sigrdataset);
1893 dns_db_detachnode(db, &node);
1894 if (result == DNS_R_NXDOMAIN) {
1896 result = dns_rdataset_first(rdataset);
1897 if (result == ISC_R_SUCCESS) {
1898 dns_rdataset_current(rdataset, &rdata);
1899 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
1901 if (result == ISC_R_SUCCESS) {
1902 (void)dns_name_fullcompare(name, fname, &order,
1904 (void)dns_name_fullcompare(name, &nsec.next, &order,
1906 if (olabels > nlabels)
1907 dns_name_split(name, olabels, NULL, wname);
1909 dns_name_split(name, nlabels, NULL, wname);
1910 result = dns_name_concatenate(dns_wildcardname,
1911 wname, wname, NULL);
1912 if (result == ISC_R_SUCCESS)
1913 have_wname = ISC_TRUE;
1914 dns_rdata_freestruct(&nsec);
1916 query_addrrset(client, &fname, &rdataset, &sigrdataset,
1917 dbuf, DNS_SECTION_AUTHORITY);
1919 if (rdataset != NULL)
1920 query_putrdataset(client, &rdataset);
1921 if (sigrdataset != NULL)
1922 query_putrdataset(client, &sigrdataset);
1924 query_releasename(client, &fname);
1926 ispositive = ISC_TRUE; /* prevent loop */
1927 if (!dns_name_equal(name, wname)) {
1933 if (rdataset != NULL)
1934 query_putrdataset(client, &rdataset);
1935 if (sigrdataset != NULL)
1936 query_putrdataset(client, &sigrdataset);
1938 query_releasename(client, &fname);
1942 query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db, dns_name_t **namep,
1943 dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp)
1946 dns_rdataset_t *sigrdataset;
1947 dns_rdata_t sigrdata;
1948 dns_rdata_rrsig_t sig;
1949 unsigned int labels;
1950 isc_buffer_t *dbuf, b;
1952 isc_result_t result;
1955 if ((name->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
1956 query_addrrset(client, namep, rdatasetp, sigrdatasetp,
1957 NULL, DNS_SECTION_AUTHORITY);
1961 if (sigrdatasetp == NULL)
1963 sigrdataset = *sigrdatasetp;
1964 if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
1966 result = dns_rdataset_first(sigrdataset);
1967 if (result != ISC_R_SUCCESS)
1969 dns_rdata_init(&sigrdata);
1970 dns_rdataset_current(sigrdataset, &sigrdata);
1971 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1972 if (result != ISC_R_SUCCESS)
1975 labels = dns_name_countlabels(name);
1976 if ((unsigned int)sig.labels + 1 >= labels)
1980 query_addwildcardproof(client, db,
1981 client->query.qname,
1985 * We'll need some resources...
1987 dbuf = query_getnamebuf(client);
1990 fname = query_newname(client, dbuf, &b);
1993 dns_name_split(name, sig.labels + 1, NULL, fname);
1994 /* This will succeed, since we've stripped labels. */
1995 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,
1996 NULL) == ISC_R_SUCCESS);
1997 query_addrrset(client, &fname, rdatasetp, sigrdatasetp,
1998 dbuf, DNS_SECTION_AUTHORITY);
2002 query_resume(isc_task_t *task, isc_event_t *event) {
2003 dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
2004 ns_client_t *client;
2005 isc_boolean_t fetch_cancelled, client_shuttingdown;
2008 * Resume a query after recursion.
2013 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
2014 client = devent->ev_arg;
2015 REQUIRE(NS_CLIENT_VALID(client));
2016 REQUIRE(task == client->task);
2017 REQUIRE(RECURSING(client));
2019 LOCK(&client->query.fetchlock);
2020 if (client->query.fetch != NULL) {
2022 * This is the fetch we've been waiting for.
2024 INSIST(devent->fetch == client->query.fetch);
2025 client->query.fetch = NULL;
2026 fetch_cancelled = ISC_FALSE;
2028 * Update client->now.
2030 isc_stdtime_get(&client->now);
2033 * This is a fetch completion event for a cancelled fetch.
2034 * Clean up and don't resume the find.
2036 fetch_cancelled = ISC_TRUE;
2038 UNLOCK(&client->query.fetchlock);
2039 INSIST(client->query.fetch == NULL);
2041 client->query.attributes &= ~NS_QUERYATTR_RECURSING;
2042 dns_resolver_destroyfetch(&devent->fetch);
2045 * If this client is shutting down, or this transaction
2046 * has timed out, do not resume the find.
2048 client_shuttingdown = ns_client_shuttingdown(client);
2049 if (fetch_cancelled || client_shuttingdown) {
2050 if (devent->node != NULL)
2051 dns_db_detachnode(devent->db, &devent->node);
2052 if (devent->db != NULL)
2053 dns_db_detach(&devent->db);
2054 query_putrdataset(client, &devent->rdataset);
2055 if (devent->sigrdataset != NULL)
2056 query_putrdataset(client, &devent->sigrdataset);
2057 isc_event_free(&event);
2058 if (fetch_cancelled)
2059 query_error(client, DNS_R_SERVFAIL);
2061 query_next(client, ISC_R_CANCELED);
2063 * This may destroy the client.
2065 ns_client_detach(&client);
2067 query_find(client, devent, 0);
2072 query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
2073 dns_rdataset_t *nameservers)
2075 isc_result_t result;
2076 dns_rdataset_t *rdataset, *sigrdataset;
2078 inc_stats(client, dns_statscounter_recursion);
2081 * We are about to recurse, which means that this client will
2082 * be unavailable for serving new requests for an indeterminate
2083 * amount of time. If this client is currently responsible
2084 * for handling incoming queries, set up a new client
2085 * object to handle them while we are waiting for a
2086 * response. There is no need to replace TCP clients
2087 * because those have already been replaced when the
2088 * connection was accepted (if allowed by the TCP quota).
2090 if (client->recursionquota == NULL) {
2091 result = isc_quota_attach(&ns_g_server->recursionquota,
2092 &client->recursionquota);
2093 if (result == ISC_R_SOFTQUOTA) {
2094 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2095 NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
2096 "recursive-clients soft limit exceeded, "
2097 "aborting oldest query");
2098 ns_client_killoldestquery(client);
2099 result = ISC_R_SUCCESS;
2100 } else if (result == ISC_R_QUOTA) {
2101 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2102 NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
2103 "no more recursive clients: %s",
2104 isc_result_totext(result));
2105 ns_client_killoldestquery(client);
2107 if (result == ISC_R_SUCCESS && !client->mortal &&
2108 (client->attributes & NS_CLIENTATTR_TCP) == 0) {
2109 result = ns_client_replace(client);
2110 if (result != ISC_R_SUCCESS) {
2111 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2114 "ns_client_replace() failed: %s",
2115 isc_result_totext(result));
2116 isc_quota_detach(&client->recursionquota);
2119 if (result != ISC_R_SUCCESS)
2121 ns_client_recursing(client);
2125 * Invoke the resolver.
2127 REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
2128 REQUIRE(client->query.fetch == NULL);
2130 rdataset = query_newrdataset(client);
2131 if (rdataset == NULL)
2132 return (ISC_R_NOMEMORY);
2133 if (WANTDNSSEC(client)) {
2134 sigrdataset = query_newrdataset(client);
2135 if (sigrdataset == NULL) {
2136 query_putrdataset(client, &rdataset);
2137 return (ISC_R_NOMEMORY);
2142 if (client->query.timerset == ISC_FALSE)
2143 ns_client_settimeout(client, 60);
2144 result = dns_resolver_createfetch(client->view->resolver,
2145 client->query.qname,
2146 qtype, qdomain, nameservers,
2147 NULL, client->query.fetchoptions,
2149 query_resume, client,
2150 rdataset, sigrdataset,
2151 &client->query.fetch);
2153 if (result == ISC_R_SUCCESS) {
2155 * Record that we're waiting for an event. A client which
2156 * is shutting down will not be destroyed until all the
2157 * events have been received.
2160 query_putrdataset(client, &rdataset);
2161 if (sigrdataset != NULL)
2162 query_putrdataset(client, &sigrdataset);
2168 #define MAX_RESTARTS 16
2170 #define QUERY_ERROR(r) \
2173 want_restart = ISC_FALSE; \
2177 * Extract a network address from the RDATA of an A or AAAA
2182 * ISC_R_NOTIMPLEMENTED The rdata is not a known address type.
2185 rdata_tonetaddr(dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
2187 struct in6_addr in6a;
2189 switch (rdata->type) {
2190 case dns_rdatatype_a:
2191 INSIST(rdata->length == 4);
2192 memcpy(&ina.s_addr, rdata->data, 4);
2193 isc_netaddr_fromin(netaddr, &ina);
2194 return (ISC_R_SUCCESS);
2195 case dns_rdatatype_aaaa:
2196 INSIST(rdata->length == 16);
2197 memcpy(in6a.s6_addr, rdata->data, 16);
2198 isc_netaddr_fromin6(netaddr, &in6a);
2199 return (ISC_R_SUCCESS);
2201 return (ISC_R_NOTIMPLEMENTED);
2206 * Find the sort order of 'rdata' in the topology-like
2207 * ACL forming the second element in a 2-element top-level
2208 * sortlist statement.
2211 query_sortlist_order_2element(dns_rdata_t *rdata, void *arg) {
2212 isc_netaddr_t netaddr;
2214 if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
2216 return (ns_sortlist_addrorder2(&netaddr, arg));
2220 * Find the sort order of 'rdata' in the matching element
2221 * of a 1-element top-level sortlist statement.
2224 query_sortlist_order_1element(dns_rdata_t *rdata, void *arg) {
2225 isc_netaddr_t netaddr;
2227 if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
2229 return (ns_sortlist_addrorder1(&netaddr, arg));
2233 * Find the sortlist statement that applies to 'client' and set up
2234 * the sortlist info in in client->message appropriately.
2237 setup_query_sortlist(ns_client_t *client) {
2238 isc_netaddr_t netaddr;
2239 dns_rdatasetorderfunc_t order = NULL;
2240 void *order_arg = NULL;
2242 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2243 switch (ns_sortlist_setup(client->view->sortlist,
2244 &netaddr, &order_arg)) {
2245 case NS_SORTLISTTYPE_1ELEMENT:
2246 order = query_sortlist_order_1element;
2248 case NS_SORTLISTTYPE_2ELEMENT:
2249 order = query_sortlist_order_2element;
2251 case NS_SORTLISTTYPE_NONE:
2258 dns_message_setsortorder(client->message, order, order_arg);
2262 query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
2263 isc_buffer_t *dbuf, b;
2265 dns_rdataset_t *nsec, *nsecsig;
2266 isc_result_t result = ISC_R_NOMEMORY;
2268 CTRACE("query_addnoqnameproof");
2274 dbuf = query_getnamebuf(client);
2277 fname = query_newname(client, dbuf, &b);
2278 nsec = query_newrdataset(client);
2279 nsecsig = query_newrdataset(client);
2280 if (fname == NULL || nsec == NULL || nsecsig == NULL)
2283 result = dns_rdataset_getnoqname(rdataset, fname, nsec, nsecsig);
2284 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2286 query_addrrset(client, &fname, &nsec, &nsecsig, dbuf,
2287 DNS_SECTION_AUTHORITY);
2291 query_putrdataset(client, &nsec);
2292 if (nsecsig != NULL)
2293 query_putrdataset(client, &nsecsig);
2295 query_releasename(client, &fname);
2299 answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
2302 dns_section_t section = DNS_SECTION_ADDITIONAL;
2303 dns_rdataset_t *rdataset = NULL;
2305 msg = client->message;
2306 for (name = ISC_LIST_HEAD(msg->sections[section]);
2308 name = ISC_LIST_NEXT(name, link))
2309 if (dns_name_equal(name, client->query.qname)) {
2310 for (rdataset = ISC_LIST_HEAD(name->list);
2312 rdataset = ISC_LIST_NEXT(rdataset, link))
2313 if (rdataset->type == qtype)
2317 if (rdataset != NULL) {
2318 ISC_LIST_UNLINK(msg->sections[section], name, link);
2319 ISC_LIST_PREPEND(msg->sections[section], name, link);
2320 ISC_LIST_UNLINK(name->list, rdataset, link);
2321 ISC_LIST_PREPEND(name->list, rdataset, link);
2322 rdataset->attributes |= DNS_RDATASETATTR_REQUIREDGLUE;
2327 * Do the bulk of query processing for the current query of 'client'.
2328 * If 'event' is non-NULL, we are returning from recursion and 'qtype'
2329 * is ignored. Otherwise, 'qtype' is the query type.
2332 query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
2336 dns_rdatatype_t type;
2337 dns_name_t *fname, *zfname, *tname, *prefix;
2338 dns_rdataset_t *rdataset, *trdataset;
2339 dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset;
2340 dns_rdataset_t **sigrdatasetp;
2341 dns_rdata_t rdata = DNS_RDATA_INIT;
2342 dns_rdatasetiter_t *rdsiter;
2343 isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof;
2344 unsigned int n, nlabels;
2345 dns_namereln_t namereln;
2349 isc_result_t result, eresult;
2350 dns_fixedname_t fixed;
2351 dns_fixedname_t wildcardname;
2352 dns_dbversion_t *version;
2354 dns_rdata_cname_t cname;
2355 dns_rdata_dname_t dname;
2356 unsigned int options;
2357 isc_boolean_t empty_wild;
2358 dns_rdataset_t *noqname;
2360 CTRACE("query_find");
2363 * One-time initialization.
2365 * It's especially important to initialize anything that the cleanup
2366 * code might cleanup.
2369 eresult = ISC_R_SUCCESS;
2375 zsigrdataset = NULL;
2381 need_wildcardproof = ISC_FALSE;
2382 empty_wild = ISC_FALSE;
2385 if (event != NULL) {
2387 * We're returning from recursion. Restore the query context
2391 want_restart = ISC_FALSE;
2392 authoritative = ISC_FALSE;
2393 is_zone = ISC_FALSE;
2395 qtype = event->qtype;
2396 if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
2397 type = dns_rdatatype_any;
2402 rdataset = event->rdataset;
2403 sigrdataset = event->sigrdataset;
2406 * We'll need some resources...
2408 dbuf = query_getnamebuf(client);
2410 QUERY_ERROR(DNS_R_SERVFAIL);
2413 fname = query_newname(client, dbuf, &b);
2414 if (fname == NULL) {
2415 QUERY_ERROR(DNS_R_SERVFAIL);
2418 tname = dns_fixedname_name(&event->foundname);
2419 result = dns_name_copy(tname, fname, NULL);
2420 if (result != ISC_R_SUCCESS) {
2421 QUERY_ERROR(DNS_R_SERVFAIL);
2425 result = event->result;
2431 * Not returning from recursion.
2435 * If it's a SIG query, we'll iterate the node.
2437 if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
2438 type = dns_rdatatype_any;
2443 CTRACE("query_find: restart");
2444 want_restart = ISC_FALSE;
2445 authoritative = ISC_FALSE;
2447 need_wildcardproof = ISC_FALSE;
2449 if (client->view->checknames &&
2450 !dns_rdata_checkowner(client->query.qname,
2451 client->message->rdclass,
2452 qtype, ISC_FALSE)) {
2453 char namebuf[DNS_NAME_FORMATSIZE];
2454 char typename[DNS_RDATATYPE_FORMATSIZE];
2455 char classname[DNS_RDATACLASS_FORMATSIZE];
2457 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2458 dns_rdatatype_format(qtype, typename, sizeof(typename));
2459 dns_rdataclass_format(client->message->rdclass, classname,
2461 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2462 NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
2463 "check-names failure %s/%s/%s", namebuf,
2464 typename, classname);
2465 QUERY_ERROR(DNS_R_REFUSED);
2470 * First we must find the right database.
2473 if (dns_rdatatype_atparent(qtype) &&
2474 !dns_name_equal(client->query.qname, dns_rootname))
2475 options |= DNS_GETDB_NOEXACT;
2476 result = query_getdb(client, client->query.qname, qtype, options,
2477 &zone, &db, &version, &is_zone);
2478 if ((result != ISC_R_SUCCESS || !is_zone) && !RECURSIONOK(client) &&
2479 (options & DNS_GETDB_NOEXACT) != 0 && qtype == dns_rdatatype_ds) {
2481 * Look to see if we are authoritative for the
2482 * child zone if the query type is DS.
2484 dns_db_t *tdb = NULL;
2485 dns_zone_t *tzone = NULL;
2486 dns_dbversion_t *tversion = NULL;
2487 isc_result_t tresult;
2489 tresult = query_getzonedb(client, client->query.qname, qtype,
2490 DNS_GETDB_PARTIAL, &tzone, &tdb,
2492 if (tresult == ISC_R_SUCCESS) {
2493 options &= ~DNS_GETDB_NOEXACT;
2494 query_putrdataset(client, &rdataset);
2498 dns_zone_detach(&zone);
2503 result = ISC_R_SUCCESS;
2506 dns_db_detach(&tdb);
2508 dns_zone_detach(&tzone);
2511 if (result != ISC_R_SUCCESS) {
2512 if (result == DNS_R_REFUSED)
2513 QUERY_ERROR(DNS_R_REFUSED);
2515 QUERY_ERROR(DNS_R_SERVFAIL);
2520 authoritative = ISC_TRUE;
2522 if (event == NULL && client->query.restarts == 0) {
2524 dns_zone_attach(zone, &client->query.authzone);
2525 dns_db_attach(db, &client->query.authdb);
2527 client->query.authdbset = ISC_TRUE;
2531 CTRACE("query_find: db_find");
2533 * We'll need some resources...
2535 dbuf = query_getnamebuf(client);
2537 QUERY_ERROR(DNS_R_SERVFAIL);
2540 fname = query_newname(client, dbuf, &b);
2541 rdataset = query_newrdataset(client);
2542 if (fname == NULL || rdataset == NULL) {
2543 QUERY_ERROR(DNS_R_SERVFAIL);
2546 if (WANTDNSSEC(client)) {
2547 sigrdataset = query_newrdataset(client);
2548 if (sigrdataset == NULL) {
2549 QUERY_ERROR(DNS_R_SERVFAIL);
2555 * Now look for an answer in the database.
2557 result = dns_db_find(db, client->query.qname, version, type,
2558 client->query.dboptions, client->now,
2559 &node, fname, rdataset, sigrdataset);
2562 CTRACE("query_find: resume");
2566 * This case is handled in the main line below.
2572 * These cases are handled in the main line below.
2575 authoritative = ISC_FALSE;
2577 case ISC_R_NOTFOUND:
2579 * The cache doesn't even have the root NS. Get them from
2586 if (client->view->hints == NULL) {
2587 /* We have no hints. */
2588 result = ISC_R_FAILURE;
2590 dns_db_attach(client->view->hints, &db);
2591 result = dns_db_find(db, dns_rootname,
2592 NULL, dns_rdatatype_ns,
2593 0, client->now, &node, fname,
2594 rdataset, sigrdataset);
2596 if (result != ISC_R_SUCCESS) {
2598 * Nonsensical root hints may require cleanup.
2600 if (dns_rdataset_isassociated(rdataset))
2601 dns_rdataset_disassociate(rdataset);
2602 if (sigrdataset != NULL &&
2603 dns_rdataset_isassociated(sigrdataset))
2604 dns_rdataset_disassociate(sigrdataset);
2606 dns_db_detachnode(db, &node);
2609 * We don't have any root server hints, but
2610 * we may have working forwarders, so try to
2613 if (RECURSIONOK(client)) {
2614 result = query_recurse(client, qtype,
2616 if (result == ISC_R_SUCCESS)
2617 client->query.attributes |=
2618 NS_QUERYATTR_RECURSING;
2620 /* Unable to recurse. */
2621 QUERY_ERROR(DNS_R_SERVFAIL);
2625 /* Unable to give root server referral. */
2626 QUERY_ERROR(DNS_R_SERVFAIL);
2631 * XXXRTH We should trigger root server priming here.
2634 case DNS_R_DELEGATION:
2635 authoritative = ISC_FALSE;
2638 * Look to see if we are authoritative for the
2639 * child zone if the query type is DS.
2641 if (!RECURSIONOK(client) &&
2642 (options & DNS_GETDB_NOEXACT) != 0 &&
2643 qtype == dns_rdatatype_ds) {
2644 dns_db_t *tdb = NULL;
2645 dns_zone_t *tzone = NULL;
2646 dns_dbversion_t *tversion = NULL;
2647 result = query_getzonedb(client,
2648 client->query.qname,
2653 if (result == ISC_R_SUCCESS) {
2654 options &= ~DNS_GETDB_NOEXACT;
2655 query_putrdataset(client, &rdataset);
2656 if (sigrdataset != NULL)
2657 query_putrdataset(client,
2660 query_releasename(client,
2663 dns_db_detachnode(db, &node);
2667 dns_zone_detach(&zone);
2671 authoritative = ISC_TRUE;
2675 dns_db_detach(&tdb);
2677 dns_zone_detach(&tzone);
2680 * We're authoritative for an ancestor of QNAME.
2682 if (!USECACHE(client) || !RECURSIONOK(client)) {
2684 * If we don't have a cache, this is the best
2687 * If the client is making a nonrecursive
2688 * query we always give out the authoritative
2689 * delegation. This way even if we get
2690 * junk in our cache, we won't fail in our
2691 * role as the delegating authority if another
2692 * nameserver asks us about a delegated
2695 * We enable the retrieval of glue for this
2696 * database by setting client->query.gluedb.
2698 client->query.gluedb = db;
2699 client->query.isreferral = ISC_TRUE;
2701 * We must ensure NOADDITIONAL is off,
2702 * because the generation of
2703 * additional data is required in
2706 client->query.attributes &=
2707 ~NS_QUERYATTR_NOADDITIONAL;
2708 if (sigrdataset != NULL)
2709 sigrdatasetp = &sigrdataset;
2711 sigrdatasetp = NULL;
2712 query_addrrset(client, &fname,
2713 &rdataset, sigrdatasetp,
2714 dbuf, DNS_SECTION_AUTHORITY);
2715 client->query.gluedb = NULL;
2716 if (WANTDNSSEC(client) && dns_db_issecure(db))
2717 query_addds(client, db, node);
2720 * We might have a better answer or delegation
2721 * in the cache. We'll remember the current
2722 * values of fname, rdataset, and sigrdataset.
2723 * We'll then go looking for QNAME in the
2724 * cache. If we find something better, we'll
2727 query_keepname(client, fname, dbuf);
2731 zrdataset = rdataset;
2733 zsigrdataset = sigrdataset;
2735 dns_db_detachnode(db, &node);
2738 dns_db_attach(client->view->cachedb, &db);
2739 is_zone = ISC_FALSE;
2743 if (zfname != NULL &&
2744 !dns_name_issubdomain(fname, zfname)) {
2746 * We've already got a delegation from
2747 * authoritative data, and it is better
2748 * than what we found in the cache. Use
2749 * it instead of the cache delegation.
2751 query_releasename(client, &fname);
2755 * We've already done query_keepname() on
2756 * zfname, so we must set dbuf to NULL to
2757 * prevent query_addrrset() from trying to
2758 * call query_keepname() again.
2761 query_putrdataset(client, &rdataset);
2762 if (sigrdataset != NULL)
2763 query_putrdataset(client,
2765 rdataset = zrdataset;
2767 sigrdataset = zsigrdataset;
2768 zsigrdataset = NULL;
2770 * We don't clean up zdb here because we
2771 * may still need it. It will get cleaned
2772 * up by the main cleanup code.
2776 if (RECURSIONOK(client)) {
2780 if (dns_rdatatype_atparent(type))
2781 result = query_recurse(client, qtype,
2784 result = query_recurse(client, qtype,
2786 if (result == ISC_R_SUCCESS)
2787 client->query.attributes |=
2788 NS_QUERYATTR_RECURSING;
2790 QUERY_ERROR(DNS_R_SERVFAIL);
2793 * This is the best answer.
2795 client->query.attributes |=
2796 NS_QUERYATTR_CACHEGLUEOK;
2797 client->query.gluedb = zdb;
2798 client->query.isreferral = ISC_TRUE;
2800 * We must ensure NOADDITIONAL is off,
2801 * because the generation of
2802 * additional data is required in
2805 client->query.attributes &=
2806 ~NS_QUERYATTR_NOADDITIONAL;
2807 if (sigrdataset != NULL)
2808 sigrdatasetp = &sigrdataset;
2810 sigrdatasetp = NULL;
2811 query_addrrset(client, &fname,
2812 &rdataset, sigrdatasetp,
2813 dbuf, DNS_SECTION_AUTHORITY);
2814 client->query.gluedb = NULL;
2815 client->query.attributes &=
2816 ~NS_QUERYATTR_CACHEGLUEOK;
2817 if (WANTDNSSEC(client))
2818 query_addds(client, db, node);
2822 case DNS_R_EMPTYNAME:
2823 result = DNS_R_NXRRSET;
2827 if (dns_rdataset_isassociated(rdataset)) {
2829 * If we've got a NSEC record, we need to save the
2830 * name now because we're going call query_addsoa()
2831 * below, and it needs to use the name buffer.
2833 query_keepname(client, fname, dbuf);
2836 * We're not going to use fname, and need to release
2837 * our hold on the name buffer so query_addsoa()
2840 query_releasename(client, &fname);
2845 result = query_addsoa(client, db, ISC_FALSE);
2846 if (result != ISC_R_SUCCESS) {
2847 QUERY_ERROR(result);
2851 * Add NSEC record if we found one.
2853 if (WANTDNSSEC(client)) {
2854 if (dns_rdataset_isassociated(rdataset))
2855 query_addnxrrsetnsec(client, db, &fname,
2856 &rdataset, &sigrdataset);
2859 case DNS_R_EMPTYWILD:
2860 empty_wild = ISC_TRUE;
2862 case DNS_R_NXDOMAIN:
2864 if (dns_rdataset_isassociated(rdataset)) {
2866 * If we've got a NSEC record, we need to save the
2867 * name now because we're going call query_addsoa()
2868 * below, and it needs to use the name buffer.
2870 query_keepname(client, fname, dbuf);
2873 * We're not going to use fname, and need to release
2874 * our hold on the name buffer so query_addsoa()
2877 query_releasename(client, &fname);
2880 * Add SOA. If the query was for a SOA record force the
2881 * ttl to zero so that it is possible for clients to find
2882 * the containing zone of an arbitrary name with a stub
2883 * resolver and not have it cached.
2885 if (qtype == dns_rdatatype_soa)
2886 result = query_addsoa(client, db, ISC_TRUE);
2888 result = query_addsoa(client, db, ISC_FALSE);
2889 if (result != ISC_R_SUCCESS) {
2890 QUERY_ERROR(result);
2894 * Add NSEC record if we found one.
2896 if (dns_rdataset_isassociated(rdataset)) {
2897 if (WANTDNSSEC(client)) {
2898 query_addrrset(client, &fname, &rdataset,
2900 NULL, DNS_SECTION_AUTHORITY);
2901 query_addwildcardproof(client, db,
2902 client->query.qname,
2907 * Set message rcode.
2910 client->message->rcode = dns_rcode_noerror;
2912 client->message->rcode = dns_rcode_nxdomain;
2914 case DNS_R_NCACHENXDOMAIN:
2915 case DNS_R_NCACHENXRRSET:
2917 authoritative = ISC_FALSE;
2919 * Set message rcode, if required.
2921 if (result == DNS_R_NCACHENXDOMAIN)
2922 client->message->rcode = dns_rcode_nxdomain;
2924 * We don't call query_addrrset() because we don't need any
2925 * of its extra features (and things would probably break!).
2927 query_keepname(client, fname, dbuf);
2928 dns_message_addname(client->message, fname,
2929 DNS_SECTION_AUTHORITY);
2930 ISC_LIST_APPEND(fname->list, rdataset, link);
2936 * Keep a copy of the rdataset. We have to do this because
2937 * query_addrrset may clear 'rdataset' (to prevent the
2938 * cleanup code from cleaning it up).
2940 trdataset = rdataset;
2942 * Add the CNAME to the answer section.
2944 if (sigrdataset != NULL)
2945 sigrdatasetp = &sigrdataset;
2947 sigrdatasetp = NULL;
2948 if (WANTDNSSEC(client) &&
2949 (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
2951 dns_fixedname_init(&wildcardname);
2952 dns_name_copy(fname, dns_fixedname_name(&wildcardname),
2954 need_wildcardproof = ISC_TRUE;
2956 if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0 &&
2961 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
2962 DNS_SECTION_ANSWER);
2963 if (noqname != NULL)
2964 query_addnoqnameproof(client, noqname);
2966 * We set the PARTIALANSWER attribute so that if anything goes
2967 * wrong later on, we'll return what we've got so far.
2969 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
2971 * Reset qname to be the target name of the CNAME and restart
2975 result = dns_message_gettempname(client->message, &tname);
2976 if (result != ISC_R_SUCCESS)
2978 result = dns_rdataset_first(trdataset);
2979 if (result != ISC_R_SUCCESS) {
2980 dns_message_puttempname(client->message, &tname);
2983 dns_rdataset_current(trdataset, &rdata);
2984 result = dns_rdata_tostruct(&rdata, &cname, NULL);
2985 dns_rdata_reset(&rdata);
2986 if (result != ISC_R_SUCCESS) {
2987 dns_message_puttempname(client->message, &tname);
2990 dns_name_init(tname, NULL);
2991 result = dns_name_dup(&cname.cname, client->mctx, tname);
2992 if (result != ISC_R_SUCCESS) {
2993 dns_message_puttempname(client->message, &tname);
2994 dns_rdata_freestruct(&cname);
2997 dns_rdata_freestruct(&cname);
2998 query_maybeputqname(client);
2999 client->query.qname = tname;
3000 want_restart = ISC_TRUE;
3004 * Compare the current qname to the found name. We need
3005 * to know how many labels and bits are in common because
3006 * we're going to have to split qname later on.
3008 namereln = dns_name_fullcompare(client->query.qname, fname,
3010 INSIST(namereln == dns_namereln_subdomain);
3012 * Keep a copy of the rdataset. We have to do this because
3013 * query_addrrset may clear 'rdataset' (to prevent the
3014 * cleanup code from cleaning it up).
3016 trdataset = rdataset;
3018 * Add the DNAME to the answer section.
3020 if (sigrdataset != NULL)
3021 sigrdatasetp = &sigrdataset;
3023 sigrdatasetp = NULL;
3024 if (WANTDNSSEC(client) &&
3025 (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
3027 dns_fixedname_init(&wildcardname);
3028 dns_name_copy(fname, dns_fixedname_name(&wildcardname),
3030 need_wildcardproof = ISC_TRUE;
3032 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
3033 DNS_SECTION_ANSWER);
3035 * We set the PARTIALANSWER attribute so that if anything goes
3036 * wrong later on, we'll return what we've got so far.
3038 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
3040 * Get the target name of the DNAME.
3043 result = dns_message_gettempname(client->message, &tname);
3044 if (result != ISC_R_SUCCESS)
3046 result = dns_rdataset_first(trdataset);
3047 if (result != ISC_R_SUCCESS) {
3048 dns_message_puttempname(client->message, &tname);
3051 dns_rdataset_current(trdataset, &rdata);
3052 result = dns_rdata_tostruct(&rdata, &dname, NULL);
3053 dns_rdata_reset(&rdata);
3054 if (result != ISC_R_SUCCESS) {
3055 dns_message_puttempname(client->message, &tname);
3058 dns_name_init(tname, NULL);
3059 dns_name_clone(&dname.dname, tname);
3060 dns_rdata_freestruct(&dname);
3062 * Construct the new qname.
3064 dns_fixedname_init(&fixed);
3065 prefix = dns_fixedname_name(&fixed);
3066 dns_name_split(client->query.qname, nlabels, prefix, NULL);
3067 INSIST(fname == NULL);
3068 dbuf = query_getnamebuf(client);
3070 dns_message_puttempname(client->message, &tname);
3073 fname = query_newname(client, dbuf, &b);
3074 if (fname == NULL) {
3075 dns_message_puttempname(client->message, &tname);
3078 result = dns_name_concatenate(prefix, tname, fname, NULL);
3079 if (result != ISC_R_SUCCESS) {
3080 dns_message_puttempname(client->message, &tname);
3081 if (result == ISC_R_NOSPACE) {
3083 * RFC 2672, section 4.1, subsection 3c says
3084 * we should return YXDOMAIN if the constructed
3085 * name would be too long.
3087 client->message->rcode = dns_rcode_yxdomain;
3091 query_keepname(client, fname, dbuf);
3093 * Synthesize a CNAME for this DNAME.
3095 * We want to synthesize a CNAME since if we don't
3096 * then older software that doesn't understand DNAME
3097 * will not chain like it should.
3099 * We do not try to synthesize a signature because we hope
3100 * that security aware servers will understand DNAME. Also,
3101 * even if we had an online key, making a signature
3102 * on-the-fly is costly, and not really legitimate anyway
3103 * since the synthesized CNAME is NOT in the zone.
3105 dns_name_init(tname, NULL);
3106 (void)query_addcnamelike(client, client->query.qname, fname,
3107 trdataset->trust, &tname,
3108 dns_rdatatype_cname);
3110 dns_message_puttempname(client->message, &tname);
3112 * Switch to the new qname and restart.
3114 query_maybeputqname(client);
3115 client->query.qname = fname;
3117 want_restart = ISC_TRUE;
3121 * Something has gone wrong.
3123 QUERY_ERROR(DNS_R_SERVFAIL);
3127 if (WANTDNSSEC(client) &&
3128 (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
3130 dns_fixedname_init(&wildcardname);
3131 dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL);
3132 need_wildcardproof = ISC_TRUE;
3135 if (type == dns_rdatatype_any) {
3137 * XXXRTH Need to handle zonecuts with special case
3142 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
3143 if (result != ISC_R_SUCCESS) {
3144 QUERY_ERROR(DNS_R_SERVFAIL);
3148 * Calling query_addrrset() with a non-NULL dbuf is going
3149 * to either keep or release the name. We don't want it to
3150 * release fname, since we may have to call query_addrrset()
3151 * more than once. That means we have to call query_keepname()
3152 * now, and pass a NULL dbuf to query_addrrset().
3154 * If we do a query_addrrset() below, we must set fname to
3155 * NULL before leaving this block, otherwise we might try to
3156 * cleanup fname even though we're using it!
3158 query_keepname(client, fname, dbuf);
3160 result = dns_rdatasetiter_first(rdsiter);
3161 while (result == ISC_R_SUCCESS) {
3162 dns_rdatasetiter_current(rdsiter, rdataset);
3163 if ((qtype == dns_rdatatype_any ||
3164 rdataset->type == qtype) && rdataset->type != 0) {
3165 query_addrrset(client,
3166 fname != NULL ? &fname : &tname,
3168 NULL, DNS_SECTION_ANSWER);
3170 INSIST(tname != NULL);
3172 * rdataset is non-NULL only in certain pathological
3173 * cases involving DNAMEs.
3175 if (rdataset != NULL)
3176 query_putrdataset(client, &rdataset);
3177 rdataset = query_newrdataset(client);
3178 if (rdataset == NULL)
3182 * We're not interested in this rdataset.
3184 dns_rdataset_disassociate(rdataset);
3186 result = dns_rdatasetiter_next(rdsiter);
3190 dns_message_puttempname(client->message, &fname);
3194 * We didn't match any rdatasets.
3196 if (qtype == dns_rdatatype_rrsig &&
3197 result == ISC_R_NOMORE) {
3199 * XXXRTH If this is a secure zone and we
3200 * didn't find any SIGs, we should generate
3201 * an error unless we were searching for
3205 * We were searching for SIG records in
3206 * a nonsecure zone. Send a "no error,
3207 * no data" response.
3212 result = query_addsoa(client, db, ISC_FALSE);
3213 if (result == ISC_R_SUCCESS)
3214 result = ISC_R_NOMORE;
3217 * Something went wrong.
3219 result = DNS_R_SERVFAIL;
3222 dns_rdatasetiter_destroy(&rdsiter);
3223 if (result != ISC_R_NOMORE) {
3224 QUERY_ERROR(DNS_R_SERVFAIL);
3229 * This is the "normal" case -- an ordinary question to which
3230 * we know the answer.
3232 if (sigrdataset != NULL)
3233 sigrdatasetp = &sigrdataset;
3235 sigrdatasetp = NULL;
3236 if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0 &&
3241 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
3242 DNS_SECTION_ANSWER);
3243 if (noqname != NULL)
3244 query_addnoqnameproof(client, noqname);
3246 * We shouldn't ever fail to add 'rdataset'
3247 * because it's already in the answer.
3249 INSIST(rdataset == NULL);
3253 CTRACE("query_find: addauth");
3255 * Add NS records to the authority section (if we haven't already
3256 * added them to the answer section).
3258 if (!want_restart && !NOAUTHORITY(client)) {
3260 if (!((qtype == dns_rdatatype_ns ||
3261 qtype == dns_rdatatype_any) &&
3262 dns_name_equal(client->query.qname,
3263 dns_db_origin(db))))
3264 (void)query_addns(client, db);
3265 } else if (qtype != dns_rdatatype_ns) {
3267 query_releasename(client, &fname);
3268 query_addbestns(client);
3273 * Add NSEC records to the authority section if they're needed for
3274 * DNSSEC wildcard proofs.
3276 if (need_wildcardproof && dns_db_issecure(db))
3277 query_addwildcardproof(client, db,
3278 dns_fixedname_name(&wildcardname),
3281 CTRACE("query_find: cleanup");
3285 if (rdataset != NULL)
3286 query_putrdataset(client, &rdataset);
3287 if (sigrdataset != NULL)
3288 query_putrdataset(client, &sigrdataset);
3290 query_releasename(client, &fname);
3292 dns_db_detachnode(db, &node);
3296 dns_zone_detach(&zone);
3298 query_putrdataset(client, &zrdataset);
3299 if (zsigrdataset != NULL)
3300 query_putrdataset(client, &zsigrdataset);
3302 query_releasename(client, &zfname);
3303 dns_db_detach(&zdb);
3306 isc_event_free(ISC_EVENT_PTR(&event));
3311 if (client->query.restarts == 0 && !authoritative) {
3313 * We're not authoritative, so we must ensure the AA bit
3316 client->message->flags &= ~DNS_MESSAGEFLAG_AA;
3320 * Restart the query?
3322 if (want_restart && client->query.restarts < MAX_RESTARTS) {
3323 client->query.restarts++;
3327 if (eresult != ISC_R_SUCCESS &&
3328 (!PARTIALANSWER(client) || WANTRECURSION(client))) {
3330 * If we don't have any answer to give the client,
3331 * or if the client requested recursion and thus wanted
3332 * the complete answer, send an error response.
3334 query_error(client, eresult);
3335 ns_client_detach(&client);
3336 } else if (!RECURSING(client)) {
3338 * We are done. Set up sortlist data for the message
3339 * rendering code, make a final tweak to the AA bit if the
3340 * auth-nxdomain config option says so, then render and
3341 * send the response.
3343 setup_query_sortlist(client);
3346 * If this is a referral and the answer to the question
3347 * is in the glue sort it to the start of the additional
3350 if (client->message->counts[DNS_SECTION_ANSWER] == 0 &&
3351 client->message->rcode == dns_rcode_noerror &&
3352 (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa))
3353 answer_in_glue(client, qtype);
3355 if (client->message->rcode == dns_rcode_nxdomain &&
3356 client->view->auth_nxdomain == ISC_TRUE)
3357 client->message->flags |= DNS_MESSAGEFLAG_AA;
3360 ns_client_detach(&client);
3362 CTRACE("query_find: done");
3366 log_query(ns_client_t *client) {
3367 char namebuf[DNS_NAME_FORMATSIZE];
3368 char typename[DNS_RDATATYPE_FORMATSIZE];
3369 char classname[DNS_RDATACLASS_FORMATSIZE];
3370 dns_rdataset_t *rdataset;
3371 int level = ISC_LOG_INFO;
3373 if (! isc_log_wouldlog(ns_g_lctx, level))
3376 rdataset = ISC_LIST_HEAD(client->query.qname->list);
3377 INSIST(rdataset != NULL);
3378 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
3379 dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname));
3380 dns_rdatatype_format(rdataset->type, typename, sizeof(typename));
3382 ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
3383 level, "query: %s %s %s %s%s%s", namebuf, classname,
3384 typename, WANTRECURSION(client) ? "+" : "-",
3385 (client->signer != NULL) ? "S": "",
3386 (client->opt != NULL) ? "E" : "");
3390 ns_query_start(ns_client_t *client) {
3391 isc_result_t result;
3392 dns_message_t *message = client->message;
3393 dns_rdataset_t *rdataset;
3394 ns_client_t *qclient;
3395 dns_rdatatype_t qtype;
3397 CTRACE("ns_query_start");
3400 * Ensure that appropriate cleanups occur.
3402 client->next = query_next_callback;
3405 * Behave as if we don't support DNSSEC if not enabled.
3407 if (!client->view->enablednssec) {
3408 message->flags &= ~DNS_MESSAGEFLAG_CD;
3409 client->extflags &= ~DNS_MESSAGEEXTFLAG_DO;
3412 if ((message->flags & DNS_MESSAGEFLAG_RD) != 0)
3413 client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
3415 if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0)
3416 client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
3418 if (client->view->minimalresponses)
3419 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
3420 NS_QUERYATTR_NOADDITIONAL);
3422 if ((client->view->cachedb == NULL)
3423 || (!client->view->additionalfromcache)) {
3425 * We don't have a cache. Turn off cache support and
3428 client->query.attributes &=
3429 ~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK);
3430 } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
3431 (message->flags & DNS_MESSAGEFLAG_RD) == 0) {
3433 * If the client isn't allowed to recurse (due to
3434 * "recursion no", the allow-recursion ACL, or the
3435 * lack of a resolver in this view), or if it
3436 * doesn't want recursion, turn recursion off.
3438 client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
3442 * Get the question name.
3444 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
3445 if (result != ISC_R_SUCCESS) {
3446 query_error(client, result);
3449 dns_message_currentname(message, DNS_SECTION_QUESTION,
3450 &client->query.qname);
3451 client->query.origqname = client->query.qname;
3452 result = dns_message_nextname(message, DNS_SECTION_QUESTION);
3453 if (result != ISC_R_NOMORE) {
3454 if (result == ISC_R_SUCCESS) {
3456 * There's more than one QNAME in the question
3459 query_error(client, DNS_R_FORMERR);
3461 query_error(client, result);
3465 if (ns_g_server->log_queries)
3469 * Check for multiple question queries, since edns1 is dead.
3471 if (message->counts[DNS_SECTION_QUESTION] > 1) {
3472 query_error(client, DNS_R_FORMERR);
3477 * Check for meta-queries like IXFR and AXFR.
3479 rdataset = ISC_LIST_HEAD(client->query.qname->list);
3480 INSIST(rdataset != NULL);
3481 qtype = rdataset->type;
3482 if (dns_rdatatype_ismeta(qtype)) {
3484 case dns_rdatatype_any:
3485 break; /* Let query_find handle it. */
3486 case dns_rdatatype_ixfr:
3487 case dns_rdatatype_axfr:
3488 ns_xfr_start(client, rdataset->type);
3490 case dns_rdatatype_maila:
3491 case dns_rdatatype_mailb:
3492 query_error(client, DNS_R_NOTIMP);
3494 case dns_rdatatype_tkey:
3495 result = dns_tkey_processquery(client->message,
3496 ns_g_server->tkeyctx,
3497 client->view->dynamickeys);
3498 if (result == ISC_R_SUCCESS)
3501 query_error(client, result);
3503 default: /* TSIG, etc. */
3504 query_error(client, DNS_R_FORMERR);
3510 * If the client has requested that DNSSEC checking be disabled,
3511 * allow lookups to return pending data and instruct the resolver
3512 * to return data before validation has completed.
3514 if (message->flags & DNS_MESSAGEFLAG_CD ||
3515 qtype == dns_rdatatype_rrsig)
3517 client->query.dboptions |= DNS_DBFIND_PENDINGOK;
3518 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
3522 * Allow glue NS records to be added to the authority section
3523 * if the answer is secure.
3525 if (message->flags & DNS_MESSAGEFLAG_CD)
3526 client->query.attributes &= ~NS_QUERYATTR_SECURE;
3529 * This is an ordinary query.
3531 result = dns_message_reply(message, ISC_TRUE);
3532 if (result != ISC_R_SUCCESS) {
3533 query_next(client, result);
3538 * Assume authoritative response until it is known to be
3541 message->flags |= DNS_MESSAGEFLAG_AA;
3544 * Set AD. We must clear it if we add non-validated data to a
3547 if (client->view->enablednssec)
3548 message->flags |= DNS_MESSAGEFLAG_AD;
3551 ns_client_attach(client, &qclient);
3552 query_find(qclient, NULL, qtype);