2 * Copyright (C) 2004 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.19 2004/04/15 02:16:25 marka Exp $ */
28 #include <dns/byaddr.h>
30 #include <dns/events.h>
31 #include <dns/message.h>
32 #include <dns/rdata.h>
33 #include <dns/rdataclass.h>
34 #include <dns/rdatalist.h>
35 #include <dns/rdataset.h>
36 #include <dns/rdatasetiter.h>
37 #include <dns/rdatastruct.h>
38 #include <dns/rdatatype.h>
39 #include <dns/resolver.h>
40 #include <dns/result.h>
41 #include <dns/stats.h>
47 #include <named/client.h>
48 #include <named/log.h>
49 #include <named/server.h>
50 #include <named/sortlist.h>
51 #include <named/xfrout.h>
53 #define PARTIALANSWER(c) (((c)->query.attributes & \
54 NS_QUERYATTR_PARTIALANSWER) != 0)
55 #define USECACHE(c) (((c)->query.attributes & \
56 NS_QUERYATTR_CACHEOK) != 0)
57 #define RECURSIONOK(c) (((c)->query.attributes & \
58 NS_QUERYATTR_RECURSIONOK) != 0)
59 #define RECURSING(c) (((c)->query.attributes & \
60 NS_QUERYATTR_RECURSING) != 0)
61 #define CACHEGLUEOK(c) (((c)->query.attributes & \
62 NS_QUERYATTR_CACHEGLUEOK) != 0)
63 #define WANTRECURSION(c) (((c)->query.attributes & \
64 NS_QUERYATTR_WANTRECURSION) != 0)
65 #define WANTDNSSEC(c) (((c)->query.attributes & \
66 NS_QUERYATTR_WANTDNSSEC) != 0)
67 #define NOAUTHORITY(c) (((c)->query.attributes & \
68 NS_QUERYATTR_NOAUTHORITY) != 0)
69 #define NOADDITIONAL(c) (((c)->query.attributes & \
70 NS_QUERYATTR_NOADDITIONAL) != 0)
73 #define CTRACE(m) isc_log_write(ns_g_lctx, \
74 NS_LOGCATEGORY_CLIENT, \
77 "client %p: %s", client, (m))
78 #define QTRACE(m) isc_log_write(ns_g_lctx, \
79 NS_LOGCATEGORY_GENERAL, \
82 "query %p: %s", query, (m))
84 #define CTRACE(m) ((void)m)
85 #define QTRACE(m) ((void)m)
88 #define DNS_GETDB_NOEXACT 0x01U
89 #define DNS_GETDB_NOLOG 0x02U
91 static unsigned char ip6int_ndata
[] = "\003ip6\003int";
92 static unsigned char ip6int_offsets
[] = { 0, 4, 8 };
94 static dns_name_t ip6int_name
= {
97 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
99 {(void *)-1, (void *)-1},
104 query_simplefind(void *arg
, dns_name_t
*name
, dns_rdatatype_t type
,
106 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
);
109 query_adda6rrset(void *arg
, dns_name_t
*name
, dns_rdataset_t
*rdataset
,
110 dns_rdataset_t
*sigrdataset
);
113 query_find(ns_client_t
*client
, dns_fetchevent_t
*event
, dns_rdatatype_t qtype
);
116 synth_fwd_start(ns_client_t
*client
);
119 synth_fwd_startfind(ns_client_t
*client
);
122 synth_fwd_respond(ns_client_t
*client
, dns_adbfind_t
*find
);
125 synth_fwd_finddone(isc_task_t
*task
, isc_event_t
*ev
);
128 synth_finish(ns_client_t
*client
, isc_result_t result
);
131 synth_rev_start(ns_client_t
*client
);
134 synth_rev_byaddrdone_arpa(isc_task_t
*task
, isc_event_t
*event
);
137 synth_rev_byaddrdone_int(isc_task_t
*task
, isc_event_t
*event
);
140 synth_rev_respond(ns_client_t
*client
, dns_byaddrevent_t
*bevent
);
143 * Increment query statistics counters.
146 inc_stats(ns_client_t
*client
, dns_statscounter_t counter
) {
147 dns_zone_t
*zone
= client
->query
.authzone
;
149 REQUIRE(counter
< DNS_STATS_NCOUNTERS
);
151 ns_g_server
->querystats
[counter
]++;
154 isc_uint64_t
*zonestats
= dns_zone_getstatscounters(zone
);
155 if (zonestats
!= NULL
)
156 zonestats
[counter
]++;
161 query_send(ns_client_t
*client
) {
162 dns_statscounter_t counter
;
163 if (client
->message
->rcode
== dns_rcode_noerror
) {
164 if (ISC_LIST_EMPTY(client
->message
->sections
[DNS_SECTION_ANSWER
])) {
165 if (client
->query
.isreferral
) {
166 counter
= dns_statscounter_referral
;
168 counter
= dns_statscounter_nxrrset
;
171 counter
= dns_statscounter_success
;
173 } else if (client
->message
->rcode
== dns_rcode_nxdomain
) {
174 counter
= dns_statscounter_nxdomain
;
176 /* We end up here in case of YXDOMAIN, and maybe others */
177 counter
= dns_statscounter_failure
;
179 inc_stats(client
, counter
);
180 ns_client_send(client
);
184 query_error(ns_client_t
*client
, isc_result_t result
) {
185 inc_stats(client
, dns_statscounter_failure
);
186 ns_client_error(client
, result
);
190 query_next(ns_client_t
*client
, isc_result_t result
) {
191 inc_stats(client
, dns_statscounter_failure
);
192 ns_client_next(client
, result
);
196 query_maybeputqname(ns_client_t
*client
) {
197 if (client
->query
.restarts
> 0) {
199 * client->query.qname was dynamically allocated.
201 dns_message_puttempname(client
->message
,
202 &client
->query
.qname
);
203 client
->query
.qname
= NULL
;
208 query_reset(ns_client_t
*client
, isc_boolean_t everything
) {
209 isc_buffer_t
*dbuf
, *dbuf_next
;
210 ns_dbversion_t
*dbversion
, *dbversion_next
;
214 * Reset the query state of a client to its default state.
218 * Cancel the fetch if it's running.
220 if (client
->query
.fetch
!= NULL
) {
221 dns_resolver_cancelfetch(client
->query
.fetch
);
223 client
->query
.fetch
= NULL
;
227 * Cleanup any active versions.
229 for (dbversion
= ISC_LIST_HEAD(client
->query
.activeversions
);
231 dbversion
= dbversion_next
) {
232 dbversion_next
= ISC_LIST_NEXT(dbversion
, link
);
233 dns_db_closeversion(dbversion
->db
, &dbversion
->version
,
235 dns_db_detach(&dbversion
->db
);
236 ISC_LIST_INITANDAPPEND(client
->query
.freeversions
,
239 ISC_LIST_INIT(client
->query
.activeversions
);
241 if (client
->query
.authdb
!= NULL
)
242 dns_db_detach(&client
->query
.authdb
);
243 if (client
->query
.authzone
!= NULL
)
244 dns_zone_detach(&client
->query
.authzone
);
247 * Clean up free versions.
249 for (dbversion
= ISC_LIST_HEAD(client
->query
.freeversions
), i
= 0;
251 dbversion
= dbversion_next
, i
++) {
252 dbversion_next
= ISC_LIST_NEXT(dbversion
, link
);
254 * If we're not freeing everything, we keep the first three
255 * dbversions structures around.
257 if (i
> 3 || everything
) {
258 ISC_LIST_UNLINK(client
->query
.freeversions
, dbversion
,
260 isc_mem_put(client
->mctx
, dbversion
,
265 for (dbuf
= ISC_LIST_HEAD(client
->query
.namebufs
);
268 dbuf_next
= ISC_LIST_NEXT(dbuf
, link
);
269 if (dbuf_next
!= NULL
|| everything
) {
270 ISC_LIST_UNLINK(client
->query
.namebufs
, dbuf
, link
);
271 isc_buffer_free(&dbuf
);
275 query_maybeputqname(client
);
277 client
->query
.attributes
= (NS_QUERYATTR_RECURSIONOK
|
278 NS_QUERYATTR_CACHEOK
);
279 client
->query
.restarts
= 0;
280 client
->query
.timerset
= ISC_FALSE
;
281 client
->query
.origqname
= NULL
;
282 client
->query
.qname
= NULL
;
283 client
->query
.dboptions
= 0;
284 client
->query
.fetchoptions
= 0;
285 client
->query
.gluedb
= NULL
;
286 client
->query
.authdbset
= ISC_FALSE
;
287 client
->query
.isreferral
= ISC_FALSE
;
291 query_next_callback(ns_client_t
*client
) {
292 query_reset(client
, ISC_FALSE
);
296 ns_query_free(ns_client_t
*client
) {
297 query_reset(client
, ISC_TRUE
);
300 static inline isc_result_t
301 query_newnamebuf(ns_client_t
*client
) {
305 CTRACE("query_newnamebuf");
307 * Allocate a name buffer.
311 result
= isc_buffer_allocate(client
->mctx
, &dbuf
, 1024);
312 if (result
!= ISC_R_SUCCESS
) {
313 CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
316 ISC_LIST_APPEND(client
->query
.namebufs
, dbuf
, link
);
318 CTRACE("query_newnamebuf: done");
319 return (ISC_R_SUCCESS
);
322 static inline isc_buffer_t
*
323 query_getnamebuf(ns_client_t
*client
) {
328 CTRACE("query_getnamebuf");
330 * Return a name buffer with space for a maximal name, allocating
331 * a new one if necessary.
334 if (ISC_LIST_EMPTY(client
->query
.namebufs
)) {
335 result
= query_newnamebuf(client
);
336 if (result
!= ISC_R_SUCCESS
) {
337 CTRACE("query_getnamebuf: query_newnamebuf failed: done");
342 dbuf
= ISC_LIST_TAIL(client
->query
.namebufs
);
343 INSIST(dbuf
!= NULL
);
344 isc_buffer_availableregion(dbuf
, &r
);
345 if (r
.length
< 255) {
346 result
= query_newnamebuf(client
);
347 if (result
!= ISC_R_SUCCESS
) {
348 CTRACE("query_getnamebuf: query_newnamebuf failed: done");
352 dbuf
= ISC_LIST_TAIL(client
->query
.namebufs
);
353 isc_buffer_availableregion(dbuf
, &r
);
354 INSIST(r
.length
>= 255);
356 CTRACE("query_getnamebuf: done");
361 query_keepname(ns_client_t
*client
, dns_name_t
*name
, isc_buffer_t
*dbuf
) {
364 CTRACE("query_keepname");
366 * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
367 * adjusted to take account of that. We do the adjustment.
370 REQUIRE((client
->query
.attributes
& NS_QUERYATTR_NAMEBUFUSED
) != 0);
372 dns_name_toregion(name
, &r
);
373 isc_buffer_add(dbuf
, r
.length
);
374 dns_name_setbuffer(name
, NULL
);
375 client
->query
.attributes
&= ~NS_QUERYATTR_NAMEBUFUSED
;
379 query_releasename(ns_client_t
*client
, dns_name_t
**namep
) {
380 dns_name_t
*name
= *namep
;
383 * 'name' is no longer needed. Return it to our pool of temporary
384 * names. If it is using a name buffer, relinquish its exclusive
385 * rights on the buffer.
388 CTRACE("query_releasename");
389 if (dns_name_hasbuffer(name
)) {
390 INSIST((client
->query
.attributes
& NS_QUERYATTR_NAMEBUFUSED
)
392 client
->query
.attributes
&= ~NS_QUERYATTR_NAMEBUFUSED
;
394 dns_message_puttempname(client
->message
, namep
);
395 CTRACE("query_releasename: done");
398 static inline dns_name_t
*
399 query_newname(ns_client_t
*client
, isc_buffer_t
*dbuf
,
406 REQUIRE((client
->query
.attributes
& NS_QUERYATTR_NAMEBUFUSED
) == 0);
408 CTRACE("query_newname");
410 result
= dns_message_gettempname(client
->message
, &name
);
411 if (result
!= ISC_R_SUCCESS
) {
412 CTRACE("query_newname: dns_message_gettempname failed: done");
415 isc_buffer_availableregion(dbuf
, &r
);
416 isc_buffer_init(nbuf
, r
.base
, r
.length
);
417 dns_name_init(name
, NULL
);
418 dns_name_setbuffer(name
, nbuf
);
419 client
->query
.attributes
|= NS_QUERYATTR_NAMEBUFUSED
;
421 CTRACE("query_newname: done");
425 static inline dns_rdataset_t
*
426 query_newrdataset(ns_client_t
*client
) {
427 dns_rdataset_t
*rdataset
;
430 CTRACE("query_newrdataset");
432 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
433 if (result
!= ISC_R_SUCCESS
) {
434 CTRACE("query_newrdataset: "
435 "dns_message_gettemprdataset failed: done");
438 dns_rdataset_init(rdataset
);
440 CTRACE("query_newrdataset: done");
445 query_putrdataset(ns_client_t
*client
, dns_rdataset_t
**rdatasetp
) {
446 dns_rdataset_t
*rdataset
= *rdatasetp
;
448 CTRACE("query_putrdataset");
449 if (rdataset
!= NULL
) {
450 if (dns_rdataset_isassociated(rdataset
))
451 dns_rdataset_disassociate(rdataset
);
452 dns_message_puttemprdataset(client
->message
, rdatasetp
);
454 CTRACE("query_putrdataset: done");
458 static inline isc_result_t
459 query_newdbversion(ns_client_t
*client
, unsigned int n
) {
461 ns_dbversion_t
*dbversion
;
463 for (i
= 0; i
< n
; i
++) {
464 dbversion
= isc_mem_get(client
->mctx
, sizeof *dbversion
);
465 if (dbversion
!= NULL
) {
466 dbversion
->db
= NULL
;
467 dbversion
->version
= NULL
;
468 ISC_LIST_INITANDAPPEND(client
->query
.freeversions
,
472 * We only return ISC_R_NOMEMORY if we couldn't
476 return (ISC_R_NOMEMORY
);
478 return (ISC_R_SUCCESS
);
482 return (ISC_R_SUCCESS
);
485 static inline ns_dbversion_t
*
486 query_getdbversion(ns_client_t
*client
) {
488 ns_dbversion_t
*dbversion
;
490 if (ISC_LIST_EMPTY(client
->query
.freeversions
)) {
491 result
= query_newdbversion(client
, 1);
492 if (result
!= ISC_R_SUCCESS
)
495 dbversion
= ISC_LIST_HEAD(client
->query
.freeversions
);
496 INSIST(dbversion
!= NULL
);
497 ISC_LIST_UNLINK(client
->query
.freeversions
, dbversion
, link
);
503 ns_query_init(ns_client_t
*client
) {
506 ISC_LIST_INIT(client
->query
.namebufs
);
507 ISC_LIST_INIT(client
->query
.activeversions
);
508 ISC_LIST_INIT(client
->query
.freeversions
);
509 client
->query
.restarts
= 0;
510 client
->query
.timerset
= ISC_FALSE
;
511 client
->query
.qname
= NULL
;
512 client
->query
.fetch
= NULL
;
513 client
->query
.authdb
= NULL
;
514 client
->query
.authzone
= NULL
;
515 client
->query
.authdbset
= ISC_FALSE
;
516 client
->query
.isreferral
= ISC_FALSE
;
517 query_reset(client
, ISC_FALSE
);
518 result
= query_newdbversion(client
, 3);
519 if (result
!= ISC_R_SUCCESS
)
521 dns_a6_init(&client
->query
.a6ctx
, query_simplefind
, query_adda6rrset
,
523 return (query_newnamebuf(client
));
526 static inline ns_dbversion_t
*
527 query_findversion(ns_client_t
*client
, dns_db_t
*db
,
528 isc_boolean_t
*newzonep
)
530 ns_dbversion_t
*dbversion
;
533 * We may already have done a query related to this
534 * database. If so, we must be sure to make subsequent
535 * queries from the same version.
537 for (dbversion
= ISC_LIST_HEAD(client
->query
.activeversions
);
539 dbversion
= ISC_LIST_NEXT(dbversion
, link
)) {
540 if (dbversion
->db
== db
)
544 if (dbversion
== NULL
) {
546 * This is a new zone for this query. Add it to
549 dbversion
= query_getdbversion(client
);
550 if (dbversion
== NULL
)
552 dns_db_attach(db
, &dbversion
->db
);
553 dns_db_currentversion(db
, &dbversion
->version
);
554 dbversion
->queryok
= ISC_FALSE
;
555 ISC_LIST_APPEND(client
->query
.activeversions
,
557 *newzonep
= ISC_TRUE
;
559 *newzonep
= ISC_FALSE
;
564 static inline isc_result_t
565 query_getzonedb(ns_client_t
*client
, dns_name_t
*name
, unsigned int options
,
566 dns_zone_t
**zonep
, dns_db_t
**dbp
, dns_dbversion_t
**versionp
)
569 isc_boolean_t check_acl
, new_zone
;
571 ns_dbversion_t
*dbversion
;
572 unsigned int ztoptions
;
573 dns_zone_t
*zone
= NULL
;
576 REQUIRE(zonep
!= NULL
&& *zonep
== NULL
);
577 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
580 * Find a zone database to answer the query.
582 ztoptions
= ((options
& DNS_GETDB_NOEXACT
) != 0) ?
583 DNS_ZTFIND_NOEXACT
: 0;
585 result
= dns_zt_find(client
->view
->zonetable
, name
, ztoptions
, NULL
,
587 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
588 result
= dns_zone_getdb(zone
, &db
);
590 if (result
!= ISC_R_SUCCESS
)
594 * This limits our searching to the zone where the first name
595 * (the query target) was looked for. This prevents following
596 * CNAMES or DNAMES into other zones and prevents returning
597 * additional data from other zones.
599 if (!client
->view
->additionalfromauth
&&
600 client
->query
.authdbset
&&
601 db
!= client
->query
.authdb
)
605 * If the zone has an ACL, we'll check it, otherwise
606 * we use the view's "allow-query" ACL. Each ACL is only checked
609 * Also, get the database version to use.
612 check_acl
= ISC_TRUE
; /* Keep compiler happy. */
616 * Get the current version of this database.
618 dbversion
= query_findversion(client
, db
, &new_zone
);
619 if (dbversion
== NULL
) {
620 result
= DNS_R_SERVFAIL
;
624 check_acl
= ISC_TRUE
;
625 } else if (!dbversion
->queryok
) {
628 check_acl
= ISC_FALSE
;
631 queryacl
= dns_zone_getqueryacl(zone
);
632 if (queryacl
== NULL
) {
633 queryacl
= client
->view
->queryacl
;
634 if ((client
->query
.attributes
&
635 NS_QUERYATTR_QUERYOKVALID
) != 0) {
637 * We've evaluated the view's queryacl already. If
638 * NS_QUERYATTR_QUERYOK is set, then the client is
639 * allowed to make queries, otherwise the query should
642 check_acl
= ISC_FALSE
;
643 if ((client
->query
.attributes
&
644 NS_QUERYATTR_QUERYOK
) == 0)
648 * We haven't evaluated the view's queryacl yet.
650 check_acl
= ISC_TRUE
;
655 isc_boolean_t log
= ISC_TF((options
& DNS_GETDB_NOLOG
) == 0);
657 result
= ns_client_checkaclsilent(client
, queryacl
, ISC_TRUE
);
659 char msg
[DNS_NAME_FORMATSIZE
+ DNS_RDATACLASS_FORMATSIZE
660 + sizeof "query '/'"];
661 if (result
== ISC_R_SUCCESS
) {
662 if (isc_log_wouldlog(ns_g_lctx
,
665 ns_client_aclmsg("query", name
,
666 client
->view
->rdclass
,
668 ns_client_log(client
,
669 DNS_LOGCATEGORY_SECURITY
,
675 ns_client_aclmsg("query", name
,
676 client
->view
->rdclass
,
678 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
679 NS_LOGMODULE_QUERY
, ISC_LOG_INFO
,
684 if (queryacl
== client
->view
->queryacl
) {
685 if (result
== ISC_R_SUCCESS
) {
687 * We were allowed by the default
688 * "allow-query" ACL. Remember this so we
689 * don't have to check again.
691 client
->query
.attributes
|=
692 NS_QUERYATTR_QUERYOK
;
695 * We've now evaluated the view's query ACL, and
696 * the NS_QUERYATTR_QUERYOK attribute is now valid.
698 client
->query
.attributes
|= NS_QUERYATTR_QUERYOKVALID
;
701 if (result
!= ISC_R_SUCCESS
)
708 * Remember the result of the ACL check so we
709 * don't have to check again.
711 dbversion
->queryok
= ISC_TRUE
;
713 /* Transfer ownership. */
716 *versionp
= dbversion
->version
;
718 return (ISC_R_SUCCESS
);
721 result
= DNS_R_REFUSED
;
724 dns_zone_detach(&zone
);
731 static inline isc_result_t
732 query_getcachedb(ns_client_t
*client
, dns_db_t
**dbp
, unsigned int options
)
735 isc_boolean_t check_acl
;
738 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
741 * Find a cache database to answer the query.
742 * This may fail with DNS_R_REFUSED if the client
743 * is not allowed to use the cache.
746 if (!USECACHE(client
))
747 return (DNS_R_REFUSED
);
748 dns_db_attach(client
->view
->cachedb
, &db
);
750 if ((client
->query
.attributes
&
751 NS_QUERYATTR_QUERYOKVALID
) != 0) {
753 * We've evaluated the view's queryacl already. If
754 * NS_QUERYATTR_QUERYOK is set, then the client is
755 * allowed to make queries, otherwise the query should
758 check_acl
= ISC_FALSE
;
759 if ((client
->query
.attributes
&
760 NS_QUERYATTR_QUERYOK
) == 0)
764 * We haven't evaluated the view's queryacl yet.
766 check_acl
= ISC_TRUE
;
770 isc_boolean_t log
= ISC_TF((options
& DNS_GETDB_NOLOG
) == 0);
772 result
= ns_client_checkacl(client
, "query (cache)",
773 client
->view
->queryacl
,
777 if (result
== ISC_R_SUCCESS
) {
779 * We were allowed by the default
780 * "allow-query" ACL. Remember this so we
781 * don't have to check again.
783 client
->query
.attributes
|=
784 NS_QUERYATTR_QUERYOK
;
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
, unsigned int options
,
815 dns_zone_t
**zonep
, dns_db_t
**dbp
, dns_dbversion_t
**versionp
,
816 isc_boolean_t
*is_zonep
)
820 result
= query_getzonedb(client
, name
, options
, zonep
, dbp
, versionp
);
821 if (result
== ISC_R_SUCCESS
) {
822 *is_zonep
= ISC_TRUE
;
823 } else if (result
== ISC_R_NOTFOUND
) {
824 result
= query_getcachedb(client
, dbp
, options
);
825 *is_zonep
= ISC_FALSE
;
831 query_simplefind(void *arg
, dns_name_t
*name
, dns_rdatatype_t type
,
833 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
835 ns_client_t
*client
= arg
;
837 dns_fixedname_t foundname
;
839 dns_dbversion_t
*version
;
840 unsigned int dboptions
;
841 isc_boolean_t is_zone
;
842 dns_rdataset_t zrdataset
, zsigrdataset
;
845 REQUIRE(NS_CLIENT_VALID(client
));
846 REQUIRE(rdataset
!= NULL
);
848 dns_rdataset_init(&zrdataset
);
849 if (sigrdataset
!= NULL
)
850 dns_rdataset_init(&zsigrdataset
);
853 * Find a database to answer the query.
858 result
= query_getdb(client
, name
, 0, &zone
, &db
, &version
, &is_zone
);
859 if (result
!= ISC_R_SUCCESS
)
864 * Now look for an answer in the database.
866 dns_fixedname_init(&foundname
);
867 dboptions
= client
->query
.dboptions
;
868 if (db
== client
->query
.gluedb
|| (!is_zone
&& CACHEGLUEOK(client
)))
869 dboptions
|= DNS_DBFIND_GLUEOK
;
870 result
= dns_db_find(db
, name
, version
, type
, dboptions
,
871 now
, NULL
, dns_fixedname_name(&foundname
),
872 rdataset
, sigrdataset
);
873 if (result
== DNS_R_DELEGATION
||
874 result
== ISC_R_NOTFOUND
) {
875 if (dns_rdataset_isassociated(rdataset
))
876 dns_rdataset_disassociate(rdataset
);
877 if (sigrdataset
!= NULL
&&
878 dns_rdataset_isassociated(sigrdataset
))
879 dns_rdataset_disassociate(sigrdataset
);
881 if (USECACHE(client
)) {
883 * Either the answer is in the cache, or we
889 dns_db_attach(client
->view
->cachedb
, &db
);
894 * We don't have the data in the cache. If we've got
895 * glue from the zone, use it.
897 if (dns_rdataset_isassociated(&zrdataset
)) {
898 dns_rdataset_clone(&zrdataset
, rdataset
);
899 if (sigrdataset
!= NULL
&&
900 dns_rdataset_isassociated(&zsigrdataset
))
901 dns_rdataset_clone(&zsigrdataset
,
903 result
= ISC_R_SUCCESS
;
908 * We don't know the answer.
910 result
= ISC_R_NOTFOUND
;
911 } else if (result
== DNS_R_GLUE
) {
912 if (USECACHE(client
) && RECURSIONOK(client
)) {
914 * We found an answer, but the cache may be better.
915 * Remember what we've got and go look in the cache.
919 dns_rdataset_clone(rdataset
, &zrdataset
);
920 dns_rdataset_disassociate(rdataset
);
921 if (sigrdataset
!= NULL
&&
922 dns_rdataset_isassociated(sigrdataset
))
924 dns_rdataset_clone(sigrdataset
, &zsigrdataset
);
925 dns_rdataset_disassociate(sigrdataset
);
928 dns_db_attach(client
->view
->cachedb
, &db
);
932 * Otherwise, the glue is the best answer.
934 result
= ISC_R_SUCCESS
;
935 } else if (result
!= ISC_R_SUCCESS
) {
936 if (dns_rdataset_isassociated(rdataset
))
937 dns_rdataset_disassociate(rdataset
);
938 if (sigrdataset
!= NULL
&&
939 dns_rdataset_isassociated(sigrdataset
))
940 dns_rdataset_disassociate(sigrdataset
);
941 result
= ISC_R_NOTFOUND
;
944 * If we get here, the result is ISC_R_SUCCESS, and we found the
945 * answer we were looking for in the zone.
949 if (dns_rdataset_isassociated(&zrdataset
)) {
950 dns_rdataset_disassociate(&zrdataset
);
951 if (sigrdataset
!= NULL
&&
952 dns_rdataset_isassociated(&zsigrdataset
))
953 dns_rdataset_disassociate(&zsigrdataset
);
958 dns_zone_detach(&zone
);
963 static inline isc_boolean_t
964 query_isduplicate(ns_client_t
*client
, dns_name_t
*name
,
965 dns_rdatatype_t type
, dns_name_t
**mnamep
)
967 dns_section_t section
;
968 dns_name_t
*mname
= NULL
;
971 CTRACE("query_isduplicate");
973 for (section
= DNS_SECTION_ANSWER
;
974 section
<= DNS_SECTION_ADDITIONAL
;
976 result
= dns_message_findname(client
->message
, section
,
977 name
, type
, 0, &mname
, NULL
);
978 if (result
== ISC_R_SUCCESS
) {
980 * We've already got this RRset in the response.
982 CTRACE("query_isduplicate: true: done");
984 } else if (result
== DNS_R_NXRRSET
) {
986 * The name exists, but the rdataset does not.
988 if (section
== DNS_SECTION_ADDITIONAL
)
991 RUNTIME_CHECK(result
== DNS_R_NXDOMAIN
);
996 * If the dns_name_t we're looking up is already in the message,
997 * we don't want to trigger the caller's name replacement logic.
1004 CTRACE("query_isduplicate: false: done");
1009 query_addadditional(void *arg
, dns_name_t
*name
, dns_rdatatype_t qtype
) {
1010 ns_client_t
*client
= arg
;
1011 isc_result_t result
, eresult
;
1014 dns_name_t
*fname
, *mname
;
1015 dns_rdataset_t
*rdataset
, *sigrdataset
, *a6rdataset
, *trdataset
;
1018 dns_dbversion_t
*version
;
1019 isc_boolean_t added_something
, need_addname
;
1021 dns_rdatatype_t type
;
1023 REQUIRE(NS_CLIENT_VALID(client
));
1024 REQUIRE(qtype
!= dns_rdatatype_any
);
1026 if (!WANTDNSSEC(client
) && dns_rdatatype_isdnssec(qtype
))
1027 return (ISC_R_SUCCESS
);
1029 CTRACE("query_addadditional");
1034 eresult
= ISC_R_SUCCESS
;
1043 added_something
= ISC_FALSE
;
1044 need_addname
= ISC_FALSE
;
1048 * We treat type A additional section processing as if it
1049 * were "any address type" additional section processing.
1050 * To avoid multiple lookups, we do an 'any' database
1051 * lookup and iterate over the node.
1053 if (qtype
== dns_rdatatype_a
)
1054 type
= dns_rdatatype_any
;
1059 * Get some resources.
1061 dbuf
= query_getnamebuf(client
);
1064 fname
= query_newname(client
, dbuf
, &b
);
1065 rdataset
= query_newrdataset(client
);
1066 if (fname
== NULL
|| rdataset
== NULL
)
1068 if (WANTDNSSEC(client
)) {
1069 sigrdataset
= query_newrdataset(client
);
1070 if (sigrdataset
== NULL
)
1075 * Look for a zone database that might contain authoritative
1078 result
= query_getzonedb(client
, name
, DNS_GETDB_NOLOG
,
1079 &zone
, &db
, &version
);
1080 if (result
!= ISC_R_SUCCESS
)
1083 CTRACE("query_addadditional: db_find");
1086 * Since we are looking for authoritative data, we do not set
1087 * the GLUEOK flag. Glue will be looked for later, but not
1088 * necessarily in the same database.
1091 result
= dns_db_find(db
, name
, version
, type
, client
->query
.dboptions
,
1092 client
->now
, &node
, fname
, rdataset
,
1094 if (result
== ISC_R_SUCCESS
)
1097 if (dns_rdataset_isassociated(rdataset
))
1098 dns_rdataset_disassociate(rdataset
);
1099 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
))
1100 dns_rdataset_disassociate(sigrdataset
);
1102 dns_db_detachnode(db
, &node
);
1107 * No authoritative data was found. The cache is our next best bet.
1111 result
= query_getcachedb(client
, &db
, DNS_GETDB_NOLOG
);
1112 if (result
!= ISC_R_SUCCESS
)
1114 * Most likely the client isn't allowed to query the cache.
1118 result
= dns_db_find(db
, name
, version
, type
, client
->query
.dboptions
,
1119 client
->now
, &node
, fname
, rdataset
,
1121 if (result
== ISC_R_SUCCESS
)
1124 if (dns_rdataset_isassociated(rdataset
))
1125 dns_rdataset_disassociate(rdataset
);
1126 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
))
1127 dns_rdataset_disassociate(sigrdataset
);
1129 dns_db_detachnode(db
, &node
);
1134 * No cached data was found. Glue is our last chance.
1137 * NS records cause both the usual additional section
1138 * processing to locate a type A record, and, when used
1139 * in a referral, a special search of the zone in which
1140 * they reside for glue information.
1142 * This is the "special search". Note that we must search
1143 * the zone where the NS record resides, not the zone it
1144 * points to, and that we only do the search in the delegation
1145 * case (identified by client->query.gluedb being set).
1148 if (client
->query
.gluedb
== NULL
)
1152 * Don't poision caches using the bailiwick protection model.
1154 if (!dns_name_issubdomain(name
, dns_db_origin(client
->query
.gluedb
)))
1157 dns_db_attach(client
->query
.gluedb
, &db
);
1158 result
= dns_db_find(db
, name
, version
, type
,
1159 client
->query
.dboptions
| DNS_DBFIND_GLUEOK
,
1160 client
->now
, &node
, fname
, rdataset
,
1162 if (!(result
== ISC_R_SUCCESS
||
1163 result
== DNS_R_ZONECUT
||
1164 result
== DNS_R_GLUE
))
1169 * We have found a potential additional data rdataset, or
1170 * at least a node to iterate over.
1172 query_keepname(client
, fname
, dbuf
);
1175 * If we have an rdataset, add it to the additional data
1179 if (dns_rdataset_isassociated(rdataset
) &&
1180 !query_isduplicate(client
, fname
, type
, &mname
)) {
1181 if (mname
!= NULL
) {
1182 query_releasename(client
, &fname
);
1185 need_addname
= ISC_TRUE
;
1186 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1187 trdataset
= rdataset
;
1189 added_something
= ISC_TRUE
;
1191 * Note: we only add SIGs if we've added the type they cover,
1192 * so we do not need to check if the SIG rdataset is already
1195 if (sigrdataset
!= NULL
&&
1196 dns_rdataset_isassociated(sigrdataset
))
1198 ISC_LIST_APPEND(fname
->list
, sigrdataset
, link
);
1203 if (qtype
== dns_rdatatype_a
) {
1205 * We now go looking for A, A6, and AAAA records, along with
1208 * XXXRTH This code could be more efficient.
1210 if (rdataset
!= NULL
) {
1211 if (dns_rdataset_isassociated(rdataset
))
1212 dns_rdataset_disassociate(rdataset
);
1214 rdataset
= query_newrdataset(client
);
1215 if (rdataset
== NULL
)
1218 if (sigrdataset
!= NULL
) {
1219 if (dns_rdataset_isassociated(sigrdataset
))
1220 dns_rdataset_disassociate(sigrdataset
);
1221 } else if (WANTDNSSEC(client
)) {
1222 sigrdataset
= query_newrdataset(client
);
1223 if (sigrdataset
== NULL
)
1226 result
= dns_db_findrdataset(db
, node
, version
,
1228 client
->now
, rdataset
,
1230 if (result
== DNS_R_NCACHENXDOMAIN
)
1232 if (result
== DNS_R_NCACHENXRRSET
) {
1233 dns_rdataset_disassociate(rdataset
);
1235 * Negative cache entries don't have sigrdatasets.
1237 INSIST(sigrdataset
== NULL
||
1238 ! dns_rdataset_isassociated(sigrdataset
));
1240 if (result
== ISC_R_SUCCESS
) {
1242 if (!query_isduplicate(client
, fname
,
1243 dns_rdatatype_a
, &mname
)) {
1244 if (mname
!= NULL
) {
1245 query_releasename(client
, &fname
);
1248 need_addname
= ISC_TRUE
;
1249 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1250 added_something
= ISC_TRUE
;
1251 if (sigrdataset
!= NULL
&&
1252 dns_rdataset_isassociated(sigrdataset
))
1254 ISC_LIST_APPEND(fname
->list
,
1257 query_newrdataset(client
);
1259 rdataset
= query_newrdataset(client
);
1260 if (rdataset
== NULL
)
1262 if (WANTDNSSEC(client
) && sigrdataset
== NULL
)
1265 dns_rdataset_disassociate(rdataset
);
1266 if (sigrdataset
!= NULL
&&
1267 dns_rdataset_isassociated(sigrdataset
))
1268 dns_rdataset_disassociate(sigrdataset
);
1271 result
= dns_db_findrdataset(db
, node
, version
,
1272 dns_rdatatype_a6
, 0,
1273 client
->now
, rdataset
,
1275 if (result
== DNS_R_NCACHENXDOMAIN
)
1277 if (result
== DNS_R_NCACHENXRRSET
) {
1278 dns_rdataset_disassociate(rdataset
);
1279 INSIST(sigrdataset
== NULL
||
1280 ! dns_rdataset_isassociated(sigrdataset
));
1282 if (result
== ISC_R_SUCCESS
) {
1284 if (!query_isduplicate(client
, fname
,
1285 dns_rdatatype_a6
, &mname
)) {
1286 if (mname
!= NULL
) {
1287 query_releasename(client
, &fname
);
1290 need_addname
= ISC_TRUE
;
1291 a6rdataset
= rdataset
;
1292 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1293 added_something
= ISC_TRUE
;
1294 if (sigrdataset
!= NULL
&&
1295 dns_rdataset_isassociated(sigrdataset
))
1297 ISC_LIST_APPEND(fname
->list
,
1300 query_newrdataset(client
);
1302 rdataset
= query_newrdataset(client
);
1303 if (rdataset
== NULL
)
1305 if (WANTDNSSEC(client
) && sigrdataset
== NULL
)
1308 dns_rdataset_disassociate(rdataset
);
1309 if (sigrdataset
!= NULL
&&
1310 dns_rdataset_isassociated(sigrdataset
))
1311 dns_rdataset_disassociate(sigrdataset
);
1314 result
= dns_db_findrdataset(db
, node
, version
,
1315 dns_rdatatype_aaaa
, 0,
1316 client
->now
, rdataset
,
1318 if (result
== DNS_R_NCACHENXDOMAIN
)
1320 if (result
== DNS_R_NCACHENXRRSET
) {
1321 dns_rdataset_disassociate(rdataset
);
1322 INSIST(sigrdataset
== NULL
||
1323 ! dns_rdataset_isassociated(sigrdataset
));
1325 if (result
== ISC_R_SUCCESS
) {
1327 if (!query_isduplicate(client
, fname
,
1328 dns_rdatatype_aaaa
, &mname
)) {
1329 if (mname
!= NULL
) {
1330 query_releasename(client
, &fname
);
1333 need_addname
= ISC_TRUE
;
1334 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1335 added_something
= ISC_TRUE
;
1336 if (sigrdataset
!= NULL
&&
1337 dns_rdataset_isassociated(sigrdataset
))
1339 ISC_LIST_APPEND(fname
->list
,
1349 CTRACE("query_addadditional: addname");
1351 * If we haven't added anything, then we're done.
1353 if (!added_something
)
1357 * We may have added our rdatasets to an existing name, if so, then
1358 * need_addname will be ISC_FALSE. Whether we used an existing name
1359 * or a new one, we must set fname to NULL to prevent cleanup.
1362 dns_message_addname(client
->message
, fname
,
1363 DNS_SECTION_ADDITIONAL
);
1367 * In a few cases, we want to add additional data for additional
1368 * data. It's simpler to just deal with special cases here than
1369 * to try to create a general purpose mechanism and allow the
1370 * rdata implementations to do it themselves.
1372 * This involves recursion, but the depth is limited. The
1373 * most complex case is adding a SRV rdataset, which involves
1374 * recursing to add address records, which in turn can cause
1375 * recursion to add KEYs.
1377 if (type
== dns_rdatatype_a
|| type
== dns_rdatatype_aaaa
) {
1379 * RFC 2535 section 3.5 says that when A or AAAA records are
1380 * retrieved as additional data, any KEY RRs for the owner name
1381 * should be added to the additional data section. Note: we
1382 * do NOT include A6 in the list of types with such treatment
1383 * in additional data because we'd have to do it for each A6
1386 * XXXRTH We should lower the priority here. Alternatively,
1387 * we could raise the priority of glue records.
1389 eresult
= query_addadditional(client
, name
, dns_rdatatype_key
);
1390 } else if (type
== dns_rdatatype_srv
&& trdataset
!= NULL
) {
1392 * If we're adding SRV records to the additional data
1393 * section, it's helpful if we add the SRV additional data
1396 eresult
= dns_rdataset_additionaldata(trdataset
,
1397 query_addadditional
,
1402 * If we added an A6 rdataset, we should also add everything we
1403 * know about the A6 chains. We wait until now to do this so that
1404 * they'll come after any additional data added above.
1406 if (a6rdataset
!= NULL
) {
1407 dns_a6_reset(&client
->query
.a6ctx
);
1408 dns_a6_foreach(&client
->query
.a6ctx
, a6rdataset
, client
->now
);
1412 CTRACE("query_addadditional: cleanup");
1413 query_putrdataset(client
, &rdataset
);
1414 if (sigrdataset
!= NULL
)
1415 query_putrdataset(client
, &sigrdataset
);
1417 query_releasename(client
, &fname
);
1419 dns_db_detachnode(db
, &node
);
1423 dns_zone_detach(&zone
);
1425 CTRACE("query_addadditional: done");
1430 query_adda6rrset(void *arg
, dns_name_t
*name
, dns_rdataset_t
*rdataset
,
1431 dns_rdataset_t
*sigrdataset
)
1433 ns_client_t
*client
= arg
;
1434 dns_rdataset_t
*crdataset
, *csigrdataset
;
1435 isc_buffer_t b
, *dbuf
;
1436 dns_name_t
*fname
, *mname
;
1439 * Add an rrset to the additional data section.
1442 REQUIRE(NS_CLIENT_VALID(client
));
1443 REQUIRE(rdataset
->type
== dns_rdatatype_a6
);
1446 * Get some resources...
1450 csigrdataset
= NULL
;
1451 dbuf
= query_getnamebuf(client
);
1454 fname
= query_newname(client
, dbuf
, &b
);
1455 crdataset
= query_newrdataset(client
);
1456 if (fname
== NULL
|| crdataset
== NULL
)
1458 if (sigrdataset
!= NULL
) {
1459 csigrdataset
= query_newrdataset(client
);
1460 if (csigrdataset
== NULL
)
1464 if (dns_name_copy(name
, fname
, NULL
) != ISC_R_SUCCESS
)
1466 dns_rdataset_clone(rdataset
, crdataset
);
1467 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
))
1468 dns_rdataset_clone(sigrdataset
, csigrdataset
);
1471 if (query_isduplicate(client
, fname
, crdataset
->type
, &mname
))
1473 if (mname
!= NULL
) {
1474 query_releasename(client
, &fname
);
1477 query_keepname(client
, fname
, dbuf
);
1478 dns_message_addname(client
->message
, fname
,
1479 DNS_SECTION_ADDITIONAL
);
1482 ISC_LIST_APPEND(fname
->list
, crdataset
, link
);
1485 * Note: we only add SIGs if we've added the type they cover, so
1486 * we do not need to check if the SIG rdataset is already in the
1489 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(csigrdataset
)) {
1490 ISC_LIST_APPEND(fname
->list
, csigrdataset
, link
);
1491 csigrdataset
= NULL
;
1497 * In spite of RFC 2535 section 3.5, we don't currently try to add
1498 * KEY RRs for the A6 records. It's just too much work.
1502 query_putrdataset(client
, &crdataset
);
1503 if (sigrdataset
!= NULL
)
1504 query_putrdataset(client
, &csigrdataset
);
1506 query_releasename(client
, &fname
);
1510 query_addrdataset(ns_client_t
*client
, dns_name_t
*fname
,
1511 dns_rdataset_t
*rdataset
)
1513 dns_rdatatype_t type
= rdataset
->type
;
1516 * Add 'rdataset' and any pertinent additional data to
1517 * 'fname', a name in the response message for 'client'.
1520 CTRACE("query_addrdataset");
1522 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
1524 if (NOADDITIONAL(client
))
1528 * Add additional data.
1530 * We don't care if dns_a6_foreach or dns_rdataset_additionaldata()
1533 if (type
== dns_rdatatype_a6
) {
1534 dns_a6_reset(&client
->query
.a6ctx
);
1535 (void)dns_a6_foreach(&client
->query
.a6ctx
, rdataset
,
1538 (void)dns_rdataset_additionaldata(rdataset
,
1539 query_addadditional
, client
);
1541 * RFC 2535 section 3.5 says that when NS, SOA, A, or AAAA records
1542 * are retrieved, any KEY RRs for the owner name should be added
1543 * to the additional data section. We treat A6 records the same way.
1545 * We don't care if query_addadditional() fails.
1547 if (type
== dns_rdatatype_ns
|| type
== dns_rdatatype_soa
||
1548 type
== dns_rdatatype_a
|| type
== dns_rdatatype_aaaa
||
1549 type
== dns_rdatatype_a6
) {
1551 * XXXRTH We should lower the priority here. Alternatively,
1552 * we could raise the priority of glue records.
1554 (void)query_addadditional(client
, fname
, dns_rdatatype_key
);
1556 CTRACE("query_addrdataset: done");
1560 query_addrrset(ns_client_t
*client
, dns_name_t
**namep
,
1561 dns_rdataset_t
**rdatasetp
, dns_rdataset_t
**sigrdatasetp
,
1562 isc_buffer_t
*dbuf
, dns_section_t section
)
1564 dns_name_t
*name
, *mname
;
1565 dns_rdataset_t
*rdataset
, *mrdataset
, *sigrdataset
;
1566 isc_result_t result
;
1569 * To the current response for 'client', add the answer RRset
1570 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
1571 * owner name '*namep', to section 'section', unless they are
1572 * already there. Also add any pertinent additional data.
1574 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
1575 * stored in 'dbuf'. In this case, query_addrrset() guarantees that
1576 * when it returns the name will either have been kept or released.
1578 CTRACE("query_addrrset");
1580 rdataset
= *rdatasetp
;
1581 if (sigrdatasetp
!= NULL
)
1582 sigrdataset
= *sigrdatasetp
;
1587 result
= dns_message_findname(client
->message
, section
,
1588 name
, rdataset
->type
, rdataset
->covers
,
1589 &mname
, &mrdataset
);
1590 if (result
== ISC_R_SUCCESS
) {
1592 * We've already got an RRset of the given name and type.
1593 * There's nothing else to do;
1595 CTRACE("query_addrrset: dns_message_findname succeeded: done");
1597 query_releasename(client
, namep
);
1599 } else if (result
== DNS_R_NXDOMAIN
) {
1601 * The name doesn't exist.
1604 query_keepname(client
, name
, dbuf
);
1605 dns_message_addname(client
->message
, name
, section
);
1609 RUNTIME_CHECK(result
== DNS_R_NXRRSET
);
1611 query_releasename(client
, namep
);
1615 * Note: we only add SIGs if we've added the type they cover, so
1616 * we do not need to check if the SIG rdataset is already in the
1619 query_addrdataset(client
, mname
, rdataset
);
1621 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(sigrdataset
)) {
1623 * We have a signature. Add it to the response.
1625 ISC_LIST_APPEND(mname
->list
, sigrdataset
, link
);
1626 *sigrdatasetp
= NULL
;
1628 CTRACE("query_addrrset: done");
1631 static inline isc_result_t
1632 query_addsoa(ns_client_t
*client
, dns_db_t
*db
, isc_boolean_t zero_ttl
) {
1633 dns_name_t
*name
, *fname
;
1635 isc_result_t result
, eresult
;
1636 dns_fixedname_t foundname
;
1637 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
1638 dns_rdataset_t
**sigrdatasetp
= NULL
;
1640 CTRACE("query_addsoa");
1644 eresult
= ISC_R_SUCCESS
;
1648 dns_fixedname_init(&foundname
);
1649 fname
= dns_fixedname_name(&foundname
);
1652 * Get resources and make 'name' be the database origin.
1654 result
= dns_message_gettempname(client
->message
, &name
);
1655 if (result
!= ISC_R_SUCCESS
)
1657 dns_name_init(name
, NULL
);
1658 dns_name_clone(dns_db_origin(db
), name
);
1659 rdataset
= query_newrdataset(client
);
1660 if (rdataset
== NULL
) {
1661 eresult
= DNS_R_SERVFAIL
;
1664 if (WANTDNSSEC(client
)) {
1665 sigrdataset
= query_newrdataset(client
);
1666 if (sigrdataset
== NULL
) {
1667 eresult
= DNS_R_SERVFAIL
;
1675 result
= dns_db_find(db
, name
, NULL
, dns_rdatatype_soa
,
1676 client
->query
.dboptions
, 0, &node
,
1677 fname
, rdataset
, sigrdataset
);
1678 if (result
!= ISC_R_SUCCESS
) {
1680 * This is bad. We tried to get the SOA RR at the zone top
1681 * and it didn't work!
1683 eresult
= DNS_R_SERVFAIL
;
1686 * Extract the SOA MINIMUM.
1688 dns_rdata_soa_t soa
;
1689 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1690 result
= dns_rdataset_first(rdataset
);
1691 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1692 dns_rdataset_current(rdataset
, &rdata
);
1693 dns_rdata_tostruct(&rdata
, &soa
, NULL
);
1697 if (sigrdataset
!= NULL
)
1698 sigrdataset
->ttl
= 0;
1702 * Add the SOA and its SIG to the response, with the
1703 * TTLs adjusted per RFC2308 section 3.
1705 if (rdataset
->ttl
> soa
.minimum
)
1706 rdataset
->ttl
= soa
.minimum
;
1707 if (sigrdataset
!= NULL
&& sigrdataset
->ttl
> soa
.minimum
)
1708 sigrdataset
->ttl
= soa
.minimum
;
1710 if (sigrdataset
!= NULL
)
1711 sigrdatasetp
= &sigrdataset
;
1713 sigrdatasetp
= NULL
;
1714 query_addrrset(client
, &name
, &rdataset
, sigrdatasetp
, NULL
,
1715 DNS_SECTION_AUTHORITY
);
1719 query_putrdataset(client
, &rdataset
);
1720 if (sigrdataset
!= NULL
)
1721 query_putrdataset(client
, &sigrdataset
);
1723 query_releasename(client
, &name
);
1725 dns_db_detachnode(db
, &node
);
1730 static inline isc_result_t
1731 query_addns(ns_client_t
*client
, dns_db_t
*db
) {
1732 dns_name_t
*name
, *fname
;
1734 isc_result_t result
, eresult
;
1735 dns_fixedname_t foundname
;
1736 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
1737 dns_rdataset_t
**sigrdatasetp
= NULL
;
1739 CTRACE("query_addns");
1743 eresult
= ISC_R_SUCCESS
;
1747 dns_fixedname_init(&foundname
);
1748 fname
= dns_fixedname_name(&foundname
);
1751 * Get resources and make 'name' be the database origin.
1753 result
= dns_message_gettempname(client
->message
, &name
);
1754 if (result
!= ISC_R_SUCCESS
) {
1755 CTRACE("query_addns: dns_message_gettempname failed: done");
1758 dns_name_init(name
, NULL
);
1759 dns_name_clone(dns_db_origin(db
), name
);
1760 rdataset
= query_newrdataset(client
);
1761 if (rdataset
== NULL
) {
1762 CTRACE("query_addns: query_newrdataset failed");
1763 eresult
= DNS_R_SERVFAIL
;
1766 if (WANTDNSSEC(client
)) {
1767 sigrdataset
= query_newrdataset(client
);
1768 if (sigrdataset
== NULL
) {
1769 CTRACE("query_addns: query_newrdataset failed");
1770 eresult
= DNS_R_SERVFAIL
;
1776 * Find the NS rdataset.
1778 CTRACE("query_addns: calling dns_db_find");
1779 result
= dns_db_find(db
, name
, NULL
, dns_rdatatype_ns
,
1780 client
->query
.dboptions
, 0, &node
,
1781 fname
, rdataset
, sigrdataset
);
1782 CTRACE("query_addns: dns_db_find complete");
1783 if (result
!= ISC_R_SUCCESS
) {
1784 CTRACE("query_addns: dns_db_find failed");
1786 * This is bad. We tried to get the NS rdataset at the zone
1787 * top and it didn't work!
1789 eresult
= DNS_R_SERVFAIL
;
1791 if (sigrdataset
!= NULL
)
1792 sigrdatasetp
= &sigrdataset
;
1794 sigrdatasetp
= NULL
;
1795 query_addrrset(client
, &name
, &rdataset
, sigrdatasetp
, NULL
,
1796 DNS_SECTION_AUTHORITY
);
1800 CTRACE("query_addns: cleanup");
1801 query_putrdataset(client
, &rdataset
);
1802 if (sigrdataset
!= NULL
)
1803 query_putrdataset(client
, &sigrdataset
);
1805 query_releasename(client
, &name
);
1807 dns_db_detachnode(db
, &node
);
1809 CTRACE("query_addns: done");
1813 static inline isc_result_t
1814 query_addcnamelike(ns_client_t
*client
, dns_name_t
*qname
, dns_name_t
*tname
,
1815 dns_ttl_t ttl
, dns_name_t
**anamep
, dns_rdatatype_t type
)
1817 dns_rdataset_t
*rdataset
;
1818 dns_rdatalist_t
*rdatalist
;
1820 isc_result_t result
;
1824 * We assume the name data referred to by tname won't go away.
1827 REQUIRE(anamep
!= NULL
);
1830 result
= dns_message_gettemprdatalist(client
->message
, &rdatalist
);
1831 if (result
!= ISC_R_SUCCESS
)
1834 result
= dns_message_gettemprdata(client
->message
, &rdata
);
1835 if (result
!= ISC_R_SUCCESS
)
1838 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
1839 if (result
!= ISC_R_SUCCESS
)
1841 dns_rdataset_init(rdataset
);
1842 result
= dns_name_dup(qname
, client
->mctx
, *anamep
);
1843 if (result
!= ISC_R_SUCCESS
) {
1844 dns_message_puttemprdataset(client
->message
, &rdataset
);
1848 rdatalist
->type
= type
;
1849 rdatalist
->covers
= 0;
1850 rdatalist
->rdclass
= client
->message
->rdclass
;
1851 rdatalist
->ttl
= ttl
;
1853 dns_name_toregion(tname
, &r
);
1854 rdata
->data
= r
.base
;
1855 rdata
->length
= r
.length
;
1856 rdata
->rdclass
= client
->message
->rdclass
;
1859 ISC_LIST_INIT(rdatalist
->rdata
);
1860 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1861 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1863 query_addrrset(client
, anamep
, &rdataset
, NULL
, NULL
,
1864 DNS_SECTION_ANSWER
);
1866 if (rdataset
!= NULL
) {
1867 if (dns_rdataset_isassociated(rdataset
))
1868 dns_rdataset_disassociate(rdataset
);
1869 dns_message_puttemprdataset(client
->message
, &rdataset
);
1872 return (ISC_R_SUCCESS
);
1876 query_addbestns(ns_client_t
*client
) {
1879 dns_name_t
*fname
, *zfname
;
1880 dns_rdataset_t
*rdataset
, *sigrdataset
, *zrdataset
, *zsigrdataset
;
1881 isc_boolean_t is_zone
, use_zone
;
1883 isc_result_t result
;
1884 dns_dbversion_t
*version
;
1888 CTRACE("query_addbestns");
1894 zsigrdataset
= NULL
;
1900 is_zone
= ISC_FALSE
;
1901 use_zone
= ISC_FALSE
;
1904 * Find the right database.
1906 result
= query_getdb(client
, client
->query
.qname
, 0, &zone
, &db
,
1907 &version
, &is_zone
);
1908 if (result
!= ISC_R_SUCCESS
)
1913 * We'll need some resources...
1915 dbuf
= query_getnamebuf(client
);
1918 fname
= query_newname(client
, dbuf
, &b
);
1919 rdataset
= query_newrdataset(client
);
1920 if (fname
== NULL
|| rdataset
== NULL
)
1922 if (WANTDNSSEC(client
)) {
1923 sigrdataset
= query_newrdataset(client
);
1924 if (sigrdataset
== NULL
)
1929 * Now look for the zonecut.
1932 result
= dns_db_find(db
, client
->query
.qname
, version
,
1933 dns_rdatatype_ns
, client
->query
.dboptions
,
1934 client
->now
, &node
, fname
,
1935 rdataset
, sigrdataset
);
1936 if (result
!= DNS_R_DELEGATION
)
1938 if (USECACHE(client
)) {
1939 query_keepname(client
, fname
, dbuf
);
1943 zrdataset
= rdataset
;
1945 zsigrdataset
= sigrdataset
;
1947 dns_db_detachnode(db
, &node
);
1950 dns_db_attach(client
->view
->cachedb
, &db
);
1951 is_zone
= ISC_FALSE
;
1955 result
= dns_db_findzonecut(db
, client
->query
.qname
,
1956 client
->query
.dboptions
,
1957 client
->now
, &node
, fname
,
1958 rdataset
, sigrdataset
);
1959 if (result
== ISC_R_SUCCESS
) {
1960 if (zfname
!= NULL
&&
1961 !dns_name_issubdomain(fname
, zfname
)) {
1963 * We found a zonecut in the cache, but our
1964 * zone delegation is better.
1966 use_zone
= ISC_TRUE
;
1968 } else if (result
== ISC_R_NOTFOUND
&& zfname
!= NULL
) {
1970 * We didn't find anything in the cache, but we
1971 * have a zone delegation, so use it.
1973 use_zone
= ISC_TRUE
;
1979 query_releasename(client
, &fname
);
1983 * We've already done query_keepname() on
1984 * zfname, so we must set dbuf to NULL to
1985 * prevent query_addrrset() from trying to
1986 * call query_keepname() again.
1989 query_putrdataset(client
, &rdataset
);
1990 if (sigrdataset
!= NULL
)
1991 query_putrdataset(client
, &sigrdataset
);
1992 rdataset
= zrdataset
;
1994 sigrdataset
= zsigrdataset
;
1995 zsigrdataset
= NULL
;
1998 if ((client
->query
.dboptions
& DNS_DBFIND_PENDINGOK
) == 0 &&
1999 (rdataset
->trust
== dns_trust_pending
||
2000 (sigrdataset
!= NULL
&& sigrdataset
->trust
== dns_trust_pending
)))
2003 query_addrrset(client
, &fname
, &rdataset
, &sigrdataset
, dbuf
,
2004 DNS_SECTION_AUTHORITY
);
2007 if (rdataset
!= NULL
)
2008 query_putrdataset(client
, &rdataset
);
2009 if (sigrdataset
!= NULL
)
2010 query_putrdataset(client
, &sigrdataset
);
2012 query_releasename(client
, &fname
);
2014 dns_db_detachnode(db
, &node
);
2018 dns_zone_detach(&zone
);
2020 query_putrdataset(client
, &zrdataset
);
2021 if (zsigrdataset
!= NULL
)
2022 query_putrdataset(client
, &zsigrdataset
);
2024 query_releasename(client
, &zfname
);
2025 dns_db_detach(&zdb
);
2030 query_resume(isc_task_t
*task
, isc_event_t
*event
) {
2031 dns_fetchevent_t
*devent
= (dns_fetchevent_t
*)event
;
2032 ns_client_t
*client
;
2033 isc_boolean_t fetch_cancelled
, client_shuttingdown
;
2036 * Resume a query after recursion.
2041 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
2042 client
= devent
->ev_arg
;
2043 REQUIRE(NS_CLIENT_VALID(client
));
2044 REQUIRE(task
== client
->task
);
2045 REQUIRE(RECURSING(client
));
2047 if (devent
->fetch
!= NULL
) {
2049 * This is the fetch we've been waiting for.
2051 INSIST(devent
->fetch
== client
->query
.fetch
);
2052 client
->query
.fetch
= NULL
;
2053 fetch_cancelled
= ISC_FALSE
;
2055 * Update client->now.
2057 isc_stdtime_get(&client
->now
);
2060 * This is a fetch completion event for a cancelled fetch.
2061 * Clean up and don't resume the find.
2063 fetch_cancelled
= ISC_TRUE
;
2065 INSIST(client
->query
.fetch
== NULL
);
2067 client
->query
.attributes
&= ~NS_QUERYATTR_RECURSING
;
2068 dns_resolver_destroyfetch(&devent
->fetch
);
2071 * If this client is shutting down, or this transaction
2072 * has timed out, do not resume the find.
2074 client_shuttingdown
= ns_client_shuttingdown(client
);
2075 if (fetch_cancelled
|| client_shuttingdown
) {
2076 if (devent
->node
!= NULL
)
2077 dns_db_detachnode(devent
->db
, &devent
->node
);
2078 if (devent
->db
!= NULL
)
2079 dns_db_detach(&devent
->db
);
2080 query_putrdataset(client
, &devent
->rdataset
);
2081 if (devent
->sigrdataset
!= NULL
)
2082 query_putrdataset(client
, &devent
->sigrdataset
);
2083 isc_event_free(&event
);
2084 query_next(client
, ISC_R_CANCELED
);
2086 * This may destroy the client.
2088 ns_client_detach(&client
);
2090 query_find(client
, devent
, 0);
2095 query_recurse(ns_client_t
*client
, dns_rdatatype_t qtype
, dns_name_t
*qdomain
,
2096 dns_rdataset_t
*nameservers
)
2098 isc_result_t result
;
2099 dns_rdataset_t
*rdataset
, *sigrdataset
;
2101 inc_stats(client
, dns_statscounter_recursion
);
2104 * We are about to recurse, which means that this client will
2105 * be unavailable for serving new requests for an indeterminate
2106 * amount of time. If this client is currently responsible
2107 * for handling incoming queries, set up a new client
2108 * object to handle them while we are waiting for a
2109 * response. There is no need to replace TCP clients
2110 * because those have already been replaced when the
2111 * connection was accepted (if allowed by the TCP quota).
2113 if (client
->recursionquota
== NULL
) {
2114 result
= isc_quota_attach(&ns_g_server
->recursionquota
,
2115 &client
->recursionquota
);
2116 if (result
== ISC_R_SUCCESS
&& !client
->mortal
&&
2117 (client
->attributes
& NS_CLIENTATTR_TCP
) == 0)
2118 result
= ns_client_replace(client
);
2119 if (result
!= ISC_R_SUCCESS
) {
2120 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2121 NS_LOGMODULE_QUERY
, ISC_LOG_WARNING
,
2122 "no more recursive clients: %s",
2123 isc_result_totext(result
));
2129 * Invoke the resolver.
2131 REQUIRE(nameservers
== NULL
|| nameservers
->type
== dns_rdatatype_ns
);
2132 REQUIRE(client
->query
.fetch
== NULL
);
2134 rdataset
= query_newrdataset(client
);
2135 if (rdataset
== NULL
)
2136 return (ISC_R_NOMEMORY
);
2137 if (WANTDNSSEC(client
)) {
2138 sigrdataset
= query_newrdataset(client
);
2139 if (sigrdataset
== NULL
) {
2140 query_putrdataset(client
, &rdataset
);
2141 return (ISC_R_NOMEMORY
);
2146 if (client
->query
.timerset
== ISC_FALSE
)
2147 ns_client_settimeout(client
, 60);
2148 result
= dns_resolver_createfetch(client
->view
->resolver
,
2149 client
->query
.qname
,
2150 qtype
, qdomain
, nameservers
,
2151 NULL
, client
->query
.fetchoptions
,
2153 query_resume
, client
,
2154 rdataset
, sigrdataset
,
2155 &client
->query
.fetch
);
2157 if (result
== ISC_R_SUCCESS
) {
2159 * Record that we're waiting for an event. A client which
2160 * is shutting down will not be destroyed until all the
2161 * events have been received.
2164 query_putrdataset(client
, &rdataset
);
2165 if (sigrdataset
!= NULL
)
2166 query_putrdataset(client
, &sigrdataset
);
2172 static inline isc_result_t
2173 query_findparentkey(ns_client_t
*client
, dns_name_t
*name
,
2174 dns_zone_t
**zonep
, dns_db_t
**dbp
,
2175 dns_dbversion_t
**versionp
, dns_dbnode_t
**nodep
,
2176 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
2179 dns_dbnode_t
*pnode
;
2180 dns_dbversion_t
*pversion
;
2181 dns_rdataset_t prdataset
, psigrdataset
;
2182 dns_rdataset_t
*psigrdatasetp
;
2183 isc_result_t result
;
2185 isc_boolean_t is_zone
;
2186 dns_fixedname_t pfoundname
;
2189 * 'name' is at a zone cut. Try to find a KEY for 'name' in
2190 * the deepest ancestor zone of 'name' (if any). If it exists,
2191 * update *zonep, *dbp, *nodep, rdataset, and sigrdataset and
2192 * return ISC_R_SUCCESS. If not, leave them alone and return a
2193 * non-success status.
2200 dns_rdataset_init(&prdataset
);
2201 if (sigrdataset
!= NULL
)
2202 dns_rdataset_init(&psigrdataset
);
2203 is_zone
= ISC_FALSE
;
2204 dns_fixedname_init(&pfoundname
);
2206 result
= query_getdb(client
, name
, DNS_GETDB_NOEXACT
,
2207 &pzone
, &pdb
, &pversion
, &is_zone
);
2208 if (result
!= ISC_R_SUCCESS
)
2211 result
= ISC_R_FAILURE
;
2215 if (sigrdataset
!= NULL
)
2216 psigrdatasetp
= &psigrdataset
;
2218 psigrdatasetp
= NULL
;
2219 result
= dns_db_find(pdb
, name
, pversion
, dns_rdatatype_key
,
2220 client
->query
.dboptions
,
2221 client
->now
, &pnode
,
2222 dns_fixedname_name(&pfoundname
),
2223 &prdataset
, psigrdatasetp
);
2224 if (result
== ISC_R_SUCCESS
) {
2225 if (dns_rdataset_isassociated(rdataset
))
2226 dns_rdataset_disassociate(rdataset
);
2227 dns_rdataset_clone(&prdataset
, rdataset
);
2228 if (sigrdataset
!= NULL
) {
2229 if (dns_rdataset_isassociated(sigrdataset
))
2230 dns_rdataset_disassociate(sigrdataset
);
2231 if (dns_rdataset_isassociated(&psigrdataset
))
2232 dns_rdataset_clone(&psigrdataset
, sigrdataset
);
2235 dns_db_detachnode(*dbp
, nodep
);
2238 *versionp
= pversion
;
2244 dns_zone_detach(zonep
);
2250 if (dns_rdataset_isassociated(&prdataset
))
2251 dns_rdataset_disassociate(&prdataset
);
2252 if (sigrdataset
!= NULL
&& dns_rdataset_isassociated(&psigrdataset
))
2253 dns_rdataset_disassociate(&psigrdataset
);
2255 dns_db_detachnode(pdb
, &pnode
);
2257 dns_db_detach(&pdb
);
2259 dns_zone_detach(&pzone
);
2264 #define MAX_RESTARTS 16
2266 #define QUERY_ERROR(r) \
2269 want_restart = ISC_FALSE; \
2273 * Extract a network address from the RDATA of an A or AAAA
2278 * ISC_R_NOTIMPLEMENTED The rdata is not a known address type.
2281 rdata_tonetaddr(dns_rdata_t
*rdata
, isc_netaddr_t
*netaddr
) {
2283 struct in6_addr in6a
;
2285 switch (rdata
->type
) {
2286 case dns_rdatatype_a
:
2287 INSIST(rdata
->length
== 4);
2288 memcpy(&ina
.s_addr
, rdata
->data
, 4);
2289 isc_netaddr_fromin(netaddr
, &ina
);
2290 return (ISC_R_SUCCESS
);
2291 case dns_rdatatype_aaaa
:
2292 INSIST(rdata
->length
== 16);
2293 memcpy(in6a
.s6_addr
, rdata
->data
, 16);
2294 isc_netaddr_fromin6(netaddr
, &in6a
);
2295 return (ISC_R_SUCCESS
);
2297 return (ISC_R_NOTIMPLEMENTED
);
2302 * Find the sort order of 'rdata' in the topology-like
2303 * ACL forming the second element in a 2-element top-level
2304 * sortlist statement.
2307 query_sortlist_order_2element(dns_rdata_t
*rdata
, void *arg
) {
2308 isc_netaddr_t netaddr
;
2310 if (rdata_tonetaddr(rdata
, &netaddr
) != ISC_R_SUCCESS
)
2312 return (ns_sortlist_addrorder2(&netaddr
, arg
));
2316 * Find the sort order of 'rdata' in the matching element
2317 * of a 1-element top-level sortlist statement.
2320 query_sortlist_order_1element(dns_rdata_t
*rdata
, void *arg
) {
2321 isc_netaddr_t netaddr
;
2323 if (rdata_tonetaddr(rdata
, &netaddr
) != ISC_R_SUCCESS
)
2325 return (ns_sortlist_addrorder1(&netaddr
, arg
));
2329 * Find the sortlist statement that applies to 'client' and set up
2330 * the sortlist info in in client->message appropriately.
2333 setup_query_sortlist(ns_client_t
*client
) {
2334 isc_netaddr_t netaddr
;
2335 dns_rdatasetorderfunc_t order
= NULL
;
2336 void *order_arg
= NULL
;
2338 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
2339 switch (ns_sortlist_setup(client
->view
->sortlist
,
2340 &netaddr
, &order_arg
)) {
2341 case NS_SORTLISTTYPE_1ELEMENT
:
2342 order
= query_sortlist_order_1element
;
2344 case NS_SORTLISTTYPE_2ELEMENT
:
2345 order
= query_sortlist_order_2element
;
2347 case NS_SORTLISTTYPE_NONE
:
2354 dns_message_setsortorder(client
->message
, order
, order_arg
);
2358 * Do the bulk of query processing for the current query of 'client'.
2359 * If 'event' is non-NULL, we are returning from recursion and 'qtype'
2360 * is ignored. Otherwise, 'qtype' is the query type.
2363 query_find(ns_client_t
*client
, dns_fetchevent_t
*event
, dns_rdatatype_t qtype
) {
2366 dns_rdatatype_t type
;
2367 dns_name_t
*fname
, *zfname
, *tname
, *prefix
;
2368 dns_rdataset_t
*rdataset
, *trdataset
;
2369 dns_rdataset_t
*sigrdataset
, *zrdataset
, *zsigrdataset
;
2370 dns_rdataset_t
**sigrdatasetp
;
2371 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2372 dns_rdatasetiter_t
*rdsiter
;
2373 isc_boolean_t want_restart
, authoritative
, is_zone
;
2374 unsigned int n
, nlabels
, nbits
;
2375 dns_namereln_t namereln
;
2379 isc_result_t result
, eresult
;
2380 dns_fixedname_t fixed
;
2381 dns_dbversion_t
*version
;
2383 dns_rdata_cname_t cname
;
2384 dns_rdata_dname_t dname
;
2385 isc_boolean_t empty_wild
;
2387 CTRACE("query_find");
2390 * One-time initialization.
2392 * It's especially important to initialize anything that the cleanup
2393 * code might cleanup.
2396 eresult
= ISC_R_SUCCESS
;
2402 zsigrdataset
= NULL
;
2408 empty_wild
= ISC_FALSE
;
2410 if (event
!= NULL
) {
2412 * We're returning from recursion. Restore the query context
2416 want_restart
= ISC_FALSE
;
2417 authoritative
= ISC_FALSE
;
2418 is_zone
= ISC_FALSE
;
2420 qtype
= event
->qtype
;
2421 if (qtype
== dns_rdatatype_sig
)
2422 type
= dns_rdatatype_any
;
2427 rdataset
= event
->rdataset
;
2428 sigrdataset
= event
->sigrdataset
;
2431 * We'll need some resources...
2433 dbuf
= query_getnamebuf(client
);
2435 QUERY_ERROR(DNS_R_SERVFAIL
);
2438 fname
= query_newname(client
, dbuf
, &b
);
2439 if (fname
== NULL
) {
2440 QUERY_ERROR(DNS_R_SERVFAIL
);
2443 tname
= dns_fixedname_name(&event
->foundname
);
2444 result
= dns_name_copy(tname
, fname
, NULL
);
2445 if (result
!= ISC_R_SUCCESS
) {
2446 QUERY_ERROR(DNS_R_SERVFAIL
);
2450 result
= event
->result
;
2456 * Not returning from recursion.
2460 * If it's a SIG query, we'll iterate the node.
2462 if (qtype
== dns_rdatatype_sig
)
2463 type
= dns_rdatatype_any
;
2468 CTRACE("query_find: restart");
2469 want_restart
= ISC_FALSE
;
2470 authoritative
= ISC_FALSE
;
2474 * First we must find the right database.
2476 result
= query_getdb(client
, client
->query
.qname
, 0, &zone
, &db
,
2477 &version
, &is_zone
);
2478 if (result
!= ISC_R_SUCCESS
) {
2479 if (result
== DNS_R_REFUSED
)
2480 QUERY_ERROR(DNS_R_REFUSED
);
2482 QUERY_ERROR(DNS_R_SERVFAIL
);
2487 authoritative
= ISC_TRUE
;
2489 if (event
== NULL
&& client
->query
.restarts
== 0) {
2491 dns_zone_attach(zone
, &client
->query
.authzone
);
2492 dns_db_attach(db
, &client
->query
.authdb
);
2494 client
->query
.authdbset
= ISC_TRUE
;
2498 CTRACE("query_find: db_find");
2500 * We'll need some resources...
2502 dbuf
= query_getnamebuf(client
);
2504 QUERY_ERROR(DNS_R_SERVFAIL
);
2507 fname
= query_newname(client
, dbuf
, &b
);
2508 rdataset
= query_newrdataset(client
);
2509 if (fname
== NULL
|| rdataset
== NULL
) {
2510 QUERY_ERROR(DNS_R_SERVFAIL
);
2513 if (WANTDNSSEC(client
)) {
2514 sigrdataset
= query_newrdataset(client
);
2515 if (sigrdataset
== NULL
) {
2516 QUERY_ERROR(DNS_R_SERVFAIL
);
2522 * Now look for an answer in the database.
2524 result
= dns_db_find(db
, client
->query
.qname
, version
, type
,
2525 client
->query
.dboptions
, client
->now
,
2526 &node
, fname
, rdataset
, sigrdataset
);
2529 * We interrupt our normal query processing to bring you this special
2532 * RFC 2535 (DNSSEC), section 2.3.4, discusses various special
2533 * cases that can occur at delegation points.
2535 * One of these cases is that the NULL KEY for an unsecure zone
2536 * may occur in the delegating zone instead of in the delegated zone.
2537 * If we're authoritative for both zones, we need to look for the
2538 * key in the delegator if we didn't find it in the delegatee. If
2539 * we didn't do this, a client doing DNSSEC validation could fail
2540 * because it couldn't get the NULL KEY.
2542 if (type
== dns_rdatatype_key
&&
2544 result
== DNS_R_NXRRSET
&&
2545 !dns_db_issecure(db
) &&
2546 dns_name_equal(client
->query
.qname
, dns_db_origin(db
))) {
2548 * We're looking for a KEY at the top of an unsecure zone,
2549 * and we didn't find it.
2551 result
= query_findparentkey(client
, client
->query
.qname
,
2552 &zone
, &db
, &version
, &node
,
2553 rdataset
, sigrdataset
);
2554 if (result
== ISC_R_SUCCESS
) {
2556 * We found the parent KEY.
2558 * zone, db, version, node, rdataset, and sigrdataset
2559 * have all been updated to refer to the parent's
2560 * data. We will resume query processing as if
2561 * we had looked for the KEY in the parent zone in
2564 * We need to set fname correctly. We do this here
2565 * instead of in query_findparentkey() because
2566 * dns_name_copy() can fail (though it shouldn't
2567 * ever do so since we should have enough space).
2569 result
= dns_name_copy(client
->query
.qname
,
2571 if (result
!= ISC_R_SUCCESS
) {
2572 QUERY_ERROR(DNS_R_SERVFAIL
);
2577 * We couldn't find the KEY in a parent zone.
2578 * Continue with processing of the original
2579 * results of dns_db_find().
2581 result
= DNS_R_NXRRSET
;
2586 CTRACE("query_find: resume");
2590 * This case is handled in the main line below.
2596 * These cases are handled in the main line below.
2599 authoritative
= ISC_FALSE
;
2601 case ISC_R_NOTFOUND
:
2603 * The cache doesn't even have the root NS. Get them from
2610 if (client
->view
->hints
== NULL
) {
2611 /* We have no hints. */
2612 result
= ISC_R_FAILURE
;
2614 dns_db_attach(client
->view
->hints
, &db
);
2615 result
= dns_db_find(db
, dns_rootname
,
2616 NULL
, dns_rdatatype_ns
,
2617 0, client
->now
, &node
, fname
,
2618 rdataset
, sigrdataset
);
2620 if (result
!= ISC_R_SUCCESS
) {
2622 * Nonsensical root hints may require cleanup.
2624 if (dns_rdataset_isassociated(rdataset
))
2625 dns_rdataset_disassociate(rdataset
);
2626 if (sigrdataset
!= NULL
&&
2627 dns_rdataset_isassociated(sigrdataset
))
2628 dns_rdataset_disassociate(sigrdataset
);
2630 dns_db_detachnode(db
, &node
);
2633 * We don't have any root server hints, but
2634 * we may have working forwarders, so try to
2637 if (RECURSIONOK(client
)) {
2638 result
= query_recurse(client
, qtype
,
2640 if (result
== ISC_R_SUCCESS
)
2641 client
->query
.attributes
|=
2642 NS_QUERYATTR_RECURSING
;
2644 /* Unable to recurse. */
2645 QUERY_ERROR(DNS_R_SERVFAIL
);
2649 /* Unable to give root server referral. */
2650 QUERY_ERROR(DNS_R_SERVFAIL
);
2655 * XXXRTH We should trigger root server priming here.
2658 case DNS_R_DELEGATION
:
2659 authoritative
= ISC_FALSE
;
2662 * We're authoritative for an ancestor of QNAME.
2664 if (!USECACHE(client
) || !RECURSIONOK(client
)) {
2666 * If we don't have a cache, this is the best
2669 * If the client is making a nonrecursive
2670 * query we always give out the authoritative
2671 * delegation. This way even if we get
2672 * junk in our cache, we won't fail in our
2673 * role as the delegating authority if another
2674 * nameserver asks us about a delegated
2677 * We enable the retrieval of glue for this
2678 * database by setting client->query.gluedb.
2680 client
->query
.gluedb
= db
;
2681 client
->query
.isreferral
= ISC_TRUE
;
2683 * We must ensure NOADDITIONAL is off,
2684 * because the generation of
2685 * additional data is required in
2688 client
->query
.attributes
&=
2689 ~NS_QUERYATTR_NOADDITIONAL
;
2690 if (sigrdataset
!= NULL
)
2691 sigrdatasetp
= &sigrdataset
;
2693 sigrdatasetp
= NULL
;
2694 query_addrrset(client
, &fname
,
2695 &rdataset
, sigrdatasetp
,
2696 dbuf
, DNS_SECTION_AUTHORITY
);
2697 client
->query
.gluedb
= NULL
;
2700 * We might have a better answer or delegation
2701 * in the cache. We'll remember the current
2702 * values of fname, rdataset, and sigrdataset.
2703 * We'll then go looking for QNAME in the
2704 * cache. If we find something better, we'll
2707 query_keepname(client
, fname
, dbuf
);
2711 zrdataset
= rdataset
;
2713 zsigrdataset
= sigrdataset
;
2715 dns_db_detachnode(db
, &node
);
2718 dns_db_attach(client
->view
->cachedb
, &db
);
2719 is_zone
= ISC_FALSE
;
2723 if (zfname
!= NULL
&&
2724 !dns_name_issubdomain(fname
, zfname
)) {
2726 * We've already got a delegation from
2727 * authoritative data, and it is better
2728 * than what we found in the cache. Use
2729 * it instead of the cache delegation.
2731 query_releasename(client
, &fname
);
2735 * We've already done query_keepname() on
2736 * zfname, so we must set dbuf to NULL to
2737 * prevent query_addrrset() from trying to
2738 * call query_keepname() again.
2741 query_putrdataset(client
, &rdataset
);
2742 if (sigrdataset
!= NULL
)
2743 query_putrdataset(client
,
2745 rdataset
= zrdataset
;
2747 sigrdataset
= zsigrdataset
;
2748 zsigrdataset
= NULL
;
2750 * We don't clean up zdb here because we
2751 * may still need it. It will get cleaned
2752 * up by the main cleanup code.
2756 if (RECURSIONOK(client
)) {
2760 if (type
== dns_rdatatype_key
)
2761 result
= query_recurse(client
, qtype
,
2764 result
= query_recurse(client
, qtype
,
2766 if (result
== ISC_R_SUCCESS
)
2767 client
->query
.attributes
|=
2768 NS_QUERYATTR_RECURSING
;
2770 QUERY_ERROR(DNS_R_SERVFAIL
);
2773 * This is the best answer.
2775 client
->query
.attributes
|=
2776 NS_QUERYATTR_CACHEGLUEOK
;
2777 client
->query
.gluedb
= zdb
;
2778 client
->query
.isreferral
= ISC_TRUE
;
2780 * We must ensure NOADDITIONAL is off,
2781 * because the generation of
2782 * additional data is required in
2785 client
->query
.attributes
&=
2786 ~NS_QUERYATTR_NOADDITIONAL
;
2787 if (sigrdataset
!= NULL
)
2788 sigrdatasetp
= &sigrdataset
;
2790 sigrdatasetp
= NULL
;
2791 query_addrrset(client
, &fname
,
2792 &rdataset
, sigrdatasetp
,
2793 dbuf
, DNS_SECTION_AUTHORITY
);
2794 client
->query
.gluedb
= NULL
;
2795 client
->query
.attributes
&=
2796 ~NS_QUERYATTR_CACHEGLUEOK
;
2800 case DNS_R_EMPTYNAME
:
2801 result
= DNS_R_NXRRSET
;
2805 if (dns_rdataset_isassociated(rdataset
)) {
2807 * If we've got a NXT record, we need to save the
2808 * name now because we're going call query_addsoa()
2809 * below, and it needs to use the name buffer.
2811 query_keepname(client
, fname
, dbuf
);
2814 * We're not going to use fname, and need to release
2815 * our hold on the name buffer so query_addsoa()
2818 query_releasename(client
, &fname
);
2823 result
= query_addsoa(client
, db
, ISC_FALSE
);
2824 if (result
!= ISC_R_SUCCESS
) {
2825 QUERY_ERROR(result
);
2829 * Add NXT record if we found one.
2831 if (dns_rdataset_isassociated(rdataset
)) {
2832 if (WANTDNSSEC(client
))
2833 query_addrrset(client
, &fname
, &rdataset
,
2835 NULL
, DNS_SECTION_AUTHORITY
);
2838 case DNS_R_EMPTYWILD
:
2839 empty_wild
= ISC_TRUE
;
2841 case DNS_R_NXDOMAIN
:
2843 if (dns_rdataset_isassociated(rdataset
)) {
2845 * If we've got a NXT record, we need to save the
2846 * name now because we're going call query_addsoa()
2847 * below, and it needs to use the name buffer.
2849 query_keepname(client
, fname
, dbuf
);
2852 * We're not going to use fname, and need to release
2853 * our hold on the name buffer so query_addsoa()
2856 query_releasename(client
, &fname
);
2859 * Add SOA. If the query was for a SOA record force the
2860 * ttl to zero so that it is possible for clients to find
2861 * the containing zone of a arbitary name with a stub
2862 * resolver and not have it cached.
2864 if (qtype
== dns_rdatatype_soa
)
2865 result
= query_addsoa(client
, db
, ISC_TRUE
);
2867 result
= query_addsoa(client
, db
, ISC_FALSE
);
2868 if (result
!= ISC_R_SUCCESS
) {
2869 QUERY_ERROR(result
);
2873 * Add NXT record if we found one.
2875 if (dns_rdataset_isassociated(rdataset
)) {
2876 if (WANTDNSSEC(client
))
2877 query_addrrset(client
, &fname
, &rdataset
,
2879 NULL
, DNS_SECTION_AUTHORITY
);
2882 * Set message rcode.
2885 client
->message
->rcode
= dns_rcode_noerror
;
2887 client
->message
->rcode
= dns_rcode_nxdomain
;
2889 case DNS_R_NCACHENXDOMAIN
:
2890 case DNS_R_NCACHENXRRSET
:
2892 authoritative
= ISC_FALSE
;
2894 * Set message rcode, if required.
2896 if (result
== DNS_R_NCACHENXDOMAIN
)
2897 client
->message
->rcode
= dns_rcode_nxdomain
;
2899 * We don't call query_addrrset() because we don't need any
2900 * of its extra features (and things would probably break!).
2902 query_keepname(client
, fname
, dbuf
);
2903 dns_message_addname(client
->message
, fname
,
2904 DNS_SECTION_AUTHORITY
);
2905 ISC_LIST_APPEND(fname
->list
, rdataset
, link
);
2911 * Keep a copy of the rdataset. We have to do this because
2912 * query_addrrset may clear 'rdataset' (to prevent the
2913 * cleanup code from cleaning it up).
2915 trdataset
= rdataset
;
2917 * Add the CNAME to the answer section.
2919 if (sigrdataset
!= NULL
)
2920 sigrdatasetp
= &sigrdataset
;
2922 sigrdatasetp
= NULL
;
2923 query_addrrset(client
, &fname
, &rdataset
, sigrdatasetp
, dbuf
,
2924 DNS_SECTION_ANSWER
);
2926 * We set the PARTIALANSWER attribute so that if anything goes
2927 * wrong later on, we'll return what we've got so far.
2929 client
->query
.attributes
|= NS_QUERYATTR_PARTIALANSWER
;
2931 * Reset qname to be the target name of the CNAME and restart
2935 result
= dns_message_gettempname(client
->message
, &tname
);
2936 if (result
!= ISC_R_SUCCESS
)
2938 result
= dns_rdataset_first(trdataset
);
2939 if (result
!= ISC_R_SUCCESS
) {
2940 dns_message_puttempname(client
->message
, &tname
);
2943 dns_rdataset_current(trdataset
, &rdata
);
2944 result
= dns_rdata_tostruct(&rdata
, &cname
, NULL
);
2945 dns_rdata_reset(&rdata
);
2946 if (result
!= ISC_R_SUCCESS
) {
2947 dns_message_puttempname(client
->message
, &tname
);
2950 dns_name_init(tname
, NULL
);
2951 result
= dns_name_dup(&cname
.cname
, client
->mctx
, tname
);
2952 if (result
!= ISC_R_SUCCESS
) {
2953 dns_message_puttempname(client
->message
, &tname
);
2954 dns_rdata_freestruct(&cname
);
2957 dns_rdata_freestruct(&cname
);
2958 query_maybeputqname(client
);
2959 client
->query
.qname
= tname
;
2960 want_restart
= ISC_TRUE
;
2964 * Compare the current qname to the found name. We need
2965 * to know how many labels and bits are in common because
2966 * we're going to have to split qname later on.
2968 namereln
= dns_name_fullcompare(client
->query
.qname
, fname
,
2969 &order
, &nlabels
, &nbits
);
2970 INSIST(namereln
== dns_namereln_subdomain
);
2972 * Keep a copy of the rdataset. We have to do this because
2973 * query_addrrset may clear 'rdataset' (to prevent the
2974 * cleanup code from cleaning it up).
2976 trdataset
= rdataset
;
2978 * Add the DNAME to the answer section.
2980 if (sigrdataset
!= NULL
)
2981 sigrdatasetp
= &sigrdataset
;
2983 sigrdatasetp
= NULL
;
2984 query_addrrset(client
, &fname
, &rdataset
, sigrdatasetp
, dbuf
,
2985 DNS_SECTION_ANSWER
);
2987 * We set the PARTIALANSWER attribute so that if anything goes
2988 * wrong later on, we'll return what we've got so far.
2990 client
->query
.attributes
|= NS_QUERYATTR_PARTIALANSWER
;
2992 * Get the target name of the DNAME.
2995 result
= dns_message_gettempname(client
->message
, &tname
);
2996 if (result
!= ISC_R_SUCCESS
)
2998 result
= dns_rdataset_first(trdataset
);
2999 if (result
!= ISC_R_SUCCESS
) {
3000 dns_message_puttempname(client
->message
, &tname
);
3003 dns_rdataset_current(trdataset
, &rdata
);
3004 result
= dns_rdata_tostruct(&rdata
, &dname
, NULL
);
3005 dns_rdata_reset(&rdata
);
3006 if (result
!= ISC_R_SUCCESS
) {
3007 dns_message_puttempname(client
->message
, &tname
);
3010 dns_name_init(tname
, NULL
);
3011 dns_name_clone(&dname
.dname
, tname
);
3012 dns_rdata_freestruct(&dname
);
3014 * Construct the new qname.
3016 dns_fixedname_init(&fixed
);
3017 prefix
= dns_fixedname_name(&fixed
);
3018 result
= dns_name_split(client
->query
.qname
, nlabels
, nbits
,
3020 if (result
!= ISC_R_SUCCESS
) {
3021 dns_message_puttempname(client
->message
, &tname
);
3024 INSIST(fname
== NULL
);
3025 dbuf
= query_getnamebuf(client
);
3027 dns_message_puttempname(client
->message
, &tname
);
3030 fname
= query_newname(client
, dbuf
, &b
);
3031 if (fname
== NULL
) {
3032 dns_message_puttempname(client
->message
, &tname
);
3035 result
= dns_name_concatenate(prefix
, tname
, fname
, NULL
);
3036 if (result
!= ISC_R_SUCCESS
) {
3037 dns_message_puttempname(client
->message
, &tname
);
3038 if (result
== ISC_R_NOSPACE
) {
3040 * RFC 2672, section 4.1, subsection 3c says
3041 * we should return YXDOMAIN if the constructed
3042 * name would be too long.
3044 client
->message
->rcode
= dns_rcode_yxdomain
;
3048 query_keepname(client
, fname
, dbuf
);
3050 * Synthesize a CNAME for this DNAME.
3052 * We want to synthesize a CNAME since if we don't
3053 * then older software that doesn't understand DNAME
3054 * will not chain like it should.
3056 * We do not try to synthesize a signature because we hope
3057 * that security aware servers will understand DNAME. Also,
3058 * even if we had an online key, making a signature
3059 * on-the-fly is costly, and not really legitimate anyway
3060 * since the synthesized CNAME is NOT in the zone.
3062 dns_name_init(tname
, NULL
);
3063 query_addcnamelike(client
, client
->query
.qname
, fname
,
3064 0, &tname
, dns_rdatatype_cname
);
3066 dns_message_puttempname(client
->message
, &tname
);
3068 * Switch to the new qname and restart.
3070 query_maybeputqname(client
);
3071 client
->query
.qname
= fname
;
3073 want_restart
= ISC_TRUE
;
3077 * Something has gone wrong.
3079 QUERY_ERROR(DNS_R_SERVFAIL
);
3083 if (type
== dns_rdatatype_any
) {
3085 * XXXRTH Need to handle zonecuts with special case
3090 result
= dns_db_allrdatasets(db
, node
, version
, 0, &rdsiter
);
3091 if (result
!= ISC_R_SUCCESS
) {
3092 QUERY_ERROR(DNS_R_SERVFAIL
);
3096 * Calling query_addrrset() with a non-NULL dbuf is going
3097 * to either keep or release the name. We don't want it to
3098 * release fname, since we may have to call query_addrrset()
3099 * more than once. That means we have to call query_keepname()
3100 * now, and pass a NULL dbuf to query_addrrset().
3102 * If we do a query_addrrset() below, we must set fname to
3103 * NULL before leaving this block, otherwise we might try to
3104 * cleanup fname even though we're using it!
3106 query_keepname(client
, fname
, dbuf
);
3108 result
= dns_rdatasetiter_first(rdsiter
);
3109 while (result
== ISC_R_SUCCESS
) {
3110 dns_rdatasetiter_current(rdsiter
, rdataset
);
3111 if ((qtype
== dns_rdatatype_any
||
3112 rdataset
->type
== qtype
) && rdataset
->type
!= 0) {
3113 query_addrrset(client
,
3114 fname
!= NULL
? &fname
: &tname
,
3116 NULL
, DNS_SECTION_ANSWER
);
3118 INSIST(tname
!= NULL
);
3120 * rdataset is non-NULL only in certain pathological
3121 * cases involving DNAMEs.
3123 if (rdataset
!= NULL
)
3124 query_putrdataset(client
, &rdataset
);
3125 rdataset
= query_newrdataset(client
);
3126 if (rdataset
== NULL
)
3130 * We're not interested in this rdataset.
3132 dns_rdataset_disassociate(rdataset
);
3134 result
= dns_rdatasetiter_next(rdsiter
);
3138 dns_message_puttempname(client
->message
, &fname
);
3142 * We didn't match any rdatasets.
3144 if (qtype
== dns_rdatatype_sig
&&
3145 result
== ISC_R_NOMORE
) {
3147 * XXXRTH If this is a secure zone and we
3148 * didn't find any SIGs, we should generate
3149 * an error unless we were searching for
3153 * We were searching for SIG records in
3154 * a nonsecure zone. Send a "no error,
3155 * no data" response.
3160 result
= query_addsoa(client
, db
, ISC_FALSE
);
3161 if (result
== ISC_R_SUCCESS
)
3162 result
= ISC_R_NOMORE
;
3165 * Something went wrong.
3167 result
= DNS_R_SERVFAIL
;
3170 dns_rdatasetiter_destroy(&rdsiter
);
3171 if (result
!= ISC_R_NOMORE
) {
3172 QUERY_ERROR(DNS_R_SERVFAIL
);
3177 * This is the "normal" case -- an ordinary question to which
3178 * we know the answer.
3180 if (sigrdataset
!= NULL
)
3181 sigrdatasetp
= &sigrdataset
;
3183 sigrdatasetp
= NULL
;
3184 query_addrrset(client
, &fname
, &rdataset
, sigrdatasetp
, dbuf
,
3185 DNS_SECTION_ANSWER
);
3187 * We shouldn't ever fail to add 'rdataset'
3188 * because it's already in the answer.
3190 INSIST(rdataset
== NULL
);
3194 CTRACE("query_find: addauth");
3196 * Add NS records to the authority section (if we haven't already
3197 * added them to the answer section).
3199 if (!want_restart
&& !NOAUTHORITY(client
)
3202 if (!((qtype
== dns_rdatatype_ns
||
3203 qtype
== dns_rdatatype_any
) &&
3204 dns_name_equal(client
->query
.qname
,
3205 dns_db_origin(db
))))
3206 query_addns(client
, db
);
3207 } else if (qtype
!= dns_rdatatype_ns
) {
3209 query_releasename(client
, &fname
);
3210 query_addbestns(client
);
3215 CTRACE("query_find: cleanup");
3219 if (rdataset
!= NULL
)
3220 query_putrdataset(client
, &rdataset
);
3221 if (sigrdataset
!= NULL
)
3222 query_putrdataset(client
, &sigrdataset
);
3224 query_releasename(client
, &fname
);
3226 dns_db_detachnode(db
, &node
);
3230 dns_zone_detach(&zone
);
3232 query_putrdataset(client
, &zrdataset
);
3233 if (zsigrdataset
!= NULL
)
3234 query_putrdataset(client
, &zsigrdataset
);
3236 query_releasename(client
, &zfname
);
3237 dns_db_detach(&zdb
);
3240 isc_event_free(ISC_EVENT_PTR(&event
));
3245 if (client
->query
.restarts
== 0 && !authoritative
) {
3247 * We're not authoritative, so we must ensure the AA bit
3250 client
->message
->flags
&= ~DNS_MESSAGEFLAG_AA
;
3254 * Restart the query?
3256 if (want_restart
&& client
->query
.restarts
< MAX_RESTARTS
) {
3257 client
->query
.restarts
++;
3261 if (eresult
!= ISC_R_SUCCESS
&&
3262 (!PARTIALANSWER(client
) || WANTRECURSION(client
))) {
3264 * If we don't have any answer to give the client,
3265 * or if the client requested recursion and thus wanted
3266 * the complete answer, send an error response.
3268 query_error(client
, eresult
);
3269 ns_client_detach(&client
);
3270 } else if (!RECURSING(client
)) {
3272 * We are done. Set up sortlist data for the message
3273 * rendering code, make a final tweak to the AA bit if the
3274 * auth-nxdomain config option says so, then render and
3275 * send the response.
3277 setup_query_sortlist(client
);
3279 if (client
->message
->rcode
== dns_rcode_nxdomain
&&
3280 client
->view
->auth_nxdomain
== ISC_TRUE
)
3281 client
->message
->flags
|= DNS_MESSAGEFLAG_AA
;
3284 ns_client_detach(&client
);
3286 CTRACE("query_find: done");
3290 log_query(ns_client_t
*client
) {
3291 char namebuf
[DNS_NAME_FORMATSIZE
];
3292 char typename
[DNS_RDATATYPE_FORMATSIZE
];
3293 char classname
[DNS_RDATACLASS_FORMATSIZE
];
3294 dns_rdataset_t
*rdataset
;
3295 int level
= ISC_LOG_INFO
;
3297 if (! isc_log_wouldlog(ns_g_lctx
, level
))
3300 rdataset
= ISC_LIST_HEAD(client
->query
.qname
->list
);
3301 INSIST(rdataset
!= NULL
);
3302 dns_name_format(client
->query
.qname
, namebuf
, sizeof(namebuf
));
3303 dns_rdataclass_format(rdataset
->rdclass
, classname
, sizeof(classname
));
3304 dns_rdatatype_format(rdataset
->type
, typename
, sizeof(typename
));
3306 ns_client_log(client
, NS_LOGCATEGORY_QUERIES
, NS_LOGMODULE_QUERY
,
3307 level
, "query: %s %s %s", namebuf
, classname
, typename
);
3311 ns_query_start(ns_client_t
*client
) {
3312 isc_result_t result
;
3313 dns_message_t
*message
= client
->message
;
3314 dns_rdataset_t
*rdataset
;
3315 ns_client_t
*qclient
;
3316 dns_rdatatype_t qtype
;
3318 CTRACE("ns_query_start");
3321 * Ensure that appropriate cleanups occur.
3323 client
->next
= query_next_callback
;
3325 if ((message
->flags
& DNS_MESSAGEFLAG_RD
) != 0)
3326 client
->query
.attributes
|= NS_QUERYATTR_WANTRECURSION
;
3329 if ((client
->extflags
& DNS_MESSAGEEXTFLAG_DO
) != 0 ||
3330 (message
->flags
& DNS_MESSAGEFLAG_AD
) != 0)
3331 client
->query
.attributes
|= NS_QUERYATTR_WANTDNSSEC
;
3334 if (client
->view
->minimalresponses
)
3335 client
->query
.attributes
|= (NS_QUERYATTR_NOAUTHORITY
|
3336 NS_QUERYATTR_NOADDITIONAL
);
3338 if ((client
->view
->cachedb
== NULL
)
3339 || (!client
->view
->additionalfromcache
)) {
3341 * We don't have a cache. Turn off cache support and
3344 client
->query
.attributes
&=
3345 ~(NS_QUERYATTR_RECURSIONOK
|NS_QUERYATTR_CACHEOK
);
3346 } else if ((client
->attributes
& NS_CLIENTATTR_RA
) == 0 ||
3347 (message
->flags
& DNS_MESSAGEFLAG_RD
) == 0) {
3349 * If the client isn't allowed to recurse (due to
3350 * "recursion no", the allow-recursion ACL, or the
3351 * lack of a resolver in this view), or if it
3352 * doesn't want recursion, turn recursion off.
3354 client
->query
.attributes
&= ~NS_QUERYATTR_RECURSIONOK
;
3358 * Get the question name.
3360 result
= dns_message_firstname(message
, DNS_SECTION_QUESTION
);
3361 if (result
!= ISC_R_SUCCESS
) {
3362 query_error(client
, result
);
3365 dns_message_currentname(message
, DNS_SECTION_QUESTION
,
3366 &client
->query
.qname
);
3367 client
->query
.origqname
= client
->query
.qname
;
3368 result
= dns_message_nextname(message
, DNS_SECTION_QUESTION
);
3369 if (result
!= ISC_R_NOMORE
) {
3370 if (result
== ISC_R_SUCCESS
) {
3372 * There's more than one QNAME in the question
3375 query_error(client
, DNS_R_FORMERR
);
3377 query_error(client
, result
);
3381 if (ns_g_server
->log_queries
)
3385 * Check for multiple question queries, since edns1 is dead.
3387 if (message
->counts
[DNS_SECTION_QUESTION
] > 1) {
3388 query_error(client
, DNS_R_FORMERR
);
3393 * Check for meta-queries like IXFR and AXFR.
3395 rdataset
= ISC_LIST_HEAD(client
->query
.qname
->list
);
3396 INSIST(rdataset
!= NULL
);
3397 qtype
= rdataset
->type
;
3398 if (dns_rdatatype_ismeta(qtype
)) {
3400 case dns_rdatatype_any
:
3401 break; /* Let query_find handle it. */
3402 case dns_rdatatype_ixfr
:
3403 case dns_rdatatype_axfr
:
3404 ns_xfr_start(client
, rdataset
->type
);
3406 case dns_rdatatype_maila
:
3407 case dns_rdatatype_mailb
:
3408 query_error(client
, DNS_R_NOTIMP
);
3410 case dns_rdatatype_tkey
:
3411 result
= dns_tkey_processquery(client
->message
,
3412 ns_g_server
->tkeyctx
,
3413 client
->view
->dynamickeys
);
3414 if (result
== ISC_R_SUCCESS
)
3417 query_error(client
, result
);
3419 default: /* TSIG, etc. */
3420 query_error(client
, DNS_R_FORMERR
);
3426 * If the client has requested that DNSSEC checking be disabled,
3427 * allow lookups to return pending data and instruct the resolver
3428 * to return data before validation has completed.
3430 if (message
->flags
& DNS_MESSAGEFLAG_CD
||
3431 qtype
== dns_rdatatype_sig
)
3433 client
->query
.dboptions
|= DNS_DBFIND_PENDINGOK
;
3434 client
->query
.fetchoptions
|= DNS_FETCHOPT_NOVALIDATE
;
3438 * This is an ordinary query.
3440 result
= dns_message_reply(message
, ISC_TRUE
);
3441 if (result
!= ISC_R_SUCCESS
) {
3442 query_next(client
, result
);
3447 * Assume authoritative response until it is known to be
3450 message
->flags
|= DNS_MESSAGEFLAG_AA
;
3453 * Set AD. We must clear it if we add non-validated data to a
3456 if (WANTDNSSEC(client
))
3457 message
->flags
|= DNS_MESSAGEFLAG_AD
;
3460 * Synthesize IPv6 responses if appropriate.
3462 if (RECURSIONOK(client
) &&
3463 (qtype
== dns_rdatatype_aaaa
|| qtype
== dns_rdatatype_ptr
) &&
3464 client
->message
->rdclass
== dns_rdataclass_in
&&
3465 ns_client_checkacl(client
, "v6 synthesis",
3466 client
->view
->v6synthesisacl
,
3467 ISC_FALSE
, ISC_LOG_DEBUG(9)) == ISC_R_SUCCESS
)
3469 if (qtype
== dns_rdatatype_aaaa
) {
3471 ns_client_attach(client
, &qclient
);
3472 synth_fwd_start(qclient
);
3475 INSIST(qtype
== dns_rdatatype_ptr
);
3476 /* Must be 32 nibbles + "ip6" + "int" + root */
3477 if (dns_name_countlabels(client
->query
.qname
) == 32 + 3 &&
3478 dns_name_issubdomain(client
->query
.qname
, &ip6int_name
)) {
3480 ns_client_attach(client
, &qclient
);
3481 synth_rev_start(qclient
);
3488 ns_client_attach(client
, &qclient
);
3489 query_find(qclient
, NULL
, qtype
);
3493 * Generate a synthetic IPv6 forward mapping response for the current
3494 * query of 'client'.
3497 synth_fwd_start(ns_client_t
*client
) {
3498 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
, NS_LOGMODULE_QUERY
,
3499 ISC_LOG_DEBUG(5), "generating synthetic AAAA response");
3501 synth_fwd_startfind(client
);
3505 * Start an ADB find to get addresses, or more addresses, for
3506 * a synthetic IPv6 forward mapping response.
3509 synth_fwd_startfind(ns_client_t
*client
) {
3510 dns_adbfind_t
*find
= NULL
;
3511 isc_result_t result
;
3512 dns_fixedname_t target_fixed
;
3515 dns_fixedname_init(&target_fixed
);
3516 target
= dns_fixedname_name(&target_fixed
);
3519 result
= dns_adb_createfind(client
->view
->adb
, client
->task
,
3520 synth_fwd_finddone
, client
, client
->query
.qname
,
3522 DNS_ADBFIND_WANTEVENT
| DNS_ADBFIND_RETURNLAME
|
3523 DNS_ADBFIND_INET6
, client
->now
,
3526 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
, NS_LOGMODULE_QUERY
,
3527 ISC_LOG_DEBUG(5), "find returned %s",
3528 isc_result_totext(result
));
3530 if (result
== DNS_R_ALIAS
) {
3531 dns_name_t
*ptarget
= NULL
;
3532 dns_name_t
*tname
= NULL
;
3537 * Make a persistent copy of the 'target' name data in 'ptarget';
3538 * it will become the new query name.
3540 dbuf
= query_getnamebuf(client
);
3543 ptarget
= query_newname(client
, dbuf
, &b
);
3544 if (ptarget
== NULL
)
3546 dns_name_copy(target
, ptarget
, NULL
);
3548 dns_adb_destroyfind(&find
);
3551 * Get another temporary name 'tname' for insertion into the
3554 result
= dns_message_gettempname(client
->message
, &tname
);
3555 if (result
!= ISC_R_SUCCESS
)
3557 dns_name_init(tname
, NULL
);
3558 result
= query_addcnamelike(client
, client
->query
.qname
,
3559 ptarget
, 0 /* XXX ttl */, &tname
,
3560 dns_rdatatype_cname
);
3562 dns_message_puttempname(client
->message
, &tname
);
3563 if (result
!= ISC_R_SUCCESS
)
3566 query_maybeputqname(client
);
3567 client
->query
.qname
= ptarget
;
3568 query_keepname(client
, ptarget
, dbuf
);
3570 if (client
->query
.restarts
< MAX_RESTARTS
) {
3571 client
->query
.restarts
++;
3575 * Probably a CNAME loop. Reply with partial
3578 result
= ISC_R_SUCCESS
;
3581 } else if (result
!= ISC_R_SUCCESS
) {
3583 dns_adb_destroyfind(&find
);
3587 if ((find
->options
& DNS_ADBFIND_WANTEVENT
) != 0) {
3588 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
, NS_LOGMODULE_QUERY
,
3589 ISC_LOG_DEBUG(5), "find will send event");
3591 synth_fwd_respond(client
, find
);
3592 dns_adb_destroyfind(&find
);
3597 result
= DNS_R_SERVFAIL
;
3599 synth_finish(client
, result
);
3603 * Handle an ADB finddone event generated as part of synthetic IPv6
3604 * forward mapping processing.
3607 synth_fwd_finddone(isc_task_t
*task
, isc_event_t
*ev
) {
3608 ns_client_t
*client
= ev
->ev_arg
;
3609 dns_adbfind_t
*find
= ev
->ev_sender
;
3610 isc_eventtype_t evtype
= ev
->ev_type
;
3614 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
, NS_LOGMODULE_QUERY
,
3615 ISC_LOG_DEBUG(5), "got find event");
3617 if (evtype
== DNS_EVENT_ADBNOMOREADDRESSES
)
3618 synth_fwd_respond(client
, find
);
3619 else if (evtype
== DNS_EVENT_ADBMOREADDRESSES
)
3620 synth_fwd_startfind(client
);
3622 synth_finish(client
, DNS_R_SERVFAIL
);
3624 isc_event_free(&ev
);
3625 dns_adb_destroyfind(&find
);
3630 * Generate a synthetic IPv6 forward mapping response based on
3631 * a completed ADB lookup.
3634 synth_fwd_respond(ns_client_t
*client
, dns_adbfind_t
*find
) {
3635 dns_adbaddrinfo_t
*ai
;
3636 dns_name_t
*tname
= NULL
;
3637 dns_rdataset_t
*rdataset
= NULL
;
3638 dns_rdatalist_t
*rdatalist
= NULL
;
3639 isc_result_t result
;
3641 result
= dns_message_gettempname(client
->message
, &tname
);
3642 if (result
!= ISC_R_SUCCESS
)
3644 dns_name_init(tname
, NULL
);
3646 result
= dns_message_gettemprdatalist(client
->message
, &rdatalist
);
3647 if (result
!= ISC_R_SUCCESS
)
3650 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
3651 if (result
!= ISC_R_SUCCESS
)
3653 dns_rdataset_init(rdataset
);
3655 ISC_LIST_INIT(rdatalist
->rdata
);
3657 rdatalist
->type
= dns_rdatatype_aaaa
;
3658 rdatalist
->covers
= 0;
3659 rdatalist
->rdclass
= client
->message
->rdclass
;
3662 dns_name_clone(client
->query
.qname
, tname
);
3664 for (ai
= ISC_LIST_HEAD(find
->list
);
3666 ai
= ISC_LIST_NEXT(ai
, publink
)) {
3667 dns_rdata_t
*rdata
= NULL
;
3669 struct sockaddr_in6
*sin6
= &ai
->sockaddr
.type
.sin6
;
3671 * Could it be useful to return IPv4 addresses as A records?
3673 if (sin6
->sin6_family
!= AF_INET6
)
3676 result
= dns_message_gettemprdata(client
->message
, &rdata
);
3677 if (result
!= ISC_R_SUCCESS
)
3680 rdata
->data
= (unsigned char *) &sin6
->sin6_addr
;
3682 rdata
->rdclass
= client
->message
->rdclass
;
3683 rdata
->type
= dns_rdatatype_aaaa
;
3684 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
3687 dns_rdatalist_tordataset(rdatalist
, rdataset
);
3689 query_addrrset(client
, &tname
, &rdataset
, NULL
, NULL
,
3690 DNS_SECTION_ANSWER
);
3694 dns_message_puttempname(client
->message
, &tname
);
3696 if (rdataset
!= NULL
) {
3697 if (dns_rdataset_isassociated(rdataset
))
3698 dns_rdataset_disassociate(rdataset
);
3699 dns_message_puttemprdataset(client
->message
, &rdataset
);
3702 synth_finish(client
, result
);
3706 * Finish synthetic IPv6 forward mapping processing.
3709 synth_finish(ns_client_t
*client
, isc_result_t result
) {
3710 if (result
== ISC_R_SUCCESS
)
3713 query_error(client
, result
);
3714 ns_client_detach(&client
);
3717 static signed char ascii2hex
[256] = {
3718 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3719 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3720 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3721 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
3722 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3723 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3724 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3725 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3726 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3727 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3728 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3729 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3730 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3731 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3732 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3733 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
3737 * Convert label 'i' of 'name' into its hexadecimal value, storing it
3738 * in '*hexp'. If the label is not a valid hex nibble, return ISC_R_FAILURE.
3741 label2hex(dns_name_t
*name
, int i
, int *hexp
) {
3744 dns_name_getlabel(name
, i
, &label
);
3745 if (label
.length
!= 2 || label
.base
[0] != '\001')
3746 return (ISC_R_FAILURE
);
3747 hexval
= ascii2hex
[label
.base
[1]];
3749 return (ISC_R_FAILURE
);
3751 return (ISC_R_SUCCESS
);
3755 * Convert the ip6.int name 'name' into the corresponding IPv6 address
3759 nibbles2netaddr(dns_name_t
*name
, isc_netaddr_t
*na
) {
3760 isc_result_t result
;
3761 struct in6_addr ina6
;
3762 unsigned char *addrdata
= (unsigned char *) &ina6
;
3765 for (i
= 0; i
< 16; i
++) {
3767 result
= label2hex(name
, 2 * i
, &hex0
);
3768 if (result
!= ISC_R_SUCCESS
)
3770 result
= label2hex(name
, 2 * i
+ 1, &hex1
);
3771 if (result
!= ISC_R_SUCCESS
)
3773 addrdata
[15-i
] = (hex1
<< 4) | hex0
;
3775 isc_netaddr_fromin6(na
, &ina6
);
3776 return (ISC_R_SUCCESS
);
3780 * Generate a synthetic IPv6 reverse mapping response for the current
3781 * query of 'client'.
3784 synth_rev_start(ns_client_t
*client
) {
3785 isc_result_t result
;
3786 dns_byaddr_t
*byaddr_dummy
= NULL
;
3788 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
, NS_LOGMODULE_QUERY
,
3789 ISC_LOG_DEBUG(5), "generating synthetic PTR response");
3791 result
= nibbles2netaddr(client
->query
.qname
, &client
->query
.synth
.na
);
3792 if (result
!= ISC_R_SUCCESS
) {
3793 result
= DNS_R_NXDOMAIN
;
3797 /* Try IP6.ARPA first. */
3798 result
= dns_byaddr_create(client
->mctx
,
3799 &client
->query
.synth
.na
,
3801 DNS_BYADDROPT_IPV6NIBBLE
,
3803 synth_rev_byaddrdone_arpa
,
3804 client
, &byaddr_dummy
);
3805 if (result
== ISC_R_SUCCESS
)
3806 return; /* Wait for completion event. */
3808 synth_finish(client
, result
);
3812 synth_rev_byaddrdone_arpa(isc_task_t
*task
, isc_event_t
*event
) {
3813 isc_result_t result
;
3814 dns_byaddrevent_t
*bevent
= (dns_byaddrevent_t
*)event
;
3815 ns_client_t
*client
= event
->ev_arg
;
3816 dns_byaddr_t
*byaddr
= event
->ev_sender
;
3817 dns_byaddr_t
*byaddr_dummy
= NULL
;
3821 if (bevent
->result
== ISC_R_SUCCESS
) {
3822 synth_rev_respond(client
, bevent
);
3824 /* Try IP6.INT next. */
3825 result
= dns_byaddr_create(client
->mctx
,
3826 &client
->query
.synth
.na
,
3828 DNS_BYADDROPT_IPV6NIBBLE
|
3829 DNS_BYADDROPT_IPV6INT
,
3831 synth_rev_byaddrdone_int
,
3832 client
, &byaddr_dummy
);
3833 if (result
!= ISC_R_SUCCESS
)
3834 synth_finish(client
, result
);
3836 dns_byaddr_destroy(&byaddr
);
3837 isc_event_free(&event
);
3841 synth_rev_byaddrdone_int(isc_task_t
*task
, isc_event_t
*event
) {
3842 dns_byaddrevent_t
*bevent
= (dns_byaddrevent_t
*)event
;
3843 ns_client_t
*client
= event
->ev_arg
;
3844 dns_byaddr_t
*byaddr
= event
->ev_sender
;
3848 if (bevent
->result
== ISC_R_SUCCESS
) {
3849 synth_rev_respond(client
, bevent
);
3850 } else if (bevent
->result
== DNS_R_NCACHENXDOMAIN
||
3851 bevent
->result
== DNS_R_NCACHENXRRSET
||
3852 bevent
->result
== DNS_R_NXDOMAIN
||
3853 bevent
->result
== DNS_R_NXRRSET
) {
3855 * We could give a NOERROR/NODATA response instead
3856 * in some cases, but since there may be any combination
3857 * of NXDOMAIN and NXRRSET results from the IP6.INT
3858 * and IP6.ARPA lookups, it could still be wrong with
3859 * respect to one or the other.
3861 synth_finish(client
, DNS_R_NXDOMAIN
);
3863 synth_finish(client
, bevent
->result
);
3865 isc_event_free(&event
);
3866 dns_byaddr_destroy(&byaddr
);
3870 synth_rev_respond(ns_client_t
*client
, dns_byaddrevent_t
*bevent
) {
3871 isc_result_t result
= ISC_R_SUCCESS
;
3874 for (name
= ISC_LIST_HEAD(bevent
->names
);
3876 name
= ISC_LIST_NEXT(name
, link
))
3878 dns_name_t
*tname
= NULL
;
3881 * Get a temporary name 'tname' for insertion into the
3884 result
= dns_message_gettempname(client
->message
, &tname
);
3885 if (result
!= ISC_R_SUCCESS
)
3887 dns_name_init(tname
, NULL
);
3889 result
= query_addcnamelike(client
, client
->query
.qname
,
3890 name
, 0 /* XXX ttl */,
3891 &tname
, dns_rdatatype_ptr
);
3893 dns_message_puttempname(client
->message
, &tname
);
3894 if (result
!= ISC_R_SUCCESS
)
3898 synth_finish(client
, result
);