1/*	$NetBSD: query.c,v 1.7.2.3.2.1 2014/01/15 10:06:40 bouyer Exp $	*/
2
3/*
4 * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003  Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/* Id */
21
22/*! \file */
23
24#include <config.h>
25
26#include <string.h>
27
28#include <isc/hex.h>
29#include <isc/mem.h>
30#include <isc/serial.h>
31#include <isc/stats.h>
32#include <isc/util.h>
33
34#include <dns/adb.h>
35#include <dns/byaddr.h>
36#include <dns/db.h>
37#include <dns/dlz.h>
38#include <dns/dns64.h>
39#include <dns/dnssec.h>
40#include <dns/events.h>
41#include <dns/message.h>
42#include <dns/ncache.h>
43#include <dns/nsec3.h>
44#include <dns/order.h>
45#include <dns/rdata.h>
46#include <dns/rdataclass.h>
47#include <dns/rdatalist.h>
48#include <dns/rdataset.h>
49#include <dns/rdatasetiter.h>
50#include <dns/rdatastruct.h>
51#include <dns/rdatatype.h>
52#include <dns/resolver.h>
53#include <dns/result.h>
54#include <dns/stats.h>
55#include <dns/tkey.h>
56#include <dns/view.h>
57#include <dns/zone.h>
58#include <dns/zt.h>
59
60#include <named/client.h>
61#include <named/globals.h>
62#include <named/log.h>
63#include <named/server.h>
64#include <named/sortlist.h>
65#include <named/xfrout.h>
66
67#if 0
68/*
69 * It has been recommended that DNS64 be changed to return excluded
70 * AAAA addresses if DNS64 synthesis does not occur.  This minimises
71 * the impact on the lookup results.  While most DNS AAAA lookups are
72 * done to send IP packets to a host, not all of them are and filtering
73 * excluded addresses has a negative impact on those uses.
74 */
75#define dns64_bis_return_excluded_addresses 1
76#endif
77
78/*% Partial answer? */
79#define PARTIALANSWER(c)	(((c)->query.attributes & \
80				  NS_QUERYATTR_PARTIALANSWER) != 0)
81/*% Use Cache? */
82#define USECACHE(c)		(((c)->query.attributes & \
83				  NS_QUERYATTR_CACHEOK) != 0)
84/*% Recursion OK? */
85#define RECURSIONOK(c)		(((c)->query.attributes & \
86				  NS_QUERYATTR_RECURSIONOK) != 0)
87/*% Recursing? */
88#define RECURSING(c)		(((c)->query.attributes & \
89				  NS_QUERYATTR_RECURSING) != 0)
90/*% Cache glue ok? */
91#define CACHEGLUEOK(c)		(((c)->query.attributes & \
92				  NS_QUERYATTR_CACHEGLUEOK) != 0)
93/*% Want Recursion? */
94#define WANTRECURSION(c)	(((c)->query.attributes & \
95				  NS_QUERYATTR_WANTRECURSION) != 0)
96/*% Want DNSSEC? */
97#define WANTDNSSEC(c)		(((c)->attributes & \
98				  NS_CLIENTATTR_WANTDNSSEC) != 0)
99/*% No authority? */
100#define NOAUTHORITY(c)		(((c)->query.attributes & \
101				  NS_QUERYATTR_NOAUTHORITY) != 0)
102/*% No additional? */
103#define NOADDITIONAL(c)		(((c)->query.attributes & \
104				  NS_QUERYATTR_NOADDITIONAL) != 0)
105/*% Secure? */
106#define SECURE(c)		(((c)->query.attributes & \
107				  NS_QUERYATTR_SECURE) != 0)
108/*% DNS64 A lookup? */
109#define DNS64(c)		(((c)->query.attributes & \
110				  NS_QUERYATTR_DNS64) != 0)
111
112#define DNS64EXCLUDE(c)		(((c)->query.attributes & \
113				  NS_QUERYATTR_DNS64EXCLUDE) != 0)
114
115/*% No QNAME Proof? */
116#define NOQNAME(r)		(((r)->attributes & \
117				  DNS_RDATASETATTR_NOQNAME) != 0)
118
119#if 0
120#define CTRACE(m)       isc_log_write(ns_g_lctx, \
121				      NS_LOGCATEGORY_CLIENT, \
122				      NS_LOGMODULE_QUERY, \
123				      ISC_LOG_DEBUG(3), \
124				      "client %p: %s", client, (m))
125#define QTRACE(m)       isc_log_write(ns_g_lctx, \
126				      NS_LOGCATEGORY_GENERAL, \
127				      NS_LOGMODULE_QUERY, \
128				      ISC_LOG_DEBUG(3), \
129				      "query %p: %s", query, (m))
130#else
131#define CTRACE(m) ((void)m)
132#define QTRACE(m) ((void)m)
133#endif
134
135#define DNS_GETDB_NOEXACT 0x01U
136#define DNS_GETDB_NOLOG 0x02U
137#define DNS_GETDB_PARTIAL 0x04U
138#define DNS_GETDB_IGNOREACL 0x08U
139
140#define PENDINGOK(x)	(((x) & DNS_DBFIND_PENDINGOK) != 0)
141
142typedef struct client_additionalctx {
143	ns_client_t *client;
144	dns_rdataset_t *rdataset;
145} client_additionalctx_t;
146
147static isc_result_t
148query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
149
150static isc_boolean_t
151validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
152	 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
153
154static void
155query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
156		       dns_dbversion_t *version, ns_client_t *client,
157		       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
158		       dns_name_t *fname, isc_boolean_t exact,
159		       dns_name_t *found);
160
161static inline void
162log_queryerror(ns_client_t *client, isc_result_t result, int line, int level);
163
164static void
165rpz_st_clear(ns_client_t *client);
166
167/*%
168 * Increment query statistics counters.
169 */
170static inline void
171inc_stats(ns_client_t *client, isc_statscounter_t counter) {
172	dns_zone_t *zone = client->query.authzone;
173
174	isc_stats_increment(ns_g_server->nsstats, counter);
175
176	if (zone != NULL) {
177		isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
178		if (zonestats != NULL)
179			isc_stats_increment(zonestats, counter);
180	}
181}
182
183static void
184query_send(ns_client_t *client) {
185	isc_statscounter_t counter;
186	if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0)
187		inc_stats(client, dns_nsstatscounter_nonauthans);
188	else
189		inc_stats(client, dns_nsstatscounter_authans);
190	if (client->message->rcode == dns_rcode_noerror) {
191		if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER])) {
192			if (client->query.isreferral) {
193				counter = dns_nsstatscounter_referral;
194			} else {
195				counter = dns_nsstatscounter_nxrrset;
196			}
197		} else {
198			counter = dns_nsstatscounter_success;
199		}
200	} else if (client->message->rcode == dns_rcode_nxdomain) {
201		counter = dns_nsstatscounter_nxdomain;
202	} else {
203		/* We end up here in case of YXDOMAIN, and maybe others */
204		counter = dns_nsstatscounter_failure;
205	}
206	inc_stats(client, counter);
207	ns_client_send(client);
208}
209
210static void
211query_error(ns_client_t *client, isc_result_t result, int line) {
212	int loglevel = ISC_LOG_DEBUG(3);
213
214	switch (result) {
215	case DNS_R_SERVFAIL:
216		loglevel = ISC_LOG_DEBUG(1);
217		inc_stats(client, dns_nsstatscounter_servfail);
218		break;
219	case DNS_R_FORMERR:
220		inc_stats(client, dns_nsstatscounter_formerr);
221		break;
222	default:
223		inc_stats(client, dns_nsstatscounter_failure);
224		break;
225	}
226
227	log_queryerror(client, result, line, loglevel);
228
229	ns_client_error(client, result);
230}
231
232static void
233query_next(ns_client_t *client, isc_result_t result) {
234	if (result == DNS_R_DUPLICATE)
235		inc_stats(client, dns_nsstatscounter_duplicate);
236	else if (result == DNS_R_DROP)
237		inc_stats(client, dns_nsstatscounter_dropped);
238	else
239		inc_stats(client, dns_nsstatscounter_failure);
240	ns_client_next(client, result);
241}
242
243static inline void
244query_freefreeversions(ns_client_t *client, isc_boolean_t everything) {
245	ns_dbversion_t *dbversion, *dbversion_next;
246	unsigned int i;
247
248	for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
249	     dbversion != NULL;
250	     dbversion = dbversion_next, i++)
251	{
252		dbversion_next = ISC_LIST_NEXT(dbversion, link);
253		/*
254		 * If we're not freeing everything, we keep the first three
255		 * dbversions structures around.
256		 */
257		if (i > 3 || everything) {
258			ISC_LIST_UNLINK(client->query.freeversions, dbversion,
259					link);
260			isc_mem_put(client->mctx, dbversion,
261				    sizeof(*dbversion));
262		}
263	}
264}
265
266void
267ns_query_cancel(ns_client_t *client) {
268	LOCK(&client->query.fetchlock);
269	if (client->query.fetch != NULL) {
270		dns_resolver_cancelfetch(client->query.fetch);
271
272		client->query.fetch = NULL;
273	}
274	UNLOCK(&client->query.fetchlock);
275}
276
277static inline void
278query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
279	dns_rdataset_t *rdataset = *rdatasetp;
280
281	CTRACE("query_putrdataset");
282	if (rdataset != NULL) {
283		if (dns_rdataset_isassociated(rdataset))
284			dns_rdataset_disassociate(rdataset);
285		dns_message_puttemprdataset(client->message, rdatasetp);
286	}
287	CTRACE("query_putrdataset: done");
288}
289
290static inline void
291query_reset(ns_client_t *client, isc_boolean_t everything) {
292	isc_buffer_t *dbuf, *dbuf_next;
293	ns_dbversion_t *dbversion, *dbversion_next;
294
295	/*%
296	 * Reset the query state of a client to its default state.
297	 */
298
299	/*
300	 * Cancel the fetch if it's running.
301	 */
302	ns_query_cancel(client);
303
304	/*
305	 * Cleanup any active versions.
306	 */
307	for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
308	     dbversion != NULL;
309	     dbversion = dbversion_next) {
310		dbversion_next = ISC_LIST_NEXT(dbversion, link);
311		dns_db_closeversion(dbversion->db, &dbversion->version,
312				    ISC_FALSE);
313		dns_db_detach(&dbversion->db);
314		ISC_LIST_INITANDAPPEND(client->query.freeversions,
315				      dbversion, link);
316	}
317	ISC_LIST_INIT(client->query.activeversions);
318
319	if (client->query.authdb != NULL)
320		dns_db_detach(&client->query.authdb);
321	if (client->query.authzone != NULL)
322		dns_zone_detach(&client->query.authzone);
323
324	if (client->query.dns64_aaaa != NULL)
325		query_putrdataset(client, &client->query.dns64_aaaa);
326	if (client->query.dns64_sigaaaa != NULL)
327		query_putrdataset(client, &client->query.dns64_sigaaaa);
328	if (client->query.dns64_aaaaok != NULL) {
329		isc_mem_put(client->mctx, client->query.dns64_aaaaok,
330			    client->query.dns64_aaaaoklen *
331			    sizeof(isc_boolean_t));
332		client->query.dns64_aaaaok =  NULL;
333		client->query.dns64_aaaaoklen =  0;
334	}
335
336	query_freefreeversions(client, everything);
337
338	for (dbuf = ISC_LIST_HEAD(client->query.namebufs);
339	     dbuf != NULL;
340	     dbuf = dbuf_next) {
341		dbuf_next = ISC_LIST_NEXT(dbuf, link);
342		if (dbuf_next != NULL || everything) {
343			ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
344			isc_buffer_free(&dbuf);
345		}
346	}
347
348	if (client->query.restarts > 0) {
349		/*
350		 * client->query.qname was dynamically allocated.
351		 */
352		dns_message_puttempname(client->message,
353					&client->query.qname);
354	}
355	client->query.qname = NULL;
356	client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
357				    NS_QUERYATTR_CACHEOK |
358				    NS_QUERYATTR_SECURE);
359	client->query.restarts = 0;
360	client->query.timerset = ISC_FALSE;
361	if (client->query.rpz_st != NULL) {
362		rpz_st_clear(client);
363		if (everything) {
364			isc_mem_put(client->mctx, client->query.rpz_st,
365				    sizeof(*client->query.rpz_st));
366			client->query.rpz_st = NULL;
367		}
368	}
369	client->query.origqname = NULL;
370	client->query.dboptions = 0;
371	client->query.fetchoptions = 0;
372	client->query.gluedb = NULL;
373	client->query.authdbset = ISC_FALSE;
374	client->query.isreferral = ISC_FALSE;
375	client->query.dns64_options = 0;
376	client->query.dns64_ttl = ISC_UINT32_MAX;
377}
378
379static void
380query_next_callback(ns_client_t *client) {
381	query_reset(client, ISC_FALSE);
382}
383
384void
385ns_query_free(ns_client_t *client) {
386	query_reset(client, ISC_TRUE);
387}
388
389static inline isc_result_t
390query_newnamebuf(ns_client_t *client) {
391	isc_buffer_t *dbuf;
392	isc_result_t result;
393
394	CTRACE("query_newnamebuf");
395	/*%
396	 * Allocate a name buffer.
397	 */
398
399	dbuf = NULL;
400	result = isc_buffer_allocate(client->mctx, &dbuf, 1024);
401	if (result != ISC_R_SUCCESS) {
402		CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
403		return (result);
404	}
405	ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
406
407	CTRACE("query_newnamebuf: done");
408	return (ISC_R_SUCCESS);
409}
410
411static inline isc_buffer_t *
412query_getnamebuf(ns_client_t *client) {
413	isc_buffer_t *dbuf;
414	isc_result_t result;
415	isc_region_t r;
416
417	CTRACE("query_getnamebuf");
418	/*%
419	 * Return a name buffer with space for a maximal name, allocating
420	 * a new one if necessary.
421	 */
422
423	if (ISC_LIST_EMPTY(client->query.namebufs)) {
424		result = query_newnamebuf(client);
425		if (result != ISC_R_SUCCESS) {
426		    CTRACE("query_getnamebuf: query_newnamebuf failed: done");
427			return (NULL);
428		}
429	}
430
431	dbuf = ISC_LIST_TAIL(client->query.namebufs);
432	INSIST(dbuf != NULL);
433	isc_buffer_availableregion(dbuf, &r);
434	if (r.length < 255) {
435		result = query_newnamebuf(client);
436		if (result != ISC_R_SUCCESS) {
437		    CTRACE("query_getnamebuf: query_newnamebuf failed: done");
438			return (NULL);
439
440		}
441		dbuf = ISC_LIST_TAIL(client->query.namebufs);
442		isc_buffer_availableregion(dbuf, &r);
443		INSIST(r.length >= 255);
444	}
445	CTRACE("query_getnamebuf: done");
446	return (dbuf);
447}
448
449static inline void
450query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
451	isc_region_t r;
452
453	CTRACE("query_keepname");
454	/*%
455	 * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
456	 * adjusted to take account of that.  We do the adjustment.
457	 */
458
459	REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
460
461	dns_name_toregion(name, &r);
462	isc_buffer_add(dbuf, r.length);
463	dns_name_setbuffer(name, NULL);
464	client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
465}
466
467static inline void
468query_releasename(ns_client_t *client, dns_name_t **namep) {
469	dns_name_t *name = *namep;
470
471	/*%
472	 * 'name' is no longer needed.  Return it to our pool of temporary
473	 * names.  If it is using a name buffer, relinquish its exclusive
474	 * rights on the buffer.
475	 */
476
477	CTRACE("query_releasename");
478	if (dns_name_hasbuffer(name)) {
479		INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
480		       != 0);
481		client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
482	}
483	dns_message_puttempname(client->message, namep);
484	CTRACE("query_releasename: done");
485}
486
487static inline dns_name_t *
488query_newname(ns_client_t *client, isc_buffer_t *dbuf,
489	      isc_buffer_t *nbuf)
490{
491	dns_name_t *name;
492	isc_region_t r;
493	isc_result_t result;
494
495	REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
496
497	CTRACE("query_newname");
498	name = NULL;
499	result = dns_message_gettempname(client->message, &name);
500	if (result != ISC_R_SUCCESS) {
501		CTRACE("query_newname: dns_message_gettempname failed: done");
502		return (NULL);
503	}
504	isc_buffer_availableregion(dbuf, &r);
505	isc_buffer_init(nbuf, r.base, r.length);
506	dns_name_init(name, NULL);
507	dns_name_setbuffer(name, nbuf);
508	client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
509
510	CTRACE("query_newname: done");
511	return (name);
512}
513
514static inline dns_rdataset_t *
515query_newrdataset(ns_client_t *client) {
516	dns_rdataset_t *rdataset;
517	isc_result_t result;
518
519	CTRACE("query_newrdataset");
520	rdataset = NULL;
521	result = dns_message_gettemprdataset(client->message, &rdataset);
522	if (result != ISC_R_SUCCESS) {
523	  CTRACE("query_newrdataset: "
524		 "dns_message_gettemprdataset failed: done");
525		return (NULL);
526	}
527	dns_rdataset_init(rdataset);
528
529	CTRACE("query_newrdataset: done");
530	return (rdataset);
531}
532
533static inline isc_result_t
534query_newdbversion(ns_client_t *client, unsigned int n) {
535	unsigned int i;
536	ns_dbversion_t *dbversion;
537
538	for (i = 0; i < n; i++) {
539		dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
540		if (dbversion != NULL) {
541			dbversion->db = NULL;
542			dbversion->version = NULL;
543			ISC_LIST_INITANDAPPEND(client->query.freeversions,
544					      dbversion, link);
545		} else {
546			/*
547			 * We only return ISC_R_NOMEMORY if we couldn't
548			 * allocate anything.
549			 */
550			if (i == 0)
551				return (ISC_R_NOMEMORY);
552			else
553				return (ISC_R_SUCCESS);
554		}
555	}
556
557	return (ISC_R_SUCCESS);
558}
559
560static inline ns_dbversion_t *
561query_getdbversion(ns_client_t *client) {
562	isc_result_t result;
563	ns_dbversion_t *dbversion;
564
565	if (ISC_LIST_EMPTY(client->query.freeversions)) {
566		result = query_newdbversion(client, 1);
567		if (result != ISC_R_SUCCESS)
568			return (NULL);
569	}
570	dbversion = ISC_LIST_HEAD(client->query.freeversions);
571	INSIST(dbversion != NULL);
572	ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
573
574	return (dbversion);
575}
576
577isc_result_t
578ns_query_init(ns_client_t *client) {
579	isc_result_t result;
580
581	ISC_LIST_INIT(client->query.namebufs);
582	ISC_LIST_INIT(client->query.activeversions);
583	ISC_LIST_INIT(client->query.freeversions);
584	client->query.restarts = 0;
585	client->query.timerset = ISC_FALSE;
586	client->query.rpz_st = NULL;
587	client->query.qname = NULL;
588	result = isc_mutex_init(&client->query.fetchlock);
589	if (result != ISC_R_SUCCESS)
590		return (result);
591	client->query.fetch = NULL;
592	client->query.authdb = NULL;
593	client->query.authzone = NULL;
594	client->query.authdbset = ISC_FALSE;
595	client->query.isreferral = ISC_FALSE;
596	client->query.dns64_aaaa = NULL;
597	client->query.dns64_sigaaaa = NULL;
598	client->query.dns64_aaaaok = NULL;
599	client->query.dns64_aaaaoklen = 0;
600	query_reset(client, ISC_FALSE);
601	result = query_newdbversion(client, 3);
602	if (result != ISC_R_SUCCESS) {
603		DESTROYLOCK(&client->query.fetchlock);
604		return (result);
605	}
606	result = query_newnamebuf(client);
607	if (result != ISC_R_SUCCESS)
608		query_freefreeversions(client, ISC_TRUE);
609
610	return (result);
611}
612
613static inline ns_dbversion_t *
614query_findversion(ns_client_t *client, dns_db_t *db)
615{
616	ns_dbversion_t *dbversion;
617
618	/*%
619	 * We may already have done a query related to this
620	 * database.  If so, we must be sure to make subsequent
621	 * queries from the same version.
622	 */
623	for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
624	     dbversion != NULL;
625	     dbversion = ISC_LIST_NEXT(dbversion, link)) {
626		if (dbversion->db == db)
627			break;
628	}
629
630	if (dbversion == NULL) {
631		/*
632		 * This is a new zone for this query.  Add it to
633		 * the active list.
634		 */
635		dbversion = query_getdbversion(client);
636		if (dbversion == NULL)
637			return (NULL);
638		dns_db_attach(db, &dbversion->db);
639		dns_db_currentversion(db, &dbversion->version);
640		dbversion->acl_checked = ISC_FALSE;
641		dbversion->queryok = ISC_FALSE;
642		ISC_LIST_APPEND(client->query.activeversions,
643				dbversion, link);
644	}
645
646	return (dbversion);
647}
648
649static inline isc_result_t
650query_validatezonedb(ns_client_t *client, dns_name_t *name,
651		     dns_rdatatype_t qtype, unsigned int options,
652		     dns_zone_t *zone, dns_db_t *db,
653		     dns_dbversion_t **versionp)
654{
655	isc_result_t result;
656	dns_acl_t *queryacl;
657	ns_dbversion_t *dbversion;
658
659	REQUIRE(zone != NULL);
660	REQUIRE(db != NULL);
661
662	/*
663	 * This limits our searching to the zone where the first name
664	 * (the query target) was looked for.  This prevents following
665	 * CNAMES or DNAMES into other zones and prevents returning
666	 * additional data from other zones.
667	 */
668	if (!client->view->additionalfromauth &&
669	    client->query.authdbset &&
670	    db != client->query.authdb)
671		return (DNS_R_REFUSED);
672
673	/*
674	 * Non recursive query to a static-stub zone is prohibited; its
675	 * zone content is not public data, but a part of local configuration
676	 * and should not be disclosed.
677	 */
678	if (dns_zone_gettype(zone) == dns_zone_staticstub &&
679	    !RECURSIONOK(client)) {
680		return (DNS_R_REFUSED);
681	}
682
683	/*
684	 * If the zone has an ACL, we'll check it, otherwise
685	 * we use the view's "allow-query" ACL.  Each ACL is only checked
686	 * once per query.
687	 *
688	 * Also, get the database version to use.
689	 */
690
691	/*
692	 * Get the current version of this database.
693	 */
694	dbversion = query_findversion(client, db);
695	if (dbversion == NULL)
696		return (DNS_R_SERVFAIL);
697
698	if ((options & DNS_GETDB_IGNOREACL) != 0)
699		goto approved;
700	if (dbversion->acl_checked) {
701		if (!dbversion->queryok)
702			return (DNS_R_REFUSED);
703		goto approved;
704	}
705
706	queryacl = dns_zone_getqueryacl(zone);
707	if (queryacl == NULL) {
708		queryacl = client->view->queryacl;
709		if ((client->query.attributes &
710		     NS_QUERYATTR_QUERYOKVALID) != 0) {
711			/*
712			 * We've evaluated the view's queryacl already.  If
713			 * NS_QUERYATTR_QUERYOK is set, then the client is
714			 * allowed to make queries, otherwise the query should
715			 * be refused.
716			 */
717			dbversion->acl_checked = ISC_TRUE;
718			if ((client->query.attributes &
719			     NS_QUERYATTR_QUERYOK) == 0) {
720				dbversion->queryok = ISC_FALSE;
721				return (DNS_R_REFUSED);
722			}
723			dbversion->queryok = ISC_TRUE;
724			goto approved;
725		}
726	}
727
728	result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE);
729	if ((options & DNS_GETDB_NOLOG) == 0) {
730		char msg[NS_CLIENT_ACLMSGSIZE("query")];
731		if (result == ISC_R_SUCCESS) {
732			if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) {
733				ns_client_aclmsg("query", name, qtype,
734						 client->view->rdclass,
735						 msg, sizeof(msg));
736				ns_client_log(client,
737					      DNS_LOGCATEGORY_SECURITY,
738					      NS_LOGMODULE_QUERY,
739					      ISC_LOG_DEBUG(3),
740					      "%s approved", msg);
741			}
742		} else {
743			ns_client_aclmsg("query", name, qtype,
744					 client->view->rdclass,
745					 msg, sizeof(msg));
746			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
747				      NS_LOGMODULE_QUERY, ISC_LOG_INFO,
748				      "%s denied", msg);
749		}
750	}
751
752	if (queryacl == client->view->queryacl) {
753		if (result == ISC_R_SUCCESS) {
754			/*
755			 * We were allowed by the default
756			 * "allow-query" ACL.  Remember this so we
757			 * don't have to check again.
758			 */
759			client->query.attributes |= NS_QUERYATTR_QUERYOK;
760		}
761		/*
762		 * We've now evaluated the view's query ACL, and
763		 * the NS_QUERYATTR_QUERYOK attribute is now valid.
764		 */
765		client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
766	}
767
768	dbversion->acl_checked = ISC_TRUE;
769	if (result != ISC_R_SUCCESS) {
770		dbversion->queryok = ISC_FALSE;
771		return (DNS_R_REFUSED);
772	}
773	dbversion->queryok = ISC_TRUE;
774
775 approved:
776	/* Transfer ownership, if necessary. */
777	if (versionp != NULL)
778		*versionp = dbversion->version;
779	return (ISC_R_SUCCESS);
780}
781
782static inline isc_result_t
783query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
784		unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
785		dns_dbversion_t **versionp)
786{
787	isc_result_t result;
788	unsigned int ztoptions;
789	dns_zone_t *zone = NULL;
790	dns_db_t *db = NULL;
791	isc_boolean_t partial = ISC_FALSE;
792
793	REQUIRE(zonep != NULL && *zonep == NULL);
794	REQUIRE(dbp != NULL && *dbp == NULL);
795
796	/*%
797	 * Find a zone database to answer the query.
798	 */
799	ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?
800		DNS_ZTFIND_NOEXACT : 0;
801
802	result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
803			     &zone);
804	if (result == DNS_R_PARTIALMATCH)
805		partial = ISC_TRUE;
806	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
807		result = dns_zone_getdb(zone, &db);
808
809	if (result != ISC_R_SUCCESS)
810		goto fail;
811
812	result = query_validatezonedb(client, name, qtype, options, zone, db,
813				      versionp);
814
815	if (result != ISC_R_SUCCESS)
816		goto fail;
817
818	/* Transfer ownership. */
819	*zonep = zone;
820	*dbp = db;
821
822	if (partial && (options & DNS_GETDB_PARTIAL) != 0)
823		return (DNS_R_PARTIALMATCH);
824	return (ISC_R_SUCCESS);
825
826 fail:
827	if (zone != NULL)
828		dns_zone_detach(&zone);
829	if (db != NULL)
830		dns_db_detach(&db);
831
832	return (result);
833}
834
835static void
836rpz_log_rewrite(ns_client_t *client, const char *disabled,
837		dns_rpz_policy_t policy, dns_rpz_type_t type,
838		dns_name_t *rpz_qname) {
839	char qname_buf[DNS_NAME_FORMATSIZE];
840	char rpz_qname_buf[DNS_NAME_FORMATSIZE];
841
842	if (!isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL))
843		return;
844
845	dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf));
846	dns_name_format(rpz_qname, rpz_qname_buf, sizeof(rpz_qname_buf));
847
848	ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY,
849		      DNS_RPZ_INFO_LEVEL, "%srpz %s %s rewrite %s via %s",
850		      disabled,
851		      dns_rpz_type2str(type), dns_rpz_policy2str(policy),
852		      qname_buf, rpz_qname_buf);
853}
854
855static void
856rpz_log_fail(ns_client_t *client, int level,
857	     dns_rpz_type_t rpz_type, dns_name_t *name,
858	     const char *str, isc_result_t result)
859{
860	char namebuf1[DNS_NAME_FORMATSIZE];
861	char namebuf2[DNS_NAME_FORMATSIZE];
862
863	if (!isc_log_wouldlog(ns_g_lctx, level))
864		return;
865
866	dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1));
867	dns_name_format(name, namebuf2, sizeof(namebuf2));
868	ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS,
869		      NS_LOGMODULE_QUERY, level,
870		      "rpz %s rewrite %s via %s %sfailed: %s",
871		      dns_rpz_type2str(rpz_type),
872		      namebuf1, namebuf2, str, isc_result_totext(result));
873}
874
875/*
876 * Get a policy rewrite zone database.
877 */
878static isc_result_t
879rpz_getdb(ns_client_t *client, dns_rpz_type_t rpz_type, dns_name_t *rpz_qname,
880	  dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp)
881{
882	char namebuf1[DNS_NAME_FORMATSIZE];
883	char namebuf2[DNS_NAME_FORMATSIZE];
884	dns_dbversion_t *rpz_version = NULL;
885	isc_result_t result;
886
887	result = query_getzonedb(client, rpz_qname, dns_rdatatype_any,
888				 DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version);
889	if (result == ISC_R_SUCCESS) {
890		if (isc_log_wouldlog(ns_g_lctx, DNS_RPZ_DEBUG_LEVEL2)) {
891			dns_name_format(client->query.qname, namebuf1,
892					sizeof(namebuf1));
893			dns_name_format(rpz_qname, namebuf2, sizeof(namebuf2));
894			ns_client_log(client, DNS_LOGCATEGORY_RPZ,
895				      NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2,
896				      "try rpz %s rewrite %s via %s",
897				      dns_rpz_type2str(rpz_type),
898				      namebuf1, namebuf2);
899		}
900		*versionp = rpz_version;
901		return (ISC_R_SUCCESS);
902	}
903	rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, rpz_qname,
904		     "query_getzonedb() ", result);
905	return (result);
906}
907
908static inline isc_result_t
909query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
910		 dns_db_t **dbp, unsigned int options)
911{
912	isc_result_t result;
913	isc_boolean_t check_acl;
914	dns_db_t *db = NULL;
915
916	REQUIRE(dbp != NULL && *dbp == NULL);
917
918	/*%
919	 * Find a cache database to answer the query.
920	 * This may fail with DNS_R_REFUSED if the client
921	 * is not allowed to use the cache.
922	 */
923
924	if (!USECACHE(client))
925		return (DNS_R_REFUSED);
926	dns_db_attach(client->view->cachedb, &db);
927
928	if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) != 0) {
929		/*
930		 * We've evaluated the view's cacheacl already.  If
931		 * NS_QUERYATTR_CACHEACLOK is set, then the client is
932		 * allowed to make queries, otherwise the query should
933		 * be refused.
934		 */
935		check_acl = ISC_FALSE;
936		if ((client->query.attributes & NS_QUERYATTR_CACHEACLOK) == 0)
937			goto refuse;
938	} else {
939		/*
940		 * We haven't evaluated the view's queryacl yet.
941		 */
942		check_acl = ISC_TRUE;
943	}
944
945	if (check_acl) {
946		isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);
947		char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
948
949		result = ns_client_checkaclsilent(client, NULL,
950						  client->view->cacheacl,
951						  ISC_TRUE);
952		if (result == ISC_R_SUCCESS) {
953			/*
954			 * We were allowed by the "allow-query-cache" ACL.
955			 * Remember this so we don't have to check again.
956			 */
957			client->query.attributes |=
958				NS_QUERYATTR_CACHEACLOK;
959			if (log && isc_log_wouldlog(ns_g_lctx,
960						     ISC_LOG_DEBUG(3)))
961			{
962				ns_client_aclmsg("query (cache)", name, qtype,
963						 client->view->rdclass,
964						 msg, sizeof(msg));
965				ns_client_log(client,
966					      DNS_LOGCATEGORY_SECURITY,
967					      NS_LOGMODULE_QUERY,
968					      ISC_LOG_DEBUG(3),
969					      "%s approved", msg);
970			}
971		} else if (log) {
972			ns_client_aclmsg("query (cache)", name, qtype,
973					 client->view->rdclass, msg,
974					 sizeof(msg));
975			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
976				      NS_LOGMODULE_QUERY, ISC_LOG_INFO,
977				      "%s denied", msg);
978		}
979		/*
980		 * We've now evaluated the view's query ACL, and
981		 * the NS_QUERYATTR_CACHEACLOKVALID attribute is now valid.
982		 */
983		client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID;
984
985		if (result != ISC_R_SUCCESS)
986			goto refuse;
987	}
988
989	/* Approved. */
990
991	/* Transfer ownership. */
992	*dbp = db;
993
994	return (ISC_R_SUCCESS);
995
996 refuse:
997	result = DNS_R_REFUSED;
998
999	if (db != NULL)
1000		dns_db_detach(&db);
1001
1002	return (result);
1003}
1004
1005
1006static inline isc_result_t
1007query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
1008	    unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
1009	    dns_dbversion_t **versionp, isc_boolean_t *is_zonep)
1010{
1011	isc_result_t result;
1012
1013	isc_result_t tresult;
1014	unsigned int namelabels;
1015	unsigned int zonelabels;
1016	dns_zone_t *zone = NULL;
1017	dns_db_t *tdbp;
1018
1019	REQUIRE(zonep != NULL && *zonep == NULL);
1020
1021	tdbp = NULL;
1022
1023	/* Calculate how many labels are in name. */
1024	namelabels = dns_name_countlabels(name);
1025	zonelabels = 0;
1026
1027	/* Try to find name in bind's standard database. */
1028	result = query_getzonedb(client, name, qtype, options, &zone,
1029				 dbp, versionp);
1030
1031	/* See how many labels are in the zone's name.	  */
1032	if (result == ISC_R_SUCCESS && zone != NULL)
1033		zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));
1034	/*
1035	 * If # zone labels < # name labels, try to find an even better match
1036	 * Only try if a DLZ driver is loaded for this view
1037	 */
1038	if (zonelabels < namelabels && client->view->dlzdatabase != NULL) {
1039		tresult = dns_dlzfindzone(client->view, name,
1040					  zonelabels, &tdbp);
1041		 /* If we successful, we found a better match. */
1042		if (tresult == ISC_R_SUCCESS) {
1043			/*
1044			 * If the previous search returned a zone, detach it.
1045			 */
1046			if (zone != NULL)
1047				dns_zone_detach(&zone);
1048
1049			/*
1050			 * If the previous search returned a database,
1051			 * detach it.
1052			 */
1053			if (*dbp != NULL)
1054				dns_db_detach(dbp);
1055
1056			/*
1057			 * If the previous search returned a version, clear it.
1058			 */
1059			*versionp = NULL;
1060
1061			/*
1062			 * Get our database version.
1063			 */
1064			dns_db_currentversion(tdbp, versionp);
1065
1066			/*
1067			 * Be sure to return our database.
1068			 */
1069			*dbp = tdbp;
1070
1071			/*
1072			 * We return a null zone, No stats for DLZ zones.
1073			 */
1074			zone = NULL;
1075			result = tresult;
1076		}
1077	}
1078
1079	/* If successful, Transfer ownership of zone. */
1080	if (result == ISC_R_SUCCESS) {
1081		*zonep = zone;
1082		/*
1083		 * If neither attempt above succeeded, return the cache instead
1084		 */
1085		*is_zonep = ISC_TRUE;
1086	} else if (result == ISC_R_NOTFOUND) {
1087		result = query_getcachedb(client, name, qtype, dbp, options);
1088		*is_zonep = ISC_FALSE;
1089	}
1090	return (result);
1091}
1092
1093static inline isc_boolean_t
1094query_isduplicate(ns_client_t *client, dns_name_t *name,
1095		  dns_rdatatype_t type, dns_name_t **mnamep)
1096{
1097	dns_section_t section;
1098	dns_name_t *mname = NULL;
1099	isc_result_t result;
1100
1101	CTRACE("query_isduplicate");
1102
1103	for (section = DNS_SECTION_ANSWER;
1104	     section <= DNS_SECTION_ADDITIONAL;
1105	     section++) {
1106		result = dns_message_findname(client->message, section,
1107					      name, type, 0, &mname, NULL);
1108		if (result == ISC_R_SUCCESS) {
1109			/*
1110			 * We've already got this RRset in the response.
1111			 */
1112			CTRACE("query_isduplicate: true: done");
1113			return (ISC_TRUE);
1114		} else if (result == DNS_R_NXRRSET) {
1115			/*
1116			 * The name exists, but the rdataset does not.
1117			 */
1118			if (section == DNS_SECTION_ADDITIONAL)
1119				break;
1120		} else
1121			RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
1122		mname = NULL;
1123	}
1124
1125	if (mnamep != NULL)
1126		*mnamep = mname;
1127
1128	CTRACE("query_isduplicate: false: done");
1129	return (ISC_FALSE);
1130}
1131
1132static isc_result_t
1133query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
1134	ns_client_t *client = arg;
1135	isc_result_t result, eresult;
1136	dns_dbnode_t *node;
1137	dns_db_t *db;
1138	dns_name_t *fname, *mname;
1139	dns_rdataset_t *rdataset, *sigrdataset, *trdataset;
1140	isc_buffer_t *dbuf;
1141	isc_buffer_t b;
1142	dns_dbversion_t *version;
1143	isc_boolean_t added_something, need_addname;
1144	dns_zone_t *zone;
1145	dns_rdatatype_t type;
1146	dns_clientinfomethods_t cm;
1147	dns_clientinfo_t ci;
1148
1149	REQUIRE(NS_CLIENT_VALID(client));
1150	REQUIRE(qtype != dns_rdatatype_any);
1151
1152	if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))
1153		return (ISC_R_SUCCESS);
1154
1155	CTRACE("query_addadditional");
1156
1157	/*
1158	 * Initialization.
1159	 */
1160	eresult = ISC_R_SUCCESS;
1161	fname = NULL;
1162	rdataset = NULL;
1163	sigrdataset = NULL;
1164	trdataset = NULL;
1165	db = NULL;
1166	version = NULL;
1167	node = NULL;
1168	added_something = ISC_FALSE;
1169	need_addname = ISC_FALSE;
1170	zone = NULL;
1171
1172	dns_clientinfomethods_init(&cm, ns_client_sourceip);
1173	dns_clientinfo_init(&ci, client);
1174
1175	/*
1176	 * We treat type A additional section processing as if it
1177	 * were "any address type" additional section processing.
1178	 * To avoid multiple lookups, we do an 'any' database
1179	 * lookup and iterate over the node.
1180	 */
1181	if (qtype == dns_rdatatype_a)
1182		type = dns_rdatatype_any;
1183	else
1184		type = qtype;
1185
1186	/*
1187	 * Get some resources.
1188	 */
1189	dbuf = query_getnamebuf(client);
1190	if (dbuf == NULL)
1191		goto cleanup;
1192	fname = query_newname(client, dbuf, &b);
1193	rdataset = query_newrdataset(client);
1194	if (fname == NULL || rdataset == NULL)
1195		goto cleanup;
1196	if (WANTDNSSEC(client)) {
1197		sigrdataset = query_newrdataset(client);
1198		if (sigrdataset == NULL)
1199			goto cleanup;
1200	}
1201
1202	/*
1203	 * Look for a zone database that might contain authoritative
1204	 * additional data.
1205	 */
1206	result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
1207				 &zone, &db, &version);
1208	if (result != ISC_R_SUCCESS)
1209		goto try_cache;
1210
1211	CTRACE("query_addadditional: db_find");
1212
1213	/*
1214	 * Since we are looking for authoritative data, we do not set
1215	 * the GLUEOK flag.  Glue will be looked for later, but not
1216	 * necessarily in the same database.
1217	 */
1218	node = NULL;
1219	result = dns_db_findext(db, name, version, type,
1220				client->query.dboptions,
1221				client->now, &node, fname, &cm, &ci,
1222				rdataset, sigrdataset);
1223	if (result == ISC_R_SUCCESS) {
1224		if (sigrdataset != NULL && !dns_db_issecure(db) &&
1225		    dns_rdataset_isassociated(sigrdataset))
1226			dns_rdataset_disassociate(sigrdataset);
1227		goto found;
1228	}
1229
1230	if (dns_rdataset_isassociated(rdataset))
1231		dns_rdataset_disassociate(rdataset);
1232	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
1233		dns_rdataset_disassociate(sigrdataset);
1234	if (node != NULL)
1235		dns_db_detachnode(db, &node);
1236	version = NULL;
1237	dns_db_detach(&db);
1238
1239	/*
1240	 * No authoritative data was found.  The cache is our next best bet.
1241	 */
1242
1243 try_cache:
1244	result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
1245	if (result != ISC_R_SUCCESS)
1246		/*
1247		 * Most likely the client isn't allowed to query the cache.
1248		 */
1249		goto try_glue;
1250	/*
1251	 * Attempt to validate glue.
1252	 */
1253	if (sigrdataset == NULL) {
1254		sigrdataset = query_newrdataset(client);
1255		if (sigrdataset == NULL)
1256			goto cleanup;
1257	}
1258	result = dns_db_findext(db, name, version, type,
1259				client->query.dboptions |
1260				 DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
1261				client->now, &node, fname, &cm, &ci,
1262				rdataset, sigrdataset);
1263	if (result == DNS_R_GLUE &&
1264	    validate(client, db, fname, rdataset, sigrdataset))
1265		result = ISC_R_SUCCESS;
1266	if (!WANTDNSSEC(client))
1267		query_putrdataset(client, &sigrdataset);
1268	if (result == ISC_R_SUCCESS)
1269		goto found;
1270
1271	if (dns_rdataset_isassociated(rdataset))
1272		dns_rdataset_disassociate(rdataset);
1273	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
1274		dns_rdataset_disassociate(sigrdataset);
1275	if (node != NULL)
1276		dns_db_detachnode(db, &node);
1277	dns_db_detach(&db);
1278
1279 try_glue:
1280	/*
1281	 * No cached data was found.  Glue is our last chance.
1282	 * RFC1035 sayeth:
1283	 *
1284	 *	NS records cause both the usual additional section
1285	 *	processing to locate a type A record, and, when used
1286	 *	in a referral, a special search of the zone in which
1287	 *	they reside for glue information.
1288	 *
1289	 * This is the "special search".  Note that we must search
1290	 * the zone where the NS record resides, not the zone it
1291	 * points to, and that we only do the search in the delegation
1292	 * case (identified by client->query.gluedb being set).
1293	 */
1294
1295	if (client->query.gluedb == NULL)
1296		goto cleanup;
1297
1298	/*
1299	 * Don't poison caches using the bailiwick protection model.
1300	 */
1301	if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
1302		goto cleanup;
1303
1304	dns_db_attach(client->query.gluedb, &db);
1305	result = dns_db_findext(db, name, version, type,
1306				client->query.dboptions | DNS_DBFIND_GLUEOK,
1307				client->now, &node, fname, &cm, &ci,
1308				rdataset, sigrdataset);
1309	if (!(result == ISC_R_SUCCESS ||
1310	      result == DNS_R_ZONECUT ||
1311	      result == DNS_R_GLUE))
1312		goto cleanup;
1313
1314 found:
1315	/*
1316	 * We have found a potential additional data rdataset, or
1317	 * at least a node to iterate over.
1318	 */
1319	query_keepname(client, fname, dbuf);
1320
1321	/*
1322	 * If we have an rdataset, add it to the additional data
1323	 * section.
1324	 */
1325	mname = NULL;
1326	if (dns_rdataset_isassociated(rdataset) &&
1327	    !query_isduplicate(client, fname, type, &mname)) {
1328		if (mname != NULL) {
1329			INSIST(mname != fname);
1330			query_releasename(client, &fname);
1331			fname = mname;
1332		} else
1333			need_addname = ISC_TRUE;
1334		ISC_LIST_APPEND(fname->list, rdataset, link);
1335		trdataset = rdataset;
1336		rdataset = NULL;
1337		added_something = ISC_TRUE;
1338		/*
1339		 * Note: we only add SIGs if we've added the type they cover,
1340		 * so we do not need to check if the SIG rdataset is already
1341		 * in the response.
1342		 */
1343		if (sigrdataset != NULL &&
1344		    dns_rdataset_isassociated(sigrdataset))
1345		{
1346			ISC_LIST_APPEND(fname->list, sigrdataset, link);
1347			sigrdataset = NULL;
1348		}
1349	}
1350
1351	if (qtype == dns_rdatatype_a) {
1352#ifdef ALLOW_FILTER_AAAA_ON_V4
1353		isc_boolean_t have_a = ISC_FALSE;
1354#endif
1355
1356		/*
1357		 * We now go looking for A and AAAA records, along with
1358		 * their signatures.
1359		 *
1360		 * XXXRTH  This code could be more efficient.
1361		 */
1362		if (rdataset != NULL) {
1363			if (dns_rdataset_isassociated(rdataset))
1364				dns_rdataset_disassociate(rdataset);
1365		} else {
1366			rdataset = query_newrdataset(client);
1367			if (rdataset == NULL)
1368				goto addname;
1369		}
1370		if (sigrdataset != NULL) {
1371			if (dns_rdataset_isassociated(sigrdataset))
1372				dns_rdataset_disassociate(sigrdataset);
1373		} else if (WANTDNSSEC(client)) {
1374			sigrdataset = query_newrdataset(client);
1375			if (sigrdataset == NULL)
1376				goto addname;
1377		}
1378		if (query_isduplicate(client, fname, dns_rdatatype_a, NULL))
1379			goto aaaa_lookup;
1380		result = dns_db_findrdataset(db, node, version,
1381					     dns_rdatatype_a, 0,
1382					     client->now,
1383					     rdataset, sigrdataset);
1384		if (result == DNS_R_NCACHENXDOMAIN)
1385			goto addname;
1386		if (result == DNS_R_NCACHENXRRSET) {
1387			dns_rdataset_disassociate(rdataset);
1388			if (sigrdataset != NULL &&
1389			    dns_rdataset_isassociated(sigrdataset))
1390				dns_rdataset_disassociate(sigrdataset);
1391		}
1392		if (result == ISC_R_SUCCESS) {
1393			mname = NULL;
1394#ifdef ALLOW_FILTER_AAAA_ON_V4
1395			have_a = ISC_TRUE;
1396#endif
1397			if (!query_isduplicate(client, fname,
1398					       dns_rdatatype_a, &mname)) {
1399				if (mname != fname) {
1400					if (mname != NULL) {
1401						query_releasename(client, &fname);
1402						fname = mname;
1403					} else
1404						need_addname = ISC_TRUE;
1405				}
1406				ISC_LIST_APPEND(fname->list, rdataset, link);
1407				added_something = ISC_TRUE;
1408				if (sigrdataset != NULL &&
1409				    dns_rdataset_isassociated(sigrdataset))
1410				{
1411					ISC_LIST_APPEND(fname->list,
1412							sigrdataset, link);
1413					sigrdataset =
1414						query_newrdataset(client);
1415				}
1416				rdataset = query_newrdataset(client);
1417				if (rdataset == NULL)
1418					goto addname;
1419				if (WANTDNSSEC(client) && sigrdataset == NULL)
1420					goto addname;
1421			} else {
1422				dns_rdataset_disassociate(rdataset);
1423				if (sigrdataset != NULL &&
1424				    dns_rdataset_isassociated(sigrdataset))
1425					dns_rdataset_disassociate(sigrdataset);
1426			}
1427		}
1428  aaaa_lookup:
1429		if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
1430			goto addname;
1431		result = dns_db_findrdataset(db, node, version,
1432					     dns_rdatatype_aaaa, 0,
1433					     client->now,
1434					     rdataset, sigrdataset);
1435		if (result == DNS_R_NCACHENXDOMAIN)
1436			goto addname;
1437		if (result == DNS_R_NCACHENXRRSET) {
1438			dns_rdataset_disassociate(rdataset);
1439			if (sigrdataset != NULL &&
1440			    dns_rdataset_isassociated(sigrdataset))
1441				dns_rdataset_disassociate(sigrdataset);
1442		}
1443		if (result == ISC_R_SUCCESS) {
1444			mname = NULL;
1445			/*
1446			 * There's an A; check whether we're filtering AAAA
1447			 */
1448#ifdef ALLOW_FILTER_AAAA_ON_V4
1449			if (have_a &&
1450			    (client->filter_aaaa == dns_v4_aaaa_break_dnssec ||
1451			    (client->filter_aaaa == dns_v4_aaaa_filter &&
1452			     (!WANTDNSSEC(client) || sigrdataset == NULL ||
1453			      !dns_rdataset_isassociated(sigrdataset)))))
1454				goto addname;
1455#endif
1456			if (!query_isduplicate(client, fname,
1457					       dns_rdatatype_aaaa, &mname)) {
1458				if (mname != fname) {
1459					if (mname != NULL) {
1460						query_releasename(client, &fname);
1461						fname = mname;
1462					} else
1463						need_addname = ISC_TRUE;
1464				}
1465				ISC_LIST_APPEND(fname->list, rdataset, link);
1466				added_something = ISC_TRUE;
1467				if (sigrdataset != NULL &&
1468				    dns_rdataset_isassociated(sigrdataset))
1469				{
1470					ISC_LIST_APPEND(fname->list,
1471							sigrdataset, link);
1472					sigrdataset = NULL;
1473				}
1474				rdataset = NULL;
1475			}
1476		}
1477	}
1478
1479 addname:
1480	CTRACE("query_addadditional: addname");
1481	/*
1482	 * If we haven't added anything, then we're done.
1483	 */
1484	if (!added_something)
1485		goto cleanup;
1486
1487	/*
1488	 * We may have added our rdatasets to an existing name, if so, then
1489	 * need_addname will be ISC_FALSE.  Whether we used an existing name
1490	 * or a new one, we must set fname to NULL to prevent cleanup.
1491	 */
1492	if (need_addname)
1493		dns_message_addname(client->message, fname,
1494				    DNS_SECTION_ADDITIONAL);
1495	fname = NULL;
1496
1497	/*
1498	 * In a few cases, we want to add additional data for additional
1499	 * data.  It's simpler to just deal with special cases here than
1500	 * to try to create a general purpose mechanism and allow the
1501	 * rdata implementations to do it themselves.
1502	 *
1503	 * This involves recursion, but the depth is limited.  The
1504	 * most complex case is adding a SRV rdataset, which involves
1505	 * recursing to add address records, which in turn can cause
1506	 * recursion to add KEYs.
1507	 */
1508	if (type == dns_rdatatype_srv && trdataset != NULL) {
1509		/*
1510		 * If we're adding SRV records to the additional data
1511		 * section, it's helpful if we add the SRV additional data
1512		 * as well.
1513		 */
1514		eresult = dns_rdataset_additionaldata(trdataset,
1515						      query_addadditional,
1516						      client);
1517	}
1518
1519 cleanup:
1520	CTRACE("query_addadditional: cleanup");
1521	query_putrdataset(client, &rdataset);
1522	if (sigrdataset != NULL)
1523		query_putrdataset(client, &sigrdataset);
1524	if (fname != NULL)
1525		query_releasename(client, &fname);
1526	if (node != NULL)
1527		dns_db_detachnode(db, &node);
1528	if (db != NULL)
1529		dns_db_detach(&db);
1530	if (zone != NULL)
1531		dns_zone_detach(&zone);
1532
1533	CTRACE("query_addadditional: done");
1534	return (eresult);
1535}
1536
1537static inline void
1538query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base,
1539		   dns_rdatasetadditional_t additionaltype,
1540		   dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp,
1541		   dns_dbversion_t **versionp, dns_dbnode_t **nodep,
1542		   dns_name_t *fname)
1543{
1544	dns_rdataset_t *rdataset;
1545
1546	while  ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) {
1547		ISC_LIST_UNLINK(fname->list, rdataset, link);
1548		query_putrdataset(client, &rdataset);
1549	}
1550	if (*versionp != NULL)
1551		dns_db_closeversion(*dbp, versionp, ISC_FALSE);
1552	if (*nodep != NULL)
1553		dns_db_detachnode(*dbp, nodep);
1554	if (*dbp != NULL)
1555		dns_db_detach(dbp);
1556	if (*zonep != NULL)
1557		dns_zone_detach(zonep);
1558	(void)dns_rdataset_putadditional(client->view->acache, rdataset_base,
1559					 additionaltype, type);
1560}
1561
1562static inline isc_result_t
1563query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0,
1564		   dns_dbversion_t *version)
1565{
1566	isc_result_t result = ISC_R_SUCCESS;
1567	dns_dbversion_t *version_current = NULL;
1568	dns_db_t *db_current = db0;
1569
1570	if (db_current == NULL) {
1571		result = dns_zone_getdb(zone, &db_current);
1572		if (result != ISC_R_SUCCESS)
1573			return (result);
1574	}
1575	dns_db_currentversion(db_current, &version_current);
1576	if (db_current != db || version_current != version) {
1577		result = ISC_R_FAILURE;
1578		goto cleanup;
1579	}
1580
1581 cleanup:
1582	dns_db_closeversion(db_current, &version_current, ISC_FALSE);
1583	if (db0 == NULL && db_current != NULL)
1584		dns_db_detach(&db_current);
1585
1586	return (result);
1587}
1588
1589static isc_result_t
1590query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
1591	client_additionalctx_t *additionalctx = arg;
1592	dns_rdataset_t *rdataset_base;
1593	ns_client_t *client;
1594	isc_result_t result, eresult;
1595	dns_dbnode_t *node, *cnode;
1596	dns_db_t *db, *cdb;
1597	dns_name_t *fname, *mname0, cfname;
1598	dns_rdataset_t *rdataset, *sigrdataset;
1599	dns_rdataset_t *crdataset, *crdataset_next;
1600	isc_buffer_t *dbuf;
1601	isc_buffer_t b;
1602	dns_dbversion_t *version, *cversion;
1603	isc_boolean_t added_something, need_addname, needadditionalcache;
1604	isc_boolean_t need_sigrrset;
1605	dns_zone_t *zone;
1606	dns_rdatatype_t type;
1607	dns_rdatasetadditional_t additionaltype;
1608	dns_clientinfomethods_t cm;
1609	dns_clientinfo_t ci;
1610
1611	/*
1612	 * If we don't have an additional cache call query_addadditional.
1613	 */
1614	client = additionalctx->client;
1615	REQUIRE(NS_CLIENT_VALID(client));
1616
1617	if (qtype != dns_rdatatype_a || client->view->acache == NULL) {
1618		/*
1619		 * This function is optimized for "address" types.  For other
1620		 * types, use a generic routine.
1621		 * XXX: ideally, this function should be generic enough.
1622		 */
1623		return (query_addadditional(additionalctx->client,
1624					    name, qtype));
1625	}
1626
1627	/*
1628	 * Initialization.
1629	 */
1630	rdataset_base = additionalctx->rdataset;
1631	eresult = ISC_R_SUCCESS;
1632	fname = NULL;
1633	rdataset = NULL;
1634	sigrdataset = NULL;
1635	db = NULL;
1636	cdb = NULL;
1637	version = NULL;
1638	cversion = NULL;
1639	node = NULL;
1640	cnode = NULL;
1641	added_something = ISC_FALSE;
1642	need_addname = ISC_FALSE;
1643	zone = NULL;
1644	needadditionalcache = ISC_FALSE;
1645	POST(needadditionalcache);
1646	additionaltype = dns_rdatasetadditional_fromauth;
1647	dns_name_init(&cfname, NULL);
1648	dns_clientinfomethods_init(&cm, ns_client_sourceip);
1649	dns_clientinfo_init(&ci, client);
1650
1651	CTRACE("query_addadditional2");
1652
1653	/*
1654	 * We treat type A additional section processing as if it
1655	 * were "any address type" additional section processing.
1656	 * To avoid multiple lookups, we do an 'any' database
1657	 * lookup and iterate over the node.
1658	 * XXXJT: this approach can cause a suboptimal result when the cache
1659	 * DB only has partial address types and the glue DB has remaining
1660	 * ones.
1661	 */
1662	type = dns_rdatatype_any;
1663
1664	/*
1665	 * Get some resources.
1666	 */
1667	dbuf = query_getnamebuf(client);
1668	if (dbuf == NULL)
1669		goto cleanup;
1670	fname = query_newname(client, dbuf, &b);
1671	if (fname == NULL)
1672		goto cleanup;
1673	dns_name_setbuffer(&cfname, &b); /* share the buffer */
1674
1675	/* Check additional cache */
1676	result = dns_rdataset_getadditional(rdataset_base, additionaltype,
1677					    type, client->view->acache, &zone,
1678					    &cdb, &cversion, &cnode, &cfname,
1679					    client->message, client->now);
1680	if (result != ISC_R_SUCCESS)
1681		goto findauthdb;
1682	if (zone == NULL) {
1683		CTRACE("query_addadditional2: auth zone not found");
1684		goto try_cache;
1685	}
1686
1687	/* Is the cached DB up-to-date? */
1688	result = query_iscachevalid(zone, cdb, NULL, cversion);
1689	if (result != ISC_R_SUCCESS) {
1690		CTRACE("query_addadditional2: old auth additional cache");
1691		query_discardcache(client, rdataset_base, additionaltype,
1692				   type, &zone, &cdb, &cversion, &cnode,
1693				   &cfname);
1694		goto findauthdb;
1695	}
1696
1697	if (cnode == NULL) {
1698		/*
1699		 * We have a negative cache.  We don't have to check the zone
1700		 * ACL, since the result (not using this zone) would be same
1701		 * regardless of the result.
1702		 */
1703		CTRACE("query_addadditional2: negative auth additional cache");
1704		dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1705		dns_db_detach(&cdb);
1706		dns_zone_detach(&zone);
1707		goto try_cache;
1708	}
1709
1710	result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG,
1711				      zone, cdb, NULL);
1712	if (result != ISC_R_SUCCESS) {
1713		query_discardcache(client, rdataset_base, additionaltype,
1714				   type, &zone, &cdb, &cversion, &cnode,
1715				   &cfname);
1716		goto try_cache;
1717	}
1718
1719	/* We've got an active cache. */
1720	CTRACE("query_addadditional2: auth additional cache");
1721	dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1722	db = cdb;
1723	node = cnode;
1724	dns_name_clone(&cfname, fname);
1725	query_keepname(client, fname, dbuf);
1726	goto foundcache;
1727
1728	/*
1729	 * Look for a zone database that might contain authoritative
1730	 * additional data.
1731	 */
1732 findauthdb:
1733	result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
1734				 &zone, &db, &version);
1735	if (result != ISC_R_SUCCESS) {
1736		/* Cache the negative result */
1737		(void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1738						 type, client->view->acache,
1739						 NULL, NULL, NULL, NULL,
1740						 NULL);
1741		goto try_cache;
1742	}
1743
1744	CTRACE("query_addadditional2: db_find");
1745
1746	/*
1747	 * Since we are looking for authoritative data, we do not set
1748	 * the GLUEOK flag.  Glue will be looked for later, but not
1749	 * necessarily in the same database.
1750	 */
1751	node = NULL;
1752	result = dns_db_findext(db, name, version, type,
1753				client->query.dboptions,
1754				client->now, &node, fname, &cm, &ci,
1755				NULL, NULL);
1756	if (result == ISC_R_SUCCESS)
1757		goto found;
1758
1759	/* Cache the negative result */
1760	(void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1761					 type, client->view->acache, zone, db,
1762					 version, NULL, fname);
1763
1764	if (node != NULL)
1765		dns_db_detachnode(db, &node);
1766	version = NULL;
1767	dns_db_detach(&db);
1768
1769	/*
1770	 * No authoritative data was found.  The cache is our next best bet.
1771	 */
1772
1773 try_cache:
1774	additionaltype = dns_rdatasetadditional_fromcache;
1775	result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
1776	if (result != ISC_R_SUCCESS)
1777		/*
1778		 * Most likely the client isn't allowed to query the cache.
1779		 */
1780		goto try_glue;
1781
1782	result = dns_db_findext(db, name, version, type,
1783				client->query.dboptions |
1784				 DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
1785				client->now, &node, fname, &cm, &ci,
1786				NULL, NULL);
1787	if (result == ISC_R_SUCCESS)
1788		goto found;
1789
1790	if (node != NULL)
1791		dns_db_detachnode(db, &node);
1792	dns_db_detach(&db);
1793
1794 try_glue:
1795	/*
1796	 * No cached data was found.  Glue is our last chance.
1797	 * RFC1035 sayeth:
1798	 *
1799	 *	NS records cause both the usual additional section
1800	 *	processing to locate a type A record, and, when used
1801	 *	in a referral, a special search of the zone in which
1802	 *	they reside for glue information.
1803	 *
1804	 * This is the "special search".  Note that we must search
1805	 * the zone where the NS record resides, not the zone it
1806	 * points to, and that we only do the search in the delegation
1807	 * case (identified by client->query.gluedb being set).
1808	 */
1809	if (client->query.gluedb == NULL)
1810		goto cleanup;
1811
1812	/*
1813	 * Don't poison caches using the bailiwick protection model.
1814	 */
1815	if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
1816		goto cleanup;
1817
1818	/* Check additional cache */
1819	additionaltype = dns_rdatasetadditional_fromglue;
1820	result = dns_rdataset_getadditional(rdataset_base, additionaltype,
1821					    type, client->view->acache, NULL,
1822					    &cdb, &cversion, &cnode, &cfname,
1823					    client->message, client->now);
1824	if (result != ISC_R_SUCCESS)
1825		goto findglue;
1826
1827	result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion);
1828	if (result != ISC_R_SUCCESS) {
1829		CTRACE("query_addadditional2: old glue additional cache");
1830		query_discardcache(client, rdataset_base, additionaltype,
1831				   type, &zone, &cdb, &cversion, &cnode,
1832				   &cfname);
1833		goto findglue;
1834	}
1835
1836	if (cnode == NULL) {
1837		/* We have a negative cache. */
1838		CTRACE("query_addadditional2: negative glue additional cache");
1839		dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1840		dns_db_detach(&cdb);
1841		goto cleanup;
1842	}
1843
1844	/* Cache hit. */
1845	CTRACE("query_addadditional2: glue additional cache");
1846	dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1847	db = cdb;
1848	node = cnode;
1849	dns_name_clone(&cfname, fname);
1850	query_keepname(client, fname, dbuf);
1851	goto foundcache;
1852
1853 findglue:
1854	dns_db_attach(client->query.gluedb, &db);
1855	result = dns_db_findext(db, name, version, type,
1856				client->query.dboptions | DNS_DBFIND_GLUEOK,
1857				client->now, &node, fname, &cm, &ci,
1858				NULL, NULL);
1859	if (!(result == ISC_R_SUCCESS ||
1860	      result == DNS_R_ZONECUT ||
1861	      result == DNS_R_GLUE)) {
1862		/* cache the negative result */
1863		(void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1864						 type, client->view->acache,
1865						 NULL, db, version, NULL,
1866						 fname);
1867		goto cleanup;
1868	}
1869
1870 found:
1871	/*
1872	 * We have found a DB node to iterate over from a DB.
1873	 * We are going to look for address RRsets (i.e., A and AAAA) in the DB
1874	 * node we've just found.  We'll then store the complete information
1875	 * in the additional data cache.
1876	 */
1877	dns_name_clone(fname, &cfname);
1878	query_keepname(client, fname, dbuf);
1879	needadditionalcache = ISC_TRUE;
1880
1881	rdataset = query_newrdataset(client);
1882	if (rdataset == NULL)
1883		goto cleanup;
1884
1885	sigrdataset = query_newrdataset(client);
1886	if (sigrdataset == NULL)
1887		goto cleanup;
1888
1889	if (additionaltype == dns_rdatasetadditional_fromcache &&
1890	    query_isduplicate(client, fname, dns_rdatatype_a, NULL))
1891		goto aaaa_lookup;
1892	/*
1893	 * Find A RRset with sig RRset.  Even if we don't find a sig RRset
1894	 * for a client using DNSSEC, we'll continue the process to make a
1895	 * complete list to be cached.  However, we need to cancel the
1896	 * caching when something unexpected happens, in order to avoid
1897	 * caching incomplete information.
1898	 */
1899	result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0,
1900				     client->now, rdataset, sigrdataset);
1901	/*
1902	 * If we can't promote glue/pending from the cache to secure
1903	 * then drop it.
1904	 */
1905	if (result == ISC_R_SUCCESS &&
1906	    additionaltype == dns_rdatasetadditional_fromcache &&
1907	    (DNS_TRUST_PENDING(rdataset->trust) ||
1908	     DNS_TRUST_GLUE(rdataset->trust)) &&
1909	    !validate(client, db, fname, rdataset, sigrdataset)) {
1910		dns_rdataset_disassociate(rdataset);
1911		if (dns_rdataset_isassociated(sigrdataset))
1912			dns_rdataset_disassociate(sigrdataset);
1913		result = ISC_R_NOTFOUND;
1914	}
1915	if (result == DNS_R_NCACHENXDOMAIN)
1916		goto setcache;
1917	if (result == DNS_R_NCACHENXRRSET) {
1918		dns_rdataset_disassociate(rdataset);
1919		if (dns_rdataset_isassociated(sigrdataset))
1920			dns_rdataset_disassociate(sigrdataset);
1921	}
1922	if (result == ISC_R_SUCCESS) {
1923		/* Remember the result as a cache */
1924		ISC_LIST_APPEND(cfname.list, rdataset, link);
1925		if (dns_rdataset_isassociated(sigrdataset)) {
1926			ISC_LIST_APPEND(cfname.list, sigrdataset, link);
1927			sigrdataset = query_newrdataset(client);
1928		}
1929		rdataset = query_newrdataset(client);
1930		if (sigrdataset == NULL || rdataset == NULL) {
1931			/* do not cache incomplete information */
1932			goto foundcache;
1933		}
1934	}
1935
1936 aaaa_lookup:
1937	if (additionaltype == dns_rdatasetadditional_fromcache &&
1938	    query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
1939		goto foundcache;
1940	/* Find AAAA RRset with sig RRset */
1941	result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa,
1942				     0, client->now, rdataset, sigrdataset);
1943	/*
1944	 * If we can't promote glue/pending from the cache to secure
1945	 * then drop it.
1946	 */
1947	if (result == ISC_R_SUCCESS &&
1948	    additionaltype == dns_rdatasetadditional_fromcache &&
1949	    (DNS_TRUST_PENDING(rdataset->trust) ||
1950	     DNS_TRUST_GLUE(rdataset->trust)) &&
1951	    !validate(client, db, fname, rdataset, sigrdataset)) {
1952		dns_rdataset_disassociate(rdataset);
1953		if (dns_rdataset_isassociated(sigrdataset))
1954			dns_rdataset_disassociate(sigrdataset);
1955		result = ISC_R_NOTFOUND;
1956	}
1957	if (result == ISC_R_SUCCESS) {
1958		ISC_LIST_APPEND(cfname.list, rdataset, link);
1959		rdataset = NULL;
1960		if (dns_rdataset_isassociated(sigrdataset)) {
1961			ISC_LIST_APPEND(cfname.list, sigrdataset, link);
1962			sigrdataset = NULL;
1963		}
1964	}
1965
1966 setcache:
1967	/*
1968	 * Set the new result in the cache if required.  We do not support
1969	 * caching additional data from a cache DB.
1970	 */
1971	if (needadditionalcache == ISC_TRUE &&
1972	    (additionaltype == dns_rdatasetadditional_fromauth ||
1973	     additionaltype == dns_rdatasetadditional_fromglue)) {
1974		(void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1975						 type, client->view->acache,
1976						 zone, db, version, node,
1977						 &cfname);
1978	}
1979
1980 foundcache:
1981	need_sigrrset = ISC_FALSE;
1982	mname0 = NULL;
1983	for (crdataset = ISC_LIST_HEAD(cfname.list);
1984	     crdataset != NULL;
1985	     crdataset = crdataset_next) {
1986		dns_name_t *mname;
1987
1988		crdataset_next = ISC_LIST_NEXT(crdataset, link);
1989
1990		mname = NULL;
1991		if (crdataset->type == dns_rdatatype_a ||
1992		    crdataset->type == dns_rdatatype_aaaa) {
1993			if (!query_isduplicate(client, fname, crdataset->type,
1994					       &mname)) {
1995				if (mname != fname) {
1996					if (mname != NULL) {
1997						/*
1998						 * A different type of this name is
1999						 * already stored in the additional
2000						 * section.  We'll reuse the name.
2001						 * Note that this should happen at most
2002						 * once.  Otherwise, fname->link could
2003						 * leak below.
2004						 */
2005						INSIST(mname0 == NULL);
2006
2007						query_releasename(client, &fname);
2008						fname = mname;
2009						mname0 = mname;
2010					} else
2011						need_addname = ISC_TRUE;
2012				}
2013				ISC_LIST_UNLINK(cfname.list, crdataset, link);
2014				ISC_LIST_APPEND(fname->list, crdataset, link);
2015				added_something = ISC_TRUE;
2016				need_sigrrset = ISC_TRUE;
2017			} else
2018				need_sigrrset = ISC_FALSE;
2019		} else if (crdataset->type == dns_rdatatype_rrsig &&
2020			   need_sigrrset && WANTDNSSEC(client)) {
2021			ISC_LIST_UNLINK(cfname.list, crdataset, link);
2022			ISC_LIST_APPEND(fname->list, crdataset, link);
2023			added_something = ISC_TRUE; /* just in case */
2024			need_sigrrset = ISC_FALSE;
2025		}
2026	}
2027
2028	CTRACE("query_addadditional2: addname");
2029
2030	/*
2031	 * If we haven't added anything, then we're done.
2032	 */
2033	if (!added_something)
2034		goto cleanup;
2035
2036	/*
2037	 * We may have added our rdatasets to an existing name, if so, then
2038	 * need_addname will be ISC_FALSE.  Whether we used an existing name
2039	 * or a new one, we must set fname to NULL to prevent cleanup.
2040	 */
2041	if (need_addname)
2042		dns_message_addname(client->message, fname,
2043				    DNS_SECTION_ADDITIONAL);
2044	fname = NULL;
2045
2046 cleanup:
2047	CTRACE("query_addadditional2: cleanup");
2048
2049	if (rdataset != NULL)
2050		query_putrdataset(client, &rdataset);
2051	if (sigrdataset != NULL)
2052		query_putrdataset(client, &sigrdataset);
2053	while  ((crdataset = ISC_LIST_HEAD(cfname.list)) != NULL) {
2054		ISC_LIST_UNLINK(cfname.list, crdataset, link);
2055		query_putrdataset(client, &crdataset);
2056	}
2057	if (fname != NULL)
2058		query_releasename(client, &fname);
2059	if (node != NULL)
2060		dns_db_detachnode(db, &node);
2061	if (db != NULL)
2062		dns_db_detach(&db);
2063	if (zone != NULL)
2064		dns_zone_detach(&zone);
2065
2066	CTRACE("query_addadditional2: done");
2067	return (eresult);
2068}
2069
2070static inline void
2071query_addrdataset(ns_client_t *client, dns_name_t *fname,
2072		  dns_rdataset_t *rdataset)
2073{
2074	client_additionalctx_t additionalctx;
2075
2076	/*
2077	 * Add 'rdataset' and any pertinent additional data to
2078	 * 'fname', a name in the response message for 'client'.
2079	 */
2080
2081	CTRACE("query_addrdataset");
2082
2083	ISC_LIST_APPEND(fname->list, rdataset, link);
2084
2085	if (client->view->order != NULL)
2086		rdataset->attributes |= dns_order_find(client->view->order,
2087						       fname, rdataset->type,
2088						       rdataset->rdclass);
2089	rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
2090
2091	if (NOADDITIONAL(client))
2092		return;
2093
2094	/*
2095	 * Add additional data.
2096	 *
2097	 * We don't care if dns_rdataset_additionaldata() fails.
2098	 */
2099	additionalctx.client = client;
2100	additionalctx.rdataset = rdataset;
2101	(void)dns_rdataset_additionaldata(rdataset, query_addadditional2,
2102					  &additionalctx);
2103	CTRACE("query_addrdataset: done");
2104}
2105
2106static isc_result_t
2107query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
2108	    dns_rdataset_t *sigrdataset, isc_buffer_t *dbuf,
2109	    dns_section_t section)
2110{
2111	dns_name_t *name, *mname;
2112	dns_rdata_t *dns64_rdata;
2113	dns_rdata_t rdata = DNS_RDATA_INIT;
2114	dns_rdatalist_t *dns64_rdatalist;
2115	dns_rdataset_t *dns64_rdataset;
2116	dns_rdataset_t *mrdataset;
2117	isc_buffer_t *buffer;
2118	isc_region_t r;
2119	isc_result_t result;
2120	dns_view_t *view = client->view;
2121	isc_netaddr_t netaddr;
2122	dns_dns64_t *dns64;
2123	unsigned int flags = 0;
2124
2125	/*%
2126	 * To the current response for 'client', add the answer RRset
2127	 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
2128	 * owner name '*namep', to section 'section', unless they are
2129	 * already there.  Also add any pertinent additional data.
2130	 *
2131	 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
2132	 * stored in 'dbuf'.  In this case, query_addrrset() guarantees that
2133	 * when it returns the name will either have been kept or released.
2134	 */
2135	CTRACE("query_dns64");
2136	name = *namep;
2137	mname = NULL;
2138	mrdataset = NULL;
2139	buffer = NULL;
2140	dns64_rdata = NULL;
2141	dns64_rdataset = NULL;
2142	dns64_rdatalist = NULL;
2143	result = dns_message_findname(client->message, section,
2144				      name, dns_rdatatype_aaaa,
2145				      rdataset->covers,
2146				      &mname, &mrdataset);
2147	if (result == ISC_R_SUCCESS) {
2148		/*
2149		 * We've already got an RRset of the given name and type.
2150		 * There's nothing else to do;
2151		 */
2152		CTRACE("query_dns64: dns_message_findname succeeded: done");
2153		if (dbuf != NULL)
2154			query_releasename(client, namep);
2155		return (ISC_R_SUCCESS);
2156	} else if (result == DNS_R_NXDOMAIN) {
2157		/*
2158		 * The name doesn't exist.
2159		 */
2160		if (dbuf != NULL)
2161			query_keepname(client, name, dbuf);
2162		dns_message_addname(client->message, name, section);
2163		*namep = NULL;
2164		mname = name;
2165	} else {
2166		RUNTIME_CHECK(result == DNS_R_NXRRSET);
2167		if (dbuf != NULL)
2168			query_releasename(client, namep);
2169	}
2170
2171	if (rdataset->trust != dns_trust_secure &&
2172	    (section == DNS_SECTION_ANSWER ||
2173	     section == DNS_SECTION_AUTHORITY))
2174		client->query.attributes &= ~NS_QUERYATTR_SECURE;
2175
2176	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2177
2178	result = isc_buffer_allocate(client->mctx, &buffer, view->dns64cnt *
2179				     16 * dns_rdataset_count(rdataset));
2180	if (result != ISC_R_SUCCESS)
2181		goto cleanup;
2182	result = dns_message_gettemprdataset(client->message, &dns64_rdataset);
2183	if (result != ISC_R_SUCCESS)
2184		goto cleanup;
2185	result = dns_message_gettemprdatalist(client->message,
2186					      &dns64_rdatalist);
2187	if (result != ISC_R_SUCCESS)
2188		goto cleanup;
2189
2190	dns_rdataset_init(dns64_rdataset);
2191	dns_rdatalist_init(dns64_rdatalist);
2192	dns64_rdatalist->rdclass = dns_rdataclass_in;
2193	dns64_rdatalist->type = dns_rdatatype_aaaa;
2194	if (client->query.dns64_ttl != ISC_UINT32_MAX)
2195		dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl,
2196					       client->query.dns64_ttl);
2197	else
2198		dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, 600);
2199
2200	if (RECURSIONOK(client))
2201		flags |= DNS_DNS64_RECURSIVE;
2202
2203	/*
2204	 * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC
2205	 * as this provides a easy way to see if the answer was signed.
2206	 */
2207	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
2208		flags |= DNS_DNS64_DNSSEC;
2209
2210	for (result = dns_rdataset_first(rdataset);
2211	     result == ISC_R_SUCCESS;
2212	     result = dns_rdataset_next(rdataset)) {
2213		for (dns64 = ISC_LIST_HEAD(client->view->dns64);
2214		     dns64 != NULL; dns64 = dns_dns64_next(dns64)) {
2215
2216			dns_rdataset_current(rdataset, &rdata);
2217			isc__buffer_availableregion(buffer, &r);
2218			INSIST(r.length >= 16);
2219			result = dns_dns64_aaaafroma(dns64, &netaddr,
2220						     client->signer,
2221						     &ns_g_server->aclenv,
2222						     flags, rdata.data, r.base);
2223			if (result != ISC_R_SUCCESS) {
2224				dns_rdata_reset(&rdata);
2225				continue;
2226			}
2227			isc_buffer_add(buffer, 16);
2228			isc_buffer_remainingregion(buffer, &r);
2229			isc_buffer_forward(buffer, 16);
2230			result = dns_message_gettemprdata(client->message,
2231							  &dns64_rdata);
2232			if (result != ISC_R_SUCCESS)
2233				goto cleanup;
2234			dns_rdata_init(dns64_rdata);
2235			dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in,
2236					     dns_rdatatype_aaaa, &r);
2237			ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata,
2238					link);
2239			dns64_rdata = NULL;
2240			dns_rdata_reset(&rdata);
2241		}
2242	}
2243	if (result != ISC_R_NOMORE)
2244		goto cleanup;
2245
2246	if (ISC_LIST_EMPTY(dns64_rdatalist->rdata))
2247		goto cleanup;
2248
2249	result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset);
2250	if (result != ISC_R_SUCCESS)
2251		goto cleanup;
2252	client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
2253	dns64_rdataset->trust = rdataset->trust;
2254	query_addrdataset(client, mname, dns64_rdataset);
2255	dns64_rdataset = NULL;
2256	dns64_rdatalist = NULL;
2257	dns_message_takebuffer(client->message, &buffer);
2258	result = ISC_R_SUCCESS;
2259
2260 cleanup:
2261	if (buffer != NULL)
2262		isc_buffer_free(&buffer);
2263
2264	if (dns64_rdata != NULL)
2265		dns_message_puttemprdata(client->message, &dns64_rdata);
2266
2267	if (dns64_rdataset != NULL)
2268		dns_message_puttemprdataset(client->message, &dns64_rdataset);
2269
2270	if (dns64_rdatalist != NULL) {
2271		for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata);
2272		     dns64_rdata != NULL;
2273		     dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata))
2274		{
2275			ISC_LIST_UNLINK(dns64_rdatalist->rdata,
2276					dns64_rdata, link);
2277			dns_message_puttemprdata(client->message, &dns64_rdata);
2278		}
2279		dns_message_puttemprdatalist(client->message, &dns64_rdatalist);
2280	}
2281
2282	CTRACE("query_dns64: done");
2283	return (result);
2284}
2285
2286static void
2287query_filter64(ns_client_t *client, dns_name_t **namep,
2288	       dns_rdataset_t *rdataset, isc_buffer_t *dbuf,
2289	       dns_section_t section)
2290{
2291	dns_name_t *name, *mname;
2292	dns_rdata_t *myrdata;
2293	dns_rdata_t rdata = DNS_RDATA_INIT;
2294	dns_rdatalist_t *myrdatalist;
2295	dns_rdataset_t *myrdataset;
2296	isc_buffer_t *buffer;
2297	isc_region_t r;
2298	isc_result_t result;
2299	unsigned int i;
2300
2301	CTRACE("query_filter64");
2302
2303	INSIST(client->query.dns64_aaaaok != NULL);
2304	INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset));
2305
2306	name = *namep;
2307	mname = NULL;
2308	buffer = NULL;
2309	myrdata = NULL;
2310	myrdataset = NULL;
2311	myrdatalist = NULL;
2312	result = dns_message_findname(client->message, section,
2313				      name, dns_rdatatype_aaaa,
2314				      rdataset->covers,
2315				      &mname, &myrdataset);
2316	if (result == ISC_R_SUCCESS) {
2317		/*
2318		 * We've already got an RRset of the given name and type.
2319		 * There's nothing else to do;
2320		 */
2321		CTRACE("query_filter64: dns_message_findname succeeded: done");
2322		if (dbuf != NULL)
2323			query_releasename(client, namep);
2324		return;
2325	} else if (result == DNS_R_NXDOMAIN) {
2326		mname = name;
2327		*namep = NULL;
2328	} else {
2329		RUNTIME_CHECK(result == DNS_R_NXRRSET);
2330		if (dbuf != NULL)
2331			query_releasename(client, namep);
2332		dbuf = NULL;
2333	}
2334
2335	if (rdataset->trust != dns_trust_secure &&
2336	    (section == DNS_SECTION_ANSWER ||
2337	     section == DNS_SECTION_AUTHORITY))
2338		client->query.attributes &= ~NS_QUERYATTR_SECURE;
2339
2340	result = isc_buffer_allocate(client->mctx, &buffer,
2341				     16 * dns_rdataset_count(rdataset));
2342	if (result != ISC_R_SUCCESS)
2343		goto cleanup;
2344	result = dns_message_gettemprdataset(client->message, &myrdataset);
2345	if (result != ISC_R_SUCCESS)
2346		goto cleanup;
2347	result = dns_message_gettemprdatalist(client->message, &myrdatalist);
2348	if (result != ISC_R_SUCCESS)
2349		goto cleanup;
2350
2351	dns_rdataset_init(myrdataset);
2352	dns_rdatalist_init(myrdatalist);
2353	myrdatalist->rdclass = dns_rdataclass_in;
2354	myrdatalist->type = dns_rdatatype_aaaa;
2355	myrdatalist->ttl = rdataset->ttl;
2356
2357	i = 0;
2358	for (result = dns_rdataset_first(rdataset);
2359	     result == ISC_R_SUCCESS;
2360	     result = dns_rdataset_next(rdataset)) {
2361		if (!client->query.dns64_aaaaok[i++])
2362			continue;
2363		dns_rdataset_current(rdataset, &rdata);
2364		INSIST(rdata.length == 16);
2365		isc_buffer_putmem(buffer, rdata.data, rdata.length);
2366		isc_buffer_remainingregion(buffer, &r);
2367		isc_buffer_forward(buffer, rdata.length);
2368		result = dns_message_gettemprdata(client->message, &myrdata);
2369		if (result != ISC_R_SUCCESS)
2370			goto cleanup;
2371		dns_rdata_init(myrdata);
2372		dns_rdata_fromregion(myrdata, dns_rdataclass_in,
2373				     dns_rdatatype_aaaa, &r);
2374		ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link);
2375		myrdata = NULL;
2376		dns_rdata_reset(&rdata);
2377	}
2378	if (result != ISC_R_NOMORE)
2379		goto cleanup;
2380
2381	result = dns_rdatalist_tordataset(myrdatalist, myrdataset);
2382	if (result != ISC_R_SUCCESS)
2383		goto cleanup;
2384	client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
2385	if (mname == name) {
2386		if (dbuf != NULL)
2387			query_keepname(client, name, dbuf);
2388		dns_message_addname(client->message, name, section);
2389		dbuf = NULL;
2390	}
2391	myrdataset->trust = rdataset->trust;
2392	query_addrdataset(client, mname, myrdataset);
2393	myrdataset = NULL;
2394	myrdatalist = NULL;
2395	dns_message_takebuffer(client->message, &buffer);
2396
2397 cleanup:
2398	if (buffer != NULL)
2399		isc_buffer_free(&buffer);
2400
2401	if (myrdata != NULL)
2402		dns_message_puttemprdata(client->message, &myrdata);
2403
2404	if (myrdataset != NULL)
2405		dns_message_puttemprdataset(client->message, &myrdataset);
2406
2407	if (myrdatalist != NULL) {
2408		for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata);
2409		     myrdata != NULL;
2410		     myrdata = ISC_LIST_HEAD(myrdatalist->rdata))
2411		{
2412			ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link);
2413			dns_message_puttemprdata(client->message, &myrdata);
2414		}
2415		dns_message_puttemprdatalist(client->message, &myrdatalist);
2416	}
2417	if (dbuf != NULL)
2418		query_releasename(client, &name);
2419
2420	CTRACE("query_filter64: done");
2421}
2422
2423static void
2424query_addrrset(ns_client_t *client, dns_name_t **namep,
2425	       dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
2426	       isc_buffer_t *dbuf, dns_section_t section)
2427{
2428	dns_name_t *name, *mname;
2429	dns_rdataset_t *rdataset, *mrdataset, *sigrdataset;
2430	isc_result_t result;
2431
2432	/*%
2433	 * To the current response for 'client', add the answer RRset
2434	 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
2435	 * owner name '*namep', to section 'section', unless they are
2436	 * already there.  Also add any pertinent additional data.
2437	 *
2438	 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
2439	 * stored in 'dbuf'.  In this case, query_addrrset() guarantees that
2440	 * when it returns the name will either have been kept or released.
2441	 */
2442	CTRACE("query_addrrset");
2443	name = *namep;
2444	rdataset = *rdatasetp;
2445	if (sigrdatasetp != NULL)
2446		sigrdataset = *sigrdatasetp;
2447	else
2448		sigrdataset = NULL;
2449	mname = NULL;
2450	mrdataset = NULL;
2451	result = dns_message_findname(client->message, section,
2452				      name, rdataset->type, rdataset->covers,
2453				      &mname, &mrdataset);
2454	if (result == ISC_R_SUCCESS) {
2455		/*
2456		 * We've already got an RRset of the given name and type.
2457		 * There's nothing else to do;
2458		 */
2459		CTRACE("query_addrrset: dns_message_findname succeeded: done");
2460		if (dbuf != NULL)
2461			query_releasename(client, namep);
2462		return;
2463	} else if (result == DNS_R_NXDOMAIN) {
2464		/*
2465		 * The name doesn't exist.
2466		 */
2467		if (dbuf != NULL)
2468			query_keepname(client, name, dbuf);
2469		dns_message_addname(client->message, name, section);
2470		*namep = NULL;
2471		mname = name;
2472	} else {
2473		RUNTIME_CHECK(result == DNS_R_NXRRSET);
2474		if (dbuf != NULL)
2475			query_releasename(client, namep);
2476	}
2477
2478	if (rdataset->trust != dns_trust_secure &&
2479	    (section == DNS_SECTION_ANSWER ||
2480	     section == DNS_SECTION_AUTHORITY))
2481		client->query.attributes &= ~NS_QUERYATTR_SECURE;
2482	/*
2483	 * Note: we only add SIGs if we've added the type they cover, so
2484	 * we do not need to check if the SIG rdataset is already in the
2485	 * response.
2486	 */
2487	query_addrdataset(client, mname, rdataset);
2488	*rdatasetp = NULL;
2489	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
2490		/*
2491		 * We have a signature.  Add it to the response.
2492		 */
2493		ISC_LIST_APPEND(mname->list, sigrdataset, link);
2494		*sigrdatasetp = NULL;
2495	}
2496	CTRACE("query_addrrset: done");
2497}
2498
2499static inline isc_result_t
2500query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
2501	     unsigned int override_ttl, isc_boolean_t isassociated)
2502{
2503	dns_name_t *name;
2504	dns_dbnode_t *node;
2505	isc_result_t result, eresult;
2506	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2507	dns_rdataset_t **sigrdatasetp = NULL;
2508	dns_clientinfomethods_t cm;
2509	dns_clientinfo_t ci;
2510
2511	CTRACE("query_addsoa");
2512	/*
2513	 * Initialization.
2514	 */
2515	eresult = ISC_R_SUCCESS;
2516	name = NULL;
2517	rdataset = NULL;
2518	node = NULL;
2519
2520	dns_clientinfomethods_init(&cm, ns_client_sourceip);
2521	dns_clientinfo_init(&ci, client);
2522
2523	/*
2524	 * Don't add the SOA record for test which set "-T nosoa".
2525	 */
2526	if (ns_g_nosoa && (!WANTDNSSEC(client) || !isassociated))
2527		return (ISC_R_SUCCESS);
2528
2529	/*
2530	 * Get resources and make 'name' be the database origin.
2531	 */
2532	result = dns_message_gettempname(client->message, &name);
2533	if (result != ISC_R_SUCCESS)
2534		return (result);
2535	dns_name_init(name, NULL);
2536	dns_name_clone(dns_db_origin(db), name);
2537	rdataset = query_newrdataset(client);
2538	if (rdataset == NULL) {
2539		eresult = DNS_R_SERVFAIL;
2540		goto cleanup;
2541	}
2542	if (WANTDNSSEC(client) && dns_db_issecure(db)) {
2543		sigrdataset = query_newrdataset(client);
2544		if (sigrdataset == NULL) {
2545			eresult = DNS_R_SERVFAIL;
2546			goto cleanup;
2547		}
2548	}
2549
2550	/*
2551	 * Find the SOA.
2552	 */
2553	result = dns_db_getoriginnode(db, &node);
2554	if (result == ISC_R_SUCCESS) {
2555		result = dns_db_findrdataset(db, node, version,
2556					     dns_rdatatype_soa, 0, client->now,
2557					     rdataset, sigrdataset);
2558	} else {
2559		dns_fixedname_t foundname;
2560		dns_name_t *fname;
2561
2562		dns_fixedname_init(&foundname);
2563		fname = dns_fixedname_name(&foundname);
2564
2565		result = dns_db_findext(db, name, version, dns_rdatatype_soa,
2566					client->query.dboptions, 0, &node,
2567					fname, &cm, &ci, rdataset, sigrdataset);
2568	}
2569	if (result != ISC_R_SUCCESS) {
2570		/*
2571		 * This is bad.  We tried to get the SOA RR at the zone top
2572		 * and it didn't work!
2573		 */
2574		eresult = DNS_R_SERVFAIL;
2575	} else {
2576		/*
2577		 * Extract the SOA MINIMUM.
2578		 */
2579		dns_rdata_soa_t soa;
2580		dns_rdata_t rdata = DNS_RDATA_INIT;
2581		result = dns_rdataset_first(rdataset);
2582		RUNTIME_CHECK(result == ISC_R_SUCCESS);
2583		dns_rdataset_current(rdataset, &rdata);
2584		result = dns_rdata_tostruct(&rdata, &soa, NULL);
2585		if (result != ISC_R_SUCCESS)
2586			goto cleanup;
2587
2588		if (override_ttl != ISC_UINT32_MAX &&
2589		    override_ttl < rdataset->ttl) {
2590			rdataset->ttl = override_ttl;
2591			if (sigrdataset != NULL)
2592				sigrdataset->ttl = override_ttl;
2593		}
2594
2595		/*
2596		 * Add the SOA and its SIG to the response, with the
2597		 * TTLs adjusted per RFC2308 section 3.
2598		 */
2599		if (rdataset->ttl > soa.minimum)
2600			rdataset->ttl = soa.minimum;
2601		if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum)
2602			sigrdataset->ttl = soa.minimum;
2603
2604		if (sigrdataset != NULL)
2605			sigrdatasetp = &sigrdataset;
2606		else
2607			sigrdatasetp = NULL;
2608		query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
2609			       DNS_SECTION_AUTHORITY);
2610	}
2611
2612 cleanup:
2613	query_putrdataset(client, &rdataset);
2614	if (sigrdataset != NULL)
2615		query_putrdataset(client, &sigrdataset);
2616	if (name != NULL)
2617		query_releasename(client, &name);
2618	if (node != NULL)
2619		dns_db_detachnode(db, &node);
2620
2621	return (eresult);
2622}
2623
2624static inline isc_result_t
2625query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
2626	dns_name_t *name, *fname;
2627	dns_dbnode_t *node;
2628	isc_result_t result, eresult;
2629	dns_fixedname_t foundname;
2630	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2631	dns_rdataset_t **sigrdatasetp = NULL;
2632	dns_clientinfomethods_t cm;
2633	dns_clientinfo_t ci;
2634
2635	CTRACE("query_addns");
2636	/*
2637	 * Initialization.
2638	 */
2639	eresult = ISC_R_SUCCESS;
2640	name = NULL;
2641	rdataset = NULL;
2642	node = NULL;
2643	dns_fixedname_init(&foundname);
2644	fname = dns_fixedname_name(&foundname);
2645	dns_clientinfomethods_init(&cm, ns_client_sourceip);
2646	dns_clientinfo_init(&ci, client);
2647
2648	/*
2649	 * Get resources and make 'name' be the database origin.
2650	 */
2651	result = dns_message_gettempname(client->message, &name);
2652	if (result != ISC_R_SUCCESS) {
2653		CTRACE("query_addns: dns_message_gettempname failed: done");
2654		return (result);
2655	}
2656	dns_name_init(name, NULL);
2657	dns_name_clone(dns_db_origin(db), name);
2658	rdataset = query_newrdataset(client);
2659	if (rdataset == NULL) {
2660		CTRACE("query_addns: query_newrdataset failed");
2661		eresult = DNS_R_SERVFAIL;
2662		goto cleanup;
2663	}
2664	if (WANTDNSSEC(client) && dns_db_issecure(db)) {
2665		sigrdataset = query_newrdataset(client);
2666		if (sigrdataset == NULL) {
2667			CTRACE("query_addns: query_newrdataset failed");
2668			eresult = DNS_R_SERVFAIL;
2669			goto cleanup;
2670		}
2671	}
2672
2673	/*
2674	 * Find the NS rdataset.
2675	 */
2676	result = dns_db_getoriginnode(db, &node);
2677	if (result == ISC_R_SUCCESS) {
2678		result = dns_db_findrdataset(db, node, version,
2679					     dns_rdatatype_ns, 0, client->now,
2680					     rdataset, sigrdataset);
2681	} else {
2682		CTRACE("query_addns: calling dns_db_find");
2683		result = dns_db_findext(db, name, NULL, dns_rdatatype_ns,
2684					client->query.dboptions, 0, &node,
2685					fname, &cm, &ci, rdataset, sigrdataset);
2686		CTRACE("query_addns: dns_db_find complete");
2687	}
2688	if (result != ISC_R_SUCCESS) {
2689		CTRACE("query_addns: "
2690		       "dns_db_findrdataset or dns_db_find failed");
2691		/*
2692		 * This is bad.  We tried to get the NS rdataset at the zone
2693		 * top and it didn't work!
2694		 */
2695		eresult = DNS_R_SERVFAIL;
2696	} else {
2697		if (sigrdataset != NULL)
2698			sigrdatasetp = &sigrdataset;
2699		else
2700			sigrdatasetp = NULL;
2701		query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
2702			       DNS_SECTION_AUTHORITY);
2703	}
2704
2705 cleanup:
2706	CTRACE("query_addns: cleanup");
2707	query_putrdataset(client, &rdataset);
2708	if (sigrdataset != NULL)
2709		query_putrdataset(client, &sigrdataset);
2710	if (name != NULL)
2711		query_releasename(client, &name);
2712	if (node != NULL)
2713		dns_db_detachnode(db, &node);
2714
2715	CTRACE("query_addns: done");
2716	return (eresult);
2717}
2718
2719static isc_result_t
2720query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
2721		dns_trust_t trust, dns_ttl_t ttl)
2722{
2723	dns_rdataset_t *rdataset;
2724	dns_rdatalist_t *rdatalist;
2725	dns_rdata_t *rdata;
2726	isc_region_t r;
2727	dns_name_t *aname;
2728	isc_result_t result;
2729
2730	/*
2731	 * We assume the name data referred to by tname won't go away.
2732	 */
2733
2734	aname = NULL;
2735	result = dns_message_gettempname(client->message, &aname);
2736	if (result != ISC_R_SUCCESS)
2737		return (result);
2738	result = dns_name_dup(qname, client->mctx, aname);
2739	if (result != ISC_R_SUCCESS) {
2740		dns_message_puttempname(client->message, &aname);
2741		return (result);
2742	}
2743
2744	rdatalist = NULL;
2745	result = dns_message_gettemprdatalist(client->message, &rdatalist);
2746	if (result != ISC_R_SUCCESS) {
2747		dns_message_puttempname(client->message, &aname);
2748		return (result);
2749	}
2750	rdata = NULL;
2751	result = dns_message_gettemprdata(client->message, &rdata);
2752	if (result != ISC_R_SUCCESS) {
2753		dns_message_puttempname(client->message, &aname);
2754		dns_message_puttemprdatalist(client->message, &rdatalist);
2755		return (result);
2756	}
2757	rdataset = NULL;
2758	result = dns_message_gettemprdataset(client->message, &rdataset);
2759	if (result != ISC_R_SUCCESS) {
2760		dns_message_puttempname(client->message, &aname);
2761		dns_message_puttemprdatalist(client->message, &rdatalist);
2762		dns_message_puttemprdata(client->message, &rdata);
2763		return (result);
2764	}
2765	dns_rdataset_init(rdataset);
2766	rdatalist->type = dns_rdatatype_cname;
2767	rdatalist->covers = 0;
2768	rdatalist->rdclass = client->message->rdclass;
2769	rdatalist->ttl = ttl;
2770
2771	dns_name_toregion(tname, &r);
2772	rdata->data = r.base;
2773	rdata->length = r.length;
2774	rdata->rdclass = client->message->rdclass;
2775	rdata->type = dns_rdatatype_cname;
2776
2777	ISC_LIST_INIT(rdatalist->rdata);
2778	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2779	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
2780		      == ISC_R_SUCCESS);
2781	rdataset->trust = trust;
2782
2783	query_addrrset(client, &aname, &rdataset, NULL, NULL,
2784		       DNS_SECTION_ANSWER);
2785	if (rdataset != NULL) {
2786		if (dns_rdataset_isassociated(rdataset))
2787			dns_rdataset_disassociate(rdataset);
2788		dns_message_puttemprdataset(client->message, &rdataset);
2789	}
2790	if (aname != NULL)
2791		dns_message_puttempname(client->message, &aname);
2792
2793	return (ISC_R_SUCCESS);
2794}
2795
2796/*
2797 * Mark the RRsets as secure.  Update the cache (db) to reflect the
2798 * change in trust level.
2799 */
2800static void
2801mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
2802	    dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset,
2803	    dns_rdataset_t *sigrdataset)
2804{
2805	isc_result_t result;
2806	dns_dbnode_t *node = NULL;
2807	dns_clientinfomethods_t cm;
2808	dns_clientinfo_t ci;
2809	isc_stdtime_t now;
2810
2811	rdataset->trust = dns_trust_secure;
2812	sigrdataset->trust = dns_trust_secure;
2813	dns_clientinfomethods_init(&cm, ns_client_sourceip);
2814	dns_clientinfo_init(&ci, client);
2815
2816	/*
2817	 * Save the updated secure state.  Ignore failures.
2818	 */
2819	result = dns_db_findnodeext(db, name, ISC_TRUE, &cm, &ci, &node);
2820	if (result != ISC_R_SUCCESS)
2821		return;
2822
2823	isc_stdtime_get(&now);
2824	dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now,
2825			     client->view->acceptexpired);
2826
2827	(void)dns_db_addrdataset(db, node, NULL, client->now, rdataset,
2828				 0, NULL);
2829	(void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset,
2830				 0, NULL);
2831	dns_db_detachnode(db, &node);
2832}
2833
2834/*
2835 * Find the secure key that corresponds to rrsig.
2836 * Note: 'keyrdataset' maintains state between successive calls,
2837 * there may be multiple keys with the same keyid.
2838 * Return ISC_FALSE if we have exhausted all the possible keys.
2839 */
2840static isc_boolean_t
2841get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
2842	dns_rdataset_t *keyrdataset, dst_key_t **keyp)
2843{
2844	isc_result_t result;
2845	dns_dbnode_t *node = NULL;
2846	isc_boolean_t secure = ISC_FALSE;
2847	dns_clientinfomethods_t cm;
2848	dns_clientinfo_t ci;
2849
2850	dns_clientinfomethods_init(&cm, ns_client_sourceip);
2851	dns_clientinfo_init(&ci, client);
2852
2853	if (!dns_rdataset_isassociated(keyrdataset)) {
2854		result = dns_db_findnodeext(db, &rrsig->signer, ISC_FALSE,
2855					    &cm, &ci, &node);
2856		if (result != ISC_R_SUCCESS)
2857			return (ISC_FALSE);
2858
2859		result = dns_db_findrdataset(db, node, NULL,
2860					     dns_rdatatype_dnskey, 0,
2861					     client->now, keyrdataset, NULL);
2862		dns_db_detachnode(db, &node);
2863		if (result != ISC_R_SUCCESS)
2864			return (ISC_FALSE);
2865
2866		if (keyrdataset->trust != dns_trust_secure)
2867			return (ISC_FALSE);
2868
2869		result = dns_rdataset_first(keyrdataset);
2870	} else
2871		result = dns_rdataset_next(keyrdataset);
2872
2873	for ( ; result == ISC_R_SUCCESS;
2874	     result = dns_rdataset_next(keyrdataset)) {
2875		dns_rdata_t rdata = DNS_RDATA_INIT;
2876		isc_buffer_t b;
2877
2878		dns_rdataset_current(keyrdataset, &rdata);
2879		isc_buffer_init(&b, rdata.data, rdata.length);
2880		isc_buffer_add(&b, rdata.length);
2881		result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
2882					 client->mctx, keyp);
2883		if (result != ISC_R_SUCCESS)
2884			continue;
2885		if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
2886		    rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
2887		    dst_key_iszonekey(*keyp)) {
2888			secure = ISC_TRUE;
2889			break;
2890		}
2891		dst_key_free(keyp);
2892	}
2893	return (secure);
2894}
2895
2896static isc_boolean_t
2897verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,
2898       dns_rdata_t *rdata, ns_client_t *client)
2899{
2900	isc_result_t result;
2901	dns_fixedname_t fixed;
2902	isc_boolean_t ignore = ISC_FALSE;
2903
2904	dns_fixedname_init(&fixed);
2905
2906again:
2907	result = dns_dnssec_verify3(name, rdataset, key, ignore,
2908				    client->view->maxbits, client->mctx,
2909				    rdata, NULL);
2910	if (result == DNS_R_SIGEXPIRED && client->view->acceptexpired) {
2911		ignore = ISC_TRUE;
2912		goto again;
2913	}
2914	if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD)
2915		return (ISC_TRUE);
2916	return (ISC_FALSE);
2917}
2918
2919/*
2920 * Validate the rdataset if possible with available records.
2921 */
2922static isc_boolean_t
2923validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
2924	 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
2925{
2926	isc_result_t result;
2927	dns_rdata_t rdata = DNS_RDATA_INIT;
2928	dns_rdata_rrsig_t rrsig;
2929	dst_key_t *key = NULL;
2930	dns_rdataset_t keyrdataset;
2931
2932	if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
2933		return (ISC_FALSE);
2934
2935	for (result = dns_rdataset_first(sigrdataset);
2936	     result == ISC_R_SUCCESS;
2937	     result = dns_rdataset_next(sigrdataset)) {
2938
2939		dns_rdata_reset(&rdata);
2940		dns_rdataset_current(sigrdataset, &rdata);
2941		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
2942		if (result != ISC_R_SUCCESS)
2943			return (ISC_FALSE);
2944		if (!dns_resolver_algorithm_supported(client->view->resolver,
2945						      name, rrsig.algorithm))
2946			continue;
2947		if (!dns_name_issubdomain(name, &rrsig.signer))
2948			continue;
2949		dns_rdataset_init(&keyrdataset);
2950		do {
2951			if (!get_key(client, db, &rrsig, &keyrdataset, &key))
2952				break;
2953			if (verify(key, name, rdataset, &rdata, client)) {
2954				dst_key_free(&key);
2955				dns_rdataset_disassociate(&keyrdataset);
2956				mark_secure(client, db, name, &rrsig,
2957					    rdataset, sigrdataset);
2958				return (ISC_TRUE);
2959			}
2960			dst_key_free(&key);
2961		} while (1);
2962		if (dns_rdataset_isassociated(&keyrdataset))
2963			dns_rdataset_disassociate(&keyrdataset);
2964	}
2965	return (ISC_FALSE);
2966}
2967
2968static void
2969query_addbestns(ns_client_t *client) {
2970	dns_db_t *db, *zdb;
2971	dns_dbnode_t *node;
2972	dns_name_t *fname, *zfname;
2973	dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset;
2974	isc_boolean_t is_zone, use_zone;
2975	isc_buffer_t *dbuf;
2976	isc_result_t result;
2977	dns_dbversion_t *version;
2978	dns_zone_t *zone;
2979	isc_buffer_t b;
2980	dns_clientinfomethods_t cm;
2981	dns_clientinfo_t ci;
2982
2983	CTRACE("query_addbestns");
2984	fname = NULL;
2985	zfname = NULL;
2986	rdataset = NULL;
2987	zrdataset = NULL;
2988	sigrdataset = NULL;
2989	zsigrdataset = NULL;
2990	node = NULL;
2991	db = NULL;
2992	zdb = NULL;
2993	version = NULL;
2994	zone = NULL;
2995	is_zone = ISC_FALSE;
2996	use_zone = ISC_FALSE;
2997
2998	dns_clientinfomethods_init(&cm, ns_client_sourceip);
2999	dns_clientinfo_init(&ci, client);
3000
3001	/*
3002	 * Find the right database.
3003	 */
3004	result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0,
3005			     &zone, &db, &version, &is_zone);
3006	if (result != ISC_R_SUCCESS)
3007		goto cleanup;
3008
3009 db_find:
3010	/*
3011	 * We'll need some resources...
3012	 */
3013	dbuf = query_getnamebuf(client);
3014	if (dbuf == NULL)
3015		goto cleanup;
3016	fname = query_newname(client, dbuf, &b);
3017	rdataset = query_newrdataset(client);
3018	if (fname == NULL || rdataset == NULL)
3019		goto cleanup;
3020	/*
3021	 * Get the RRSIGs if the client requested them or if we may
3022	 * need to validate answers from the cache.
3023	 */
3024	if (WANTDNSSEC(client) || !is_zone) {
3025		sigrdataset = query_newrdataset(client);
3026		if (sigrdataset == NULL)
3027			goto cleanup;
3028	}
3029
3030	/*
3031	 * Now look for the zonecut.
3032	 */
3033	if (is_zone) {
3034		result = dns_db_findext(db, client->query.qname, version,
3035					dns_rdatatype_ns,
3036					client->query.dboptions,
3037					client->now, &node, fname,
3038					&cm, &ci, rdataset, sigrdataset);
3039		if (result != DNS_R_DELEGATION)
3040			goto cleanup;
3041		if (USECACHE(client)) {
3042			query_keepname(client, fname, dbuf);
3043			zdb = db;
3044			zfname = fname;
3045			fname = NULL;
3046			zrdataset = rdataset;
3047			rdataset = NULL;
3048			zsigrdataset = sigrdataset;
3049			sigrdataset = NULL;
3050			dns_db_detachnode(db, &node);
3051			version = NULL;
3052			db = NULL;
3053			dns_db_attach(client->view->cachedb, &db);
3054			is_zone = ISC_FALSE;
3055			goto db_find;
3056		}
3057	} else {
3058		result = dns_db_findzonecut(db, client->query.qname,
3059					    client->query.dboptions,
3060					    client->now, &node, fname,
3061					    rdataset, sigrdataset);
3062		if (result == ISC_R_SUCCESS) {
3063			if (zfname != NULL &&
3064			    !dns_name_issubdomain(fname, zfname)) {
3065				/*
3066				 * We found a zonecut in the cache, but our
3067				 * zone delegation is better.
3068				 */
3069				use_zone = ISC_TRUE;
3070			}
3071		} else if (result == ISC_R_NOTFOUND && zfname != NULL) {
3072			/*
3073			 * We didn't find anything in the cache, but we
3074			 * have a zone delegation, so use it.
3075			 */
3076			use_zone = ISC_TRUE;
3077		} else
3078			goto cleanup;
3079	}
3080
3081	if (use_zone) {
3082		query_releasename(client, &fname);
3083		fname = zfname;
3084		zfname = NULL;
3085		/*
3086		 * We've already done query_keepname() on
3087		 * zfname, so we must set dbuf to NULL to
3088		 * prevent query_addrrset() from trying to
3089		 * call query_keepname() again.
3090		 */
3091		dbuf = NULL;
3092		query_putrdataset(client, &rdataset);
3093		if (sigrdataset != NULL)
3094			query_putrdataset(client, &sigrdataset);
3095		rdataset = zrdataset;
3096		zrdataset = NULL;
3097		sigrdataset = zsigrdataset;
3098		zsigrdataset = NULL;
3099	}
3100
3101	/*
3102	 * Attempt to validate RRsets that are pending or that are glue.
3103	 */
3104	if ((DNS_TRUST_PENDING(rdataset->trust) ||
3105	     (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust)))
3106	    && !validate(client, db, fname, rdataset, sigrdataset) &&
3107	    !PENDINGOK(client->query.dboptions))
3108		goto cleanup;
3109
3110	if ((DNS_TRUST_GLUE(rdataset->trust) ||
3111	     (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
3112	    !validate(client, db, fname, rdataset, sigrdataset) &&
3113	    SECURE(client) && WANTDNSSEC(client))
3114		goto cleanup;
3115
3116	/*
3117	 * If the client doesn't want DNSSEC we can discard the sigrdataset
3118	 * now.
3119	 */
3120	if (!WANTDNSSEC(client))
3121		query_putrdataset(client, &sigrdataset);
3122	query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
3123		       DNS_SECTION_AUTHORITY);
3124
3125 cleanup:
3126	if (rdataset != NULL)
3127		query_putrdataset(client, &rdataset);
3128	if (sigrdataset != NULL)
3129		query_putrdataset(client, &sigrdataset);
3130	if (fname != NULL)
3131		query_releasename(client, &fname);
3132	if (node != NULL)
3133		dns_db_detachnode(db, &node);
3134	if (db != NULL)
3135		dns_db_detach(&db);
3136	if (zone != NULL)
3137		dns_zone_detach(&zone);
3138	if (zdb != NULL) {
3139		query_putrdataset(client, &zrdataset);
3140		if (zsigrdataset != NULL)
3141			query_putrdataset(client, &zsigrdataset);
3142		if (zfname != NULL)
3143			query_releasename(client, &zfname);
3144		dns_db_detach(&zdb);
3145	}
3146}
3147
3148static void
3149fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) {
3150	if (*rdataset == NULL)
3151		*rdataset = query_newrdataset(client);
3152	else  if (dns_rdataset_isassociated(*rdataset))
3153		dns_rdataset_disassociate(*rdataset);
3154}
3155
3156static void
3157fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf,
3158	 isc_buffer_t *nbuf)
3159{
3160	if (*fname == NULL) {
3161		*dbuf = query_getnamebuf(client);
3162		if (*dbuf == NULL)
3163			return;
3164		*fname = query_newname(client, *dbuf, nbuf);
3165	}
3166}
3167
3168static void
3169query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node,
3170	    dns_dbversion_t *version, dns_name_t *name)
3171{
3172	dns_fixedname_t fixed;
3173	dns_name_t *fname = NULL;
3174	dns_name_t *rname;
3175	dns_rdataset_t *rdataset, *sigrdataset;
3176	isc_buffer_t *dbuf, b;
3177	isc_result_t result;
3178	unsigned int count;
3179
3180	CTRACE("query_addds");
3181	rname = NULL;
3182	rdataset = NULL;
3183	sigrdataset = NULL;
3184
3185	/*
3186	 * We'll need some resources...
3187	 */
3188	rdataset = query_newrdataset(client);
3189	sigrdataset = query_newrdataset(client);
3190	if (rdataset == NULL || sigrdataset == NULL)
3191		goto cleanup;
3192
3193	/*
3194	 * Look for the DS record, which may or may not be present.
3195	 */
3196	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ds, 0,
3197				     client->now, rdataset, sigrdataset);
3198	/*
3199	 * If we didn't find it, look for an NSEC.
3200	 */
3201	if (result == ISC_R_NOTFOUND)
3202		result = dns_db_findrdataset(db, node, version,
3203					     dns_rdatatype_nsec, 0, client->now,
3204					     rdataset, sigrdataset);
3205	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
3206		goto addnsec3;
3207	if (!dns_rdataset_isassociated(rdataset) ||
3208	    !dns_rdataset_isassociated(sigrdataset))
3209		goto addnsec3;
3210
3211	/*
3212	 * We've already added the NS record, so if the name's not there,
3213	 * we have other problems.  Use this name rather than calling
3214	 * query_addrrset().
3215	 */
3216	result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
3217	if (result != ISC_R_SUCCESS)
3218		goto cleanup;
3219
3220	rname = NULL;
3221	dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
3222				&rname);
3223	result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
3224	if (result != ISC_R_SUCCESS)
3225		goto cleanup;
3226
3227	ISC_LIST_APPEND(rname->list, rdataset, link);
3228	ISC_LIST_APPEND(rname->list, sigrdataset, link);
3229	rdataset = NULL;
3230	sigrdataset = NULL;
3231	return;
3232
3233   addnsec3:
3234	if (!dns_db_iszone(db))
3235		goto cleanup;
3236	/*
3237	 * Add the NSEC3 which proves the DS does not exist.
3238	 */
3239	dbuf = query_getnamebuf(client);
3240	if (dbuf == NULL)
3241		goto cleanup;
3242	fname = query_newname(client, dbuf, &b);
3243	dns_fixedname_init(&fixed);
3244	if (dns_rdataset_isassociated(rdataset))
3245		dns_rdataset_disassociate(rdataset);
3246	if (dns_rdataset_isassociated(sigrdataset))
3247		dns_rdataset_disassociate(sigrdataset);
3248	query_findclosestnsec3(name, db, version, client, rdataset,
3249			       sigrdataset, fname, ISC_TRUE,
3250			       dns_fixedname_name(&fixed));
3251	if (!dns_rdataset_isassociated(rdataset))
3252		goto cleanup;
3253	query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
3254		       DNS_SECTION_AUTHORITY);
3255	/*
3256	 * Did we find the closest provable encloser instead?
3257	 * If so add the nearest to the closest provable encloser.
3258	 */
3259	if (!dns_name_equal(name, dns_fixedname_name(&fixed))) {
3260		count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1;
3261		dns_name_getlabelsequence(name,
3262					  dns_name_countlabels(name) - count,
3263					  count, dns_fixedname_name(&fixed));
3264		fixfname(client, &fname, &dbuf, &b);
3265		fixrdataset(client, &rdataset);
3266		fixrdataset(client, &sigrdataset);
3267		if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
3268				goto cleanup;
3269		query_findclosestnsec3(dns_fixedname_name(&fixed), db, version,
3270				       client, rdataset, sigrdataset, fname,
3271				       ISC_FALSE, NULL);
3272		if (!dns_rdataset_isassociated(rdataset))
3273			goto cleanup;
3274		query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
3275			       DNS_SECTION_AUTHORITY);
3276	}
3277
3278 cleanup:
3279	if (rdataset != NULL)
3280		query_putrdataset(client, &rdataset);
3281	if (sigrdataset != NULL)
3282		query_putrdataset(client, &sigrdataset);
3283	if (fname != NULL)
3284		query_releasename(client, &fname);
3285}
3286
3287static void
3288query_addwildcardproof(ns_client_t *client, dns_db_t *db,
3289		       dns_dbversion_t *version, dns_name_t *name,
3290		       isc_boolean_t ispositive, isc_boolean_t nodata)
3291{
3292	isc_buffer_t *dbuf, b;
3293	dns_name_t *fname;
3294	dns_rdataset_t *rdataset, *sigrdataset;
3295	dns_fixedname_t wfixed;
3296	dns_name_t *wname;
3297	dns_dbnode_t *node;
3298	unsigned int options;
3299	unsigned int olabels, nlabels, labels;
3300	isc_result_t result;
3301	dns_rdata_t rdata = DNS_RDATA_INIT;
3302	dns_rdata_nsec_t nsec;
3303	isc_boolean_t have_wname;
3304	int order;
3305	dns_fixedname_t cfixed;
3306	dns_name_t *cname;
3307	dns_clientinfomethods_t cm;
3308	dns_clientinfo_t ci;
3309
3310	CTRACE("query_addwildcardproof");
3311	fname = NULL;
3312	rdataset = NULL;
3313	sigrdataset = NULL;
3314	node = NULL;
3315
3316	dns_clientinfomethods_init(&cm, ns_client_sourceip);
3317	dns_clientinfo_init(&ci, client);
3318
3319	/*
3320	 * Get the NOQNAME proof then if !ispositive
3321	 * get the NOWILDCARD proof.
3322	 *
3323	 * DNS_DBFIND_NOWILD finds the NSEC records that covers the
3324	 * name ignoring any wildcard.  From the owner and next names
3325	 * of this record you can compute which wildcard (if it exists)
3326	 * will match by finding the longest common suffix of the
3327	 * owner name and next names with the qname and prefixing that
3328	 * with the wildcard label.
3329	 *
3330	 * e.g.
3331	 *   Given:
3332	 *	example SOA
3333	 *	example NSEC b.example
3334	 *	b.example A
3335	 *	b.example NSEC a.d.example
3336	 *	a.d.example A
3337	 *	a.d.example NSEC g.f.example
3338	 *	g.f.example A
3339	 *	g.f.example NSEC z.i.example
3340	 *	z.i.example A
3341	 *	z.i.example NSEC example
3342	 *
3343	 *   QNAME:
3344	 *   a.example -> example NSEC b.example
3345	 *	owner common example
3346	 *	next common example
3347	 *	wild *.example
3348	 *   d.b.example -> b.example NSEC a.d.example
3349	 *	owner common b.example
3350	 *	next common example
3351	 *	wild *.b.example
3352	 *   a.f.example -> a.d.example NSEC g.f.example
3353	 *	owner common example
3354	 *	next common f.example
3355	 *	wild *.f.example
3356	 *  j.example -> z.i.example NSEC example
3357	 *	owner common example
3358	 *	next common example
3359	 *	wild *.example
3360	 */
3361	options = client->query.dboptions | DNS_DBFIND_NOWILD;
3362	dns_fixedname_init(&wfixed);
3363	wname = dns_fixedname_name(&wfixed);
3364 again:
3365	have_wname = ISC_FALSE;
3366	/*
3367	 * We'll need some resources...
3368	 */
3369	dbuf = query_getnamebuf(client);
3370	if (dbuf == NULL)
3371		goto cleanup;
3372	fname = query_newname(client, dbuf, &b);
3373	rdataset = query_newrdataset(client);
3374	sigrdataset = query_newrdataset(client);
3375	if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
3376		goto cleanup;
3377
3378	result = dns_db_findext(db, name, version, dns_rdatatype_nsec,
3379				options, 0, &node, fname, &cm, &ci,
3380				rdataset, sigrdataset);
3381	if (node != NULL)
3382		dns_db_detachnode(db, &node);
3383
3384	if (!dns_rdataset_isassociated(rdataset)) {
3385		/*
3386		 * No NSEC proof available, return NSEC3 proofs instead.
3387		 */
3388		dns_fixedname_init(&cfixed);
3389		cname = dns_fixedname_name(&cfixed);
3390		/*
3391		 * Find the closest encloser.
3392		 */
3393		dns_name_copy(name, cname, NULL);
3394		while (result == DNS_R_NXDOMAIN) {
3395			labels = dns_name_countlabels(cname) - 1;
3396			/*
3397			 * Sanity check.
3398			 */
3399			if (labels == 0U)
3400				goto cleanup;
3401			dns_name_split(cname, labels, NULL, cname);
3402			result = dns_db_findext(db, cname, version,
3403						dns_rdatatype_nsec,
3404						options, 0, NULL, fname,
3405						&cm, &ci, NULL, NULL);
3406		}
3407		/*
3408		 * Add closest (provable) encloser NSEC3.
3409		 */
3410		query_findclosestnsec3(cname, db, NULL, client, rdataset,
3411				       sigrdataset, fname, ISC_TRUE, cname);
3412		if (!dns_rdataset_isassociated(rdataset))
3413			goto cleanup;
3414		if (!ispositive)
3415			query_addrrset(client, &fname, &rdataset, &sigrdataset,
3416				       dbuf, DNS_SECTION_AUTHORITY);
3417
3418		/*
3419		 * Replace resources which were consumed by query_addrrset.
3420		 */
3421		if (fname == NULL) {
3422			dbuf = query_getnamebuf(client);
3423			if (dbuf == NULL)
3424				goto cleanup;
3425			fname = query_newname(client, dbuf, &b);
3426		}
3427
3428		if (rdataset == NULL)
3429			rdataset = query_newrdataset(client);
3430		else if (dns_rdataset_isassociated(rdataset))
3431			dns_rdataset_disassociate(rdataset);
3432
3433		if (sigrdataset == NULL)
3434			sigrdataset = query_newrdataset(client);
3435		else if (dns_rdataset_isassociated(sigrdataset))
3436			dns_rdataset_disassociate(sigrdataset);
3437
3438		if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
3439			goto cleanup;
3440		/*
3441		 * Add no qname proof.
3442		 */
3443		labels = dns_name_countlabels(cname) + 1;
3444		if (dns_name_countlabels(name) == labels)
3445			dns_name_copy(name, wname, NULL);
3446		else
3447			dns_name_split(name, labels, NULL, wname);
3448
3449		query_findclosestnsec3(wname, db, NULL, client, rdataset,
3450				       sigrdataset, fname, ISC_FALSE, NULL);
3451		if (!dns_rdataset_isassociated(rdataset))
3452			goto cleanup;
3453		query_addrrset(client, &fname, &rdataset, &sigrdataset,
3454			       dbuf, DNS_SECTION_AUTHORITY);
3455
3456		if (ispositive)
3457			goto cleanup;
3458
3459		/*
3460		 * Replace resources which were consumed by query_addrrset.
3461		 */
3462		if (fname == NULL) {
3463			dbuf = query_getnamebuf(client);
3464			if (dbuf == NULL)
3465				goto cleanup;
3466			fname = query_newname(client, dbuf, &b);
3467		}
3468
3469		if (rdataset == NULL)
3470			rdataset = query_newrdataset(client);
3471		else if (dns_rdataset_isassociated(rdataset))
3472			dns_rdataset_disassociate(rdataset);
3473
3474		if (sigrdataset == NULL)
3475			sigrdataset = query_newrdataset(client);
3476		else if (dns_rdataset_isassociated(sigrdataset))
3477			dns_rdataset_disassociate(sigrdataset);
3478
3479		if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
3480			goto cleanup;
3481		/*
3482		 * Add the no wildcard proof.
3483		 */
3484		result = dns_name_concatenate(dns_wildcardname,
3485					      cname, wname, NULL);
3486		if (result != ISC_R_SUCCESS)
3487			goto cleanup;
3488
3489		query_findclosestnsec3(wname, db, NULL, client, rdataset,
3490				       sigrdataset, fname, nodata, NULL);
3491		if (!dns_rdataset_isassociated(rdataset))
3492			goto cleanup;
3493		query_addrrset(client, &fname, &rdataset, &sigrdataset,
3494			       dbuf, DNS_SECTION_AUTHORITY);
3495
3496		goto cleanup;
3497	} else if (result == DNS_R_NXDOMAIN) {
3498		if (!ispositive)
3499			result = dns_rdataset_first(rdataset);
3500		if (result == ISC_R_SUCCESS) {
3501			dns_rdataset_current(rdataset, &rdata);
3502			result = dns_rdata_tostruct(&rdata, &nsec, NULL);
3503		}
3504		if (result == ISC_R_SUCCESS) {
3505			(void)dns_name_fullcompare(name, fname, &order,
3506						   &olabels);
3507			(void)dns_name_fullcompare(name, &nsec.next, &order,
3508						   &nlabels);
3509			/*
3510			 * Check for a pathological condition created when
3511			 * serving some malformed signed zones and bail out.
3512			 */
3513			if (dns_name_countlabels(name) == nlabels)
3514				goto cleanup;
3515
3516			if (olabels > nlabels)
3517				dns_name_split(name, olabels, NULL, wname);
3518			else
3519				dns_name_split(name, nlabels, NULL, wname);
3520			result = dns_name_concatenate(dns_wildcardname,
3521						      wname, wname, NULL);
3522			if (result == ISC_R_SUCCESS)
3523				have_wname = ISC_TRUE;
3524			dns_rdata_freestruct(&nsec);
3525		}
3526		query_addrrset(client, &fname, &rdataset, &sigrdataset,
3527			       dbuf, DNS_SECTION_AUTHORITY);
3528	}
3529	if (rdataset != NULL)
3530		query_putrdataset(client, &rdataset);
3531	if (sigrdataset != NULL)
3532		query_putrdataset(client, &sigrdataset);
3533	if (fname != NULL)
3534		query_releasename(client, &fname);
3535	if (have_wname) {
3536		ispositive = ISC_TRUE;	/* prevent loop */
3537		if (!dns_name_equal(name, wname)) {
3538			name = wname;
3539			goto again;
3540		}
3541	}
3542 cleanup:
3543	if (rdataset != NULL)
3544		query_putrdataset(client, &rdataset);
3545	if (sigrdataset != NULL)
3546		query_putrdataset(client, &sigrdataset);
3547	if (fname != NULL)
3548		query_releasename(client, &fname);
3549}
3550
3551static void
3552query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db,
3553		     dns_dbversion_t *version, dns_name_t **namep,
3554		     dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp)
3555{
3556	dns_name_t *name;
3557	dns_rdataset_t *sigrdataset;
3558	dns_rdata_t sigrdata;
3559	dns_rdata_rrsig_t sig;
3560	unsigned int labels;
3561	isc_buffer_t *dbuf, b;
3562	dns_name_t *fname;
3563	isc_result_t result;
3564
3565	name = *namep;
3566	if ((name->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
3567		query_addrrset(client, namep, rdatasetp, sigrdatasetp,
3568			       NULL, DNS_SECTION_AUTHORITY);
3569		return;
3570	}
3571
3572	if (sigrdatasetp == NULL)
3573		return;
3574
3575	sigrdataset = *sigrdatasetp;
3576	if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
3577		return;
3578	result = dns_rdataset_first(sigrdataset);
3579	if (result != ISC_R_SUCCESS)
3580		return;
3581	dns_rdata_init(&sigrdata);
3582	dns_rdataset_current(sigrdataset, &sigrdata);
3583	result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
3584	if (result != ISC_R_SUCCESS)
3585		return;
3586
3587	labels = dns_name_countlabels(name);
3588	if ((unsigned int)sig.labels + 1 >= labels)
3589		return;
3590
3591	/* XXX */
3592	query_addwildcardproof(client, db, version, client->query.qname,
3593			       ISC_TRUE, ISC_FALSE);
3594
3595	/*
3596	 * We'll need some resources...
3597	 */
3598	dbuf = query_getnamebuf(client);
3599	if (dbuf == NULL)
3600		return;
3601	fname = query_newname(client, dbuf, &b);
3602	if (fname == NULL)
3603		return;
3604	dns_name_split(name, sig.labels + 1, NULL, fname);
3605	/* This will succeed, since we've stripped labels. */
3606	RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,
3607					   NULL) == ISC_R_SUCCESS);
3608	query_addrrset(client, &fname, rdatasetp, sigrdatasetp,
3609		       dbuf, DNS_SECTION_AUTHORITY);
3610}
3611
3612static void
3613query_resume(isc_task_t *task, isc_event_t *event) {
3614	dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
3615	dns_fetch_t *fetch;
3616	ns_client_t *client;
3617	isc_boolean_t fetch_canceled, client_shuttingdown;
3618	isc_result_t result;
3619	isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_EERRORS;
3620	int errorloglevel;
3621
3622	/*
3623	 * Resume a query after recursion.
3624	 */
3625
3626	UNUSED(task);
3627
3628	REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
3629	client = devent->ev_arg;
3630	REQUIRE(NS_CLIENT_VALID(client));
3631	REQUIRE(task == client->task);
3632	REQUIRE(RECURSING(client));
3633
3634	LOCK(&client->query.fetchlock);
3635	if (client->query.fetch != NULL) {
3636		/*
3637		 * This is the fetch we've been waiting for.
3638		 */
3639		INSIST(devent->fetch == client->query.fetch);
3640		client->query.fetch = NULL;
3641		fetch_canceled = ISC_FALSE;
3642		/*
3643		 * Update client->now.
3644		 */
3645		isc_stdtime_get(&client->now);
3646	} else {
3647		/*
3648		 * This is a fetch completion event for a canceled fetch.
3649		 * Clean up and don't resume the find.
3650		 */
3651		fetch_canceled = ISC_TRUE;
3652	}
3653	UNLOCK(&client->query.fetchlock);
3654	INSIST(client->query.fetch == NULL);
3655
3656	client->query.attributes &= ~NS_QUERYATTR_RECURSING;
3657	fetch = devent->fetch;
3658	devent->fetch = NULL;
3659
3660	/*
3661	 * If this client is shutting down, or this transaction
3662	 * has timed out, do not resume the find.
3663	 */
3664	client_shuttingdown = ns_client_shuttingdown(client);
3665	if (fetch_canceled || client_shuttingdown) {
3666		if (devent->node != NULL)
3667			dns_db_detachnode(devent->db, &devent->node);
3668		if (devent->db != NULL)
3669			dns_db_detach(&devent->db);
3670		query_putrdataset(client, &devent->rdataset);
3671		if (devent->sigrdataset != NULL)
3672			query_putrdataset(client, &devent->sigrdataset);
3673		isc_event_free(&event);
3674		if (fetch_canceled)
3675			query_error(client, DNS_R_SERVFAIL, __LINE__);
3676		else
3677			query_next(client, ISC_R_CANCELED);
3678		/*
3679		 * This may destroy the client.
3680		 */
3681		ns_client_detach(&client);
3682	} else {
3683		result = query_find(client, devent, 0);
3684		if (result != ISC_R_SUCCESS) {
3685			if (result == DNS_R_SERVFAIL)
3686				errorloglevel = ISC_LOG_DEBUG(2);
3687			else
3688				errorloglevel = ISC_LOG_DEBUG(4);
3689			if (isc_log_wouldlog(ns_g_lctx, errorloglevel)) {
3690				dns_resolver_logfetch(fetch, ns_g_lctx,
3691						      logcategory,
3692						      NS_LOGMODULE_QUERY,
3693						      errorloglevel, ISC_FALSE);
3694			}
3695		}
3696	}
3697
3698	dns_resolver_destroyfetch(&fetch);
3699}
3700
3701static isc_result_t
3702query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
3703	      dns_name_t *qdomain, dns_rdataset_t *nameservers,
3704	      isc_boolean_t resuming)
3705{
3706	isc_result_t result;
3707	dns_rdataset_t *rdataset, *sigrdataset;
3708	isc_sockaddr_t *peeraddr;
3709
3710	if (!resuming)
3711		inc_stats(client, dns_nsstatscounter_recursion);
3712
3713	/*
3714	 * We are about to recurse, which means that this client will
3715	 * be unavailable for serving new requests for an indeterminate
3716	 * amount of time.  If this client is currently responsible
3717	 * for handling incoming queries, set up a new client
3718	 * object to handle them while we are waiting for a
3719	 * response.  There is no need to replace TCP clients
3720	 * because those have already been replaced when the
3721	 * connection was accepted (if allowed by the TCP quota).
3722	 */
3723	if (client->recursionquota == NULL) {
3724		result = isc_quota_attach(&ns_g_server->recursionquota,
3725					  &client->recursionquota);
3726		if  (result == ISC_R_SOFTQUOTA) {
3727			static isc_stdtime_t last = 0;
3728			isc_stdtime_t now;
3729			isc_stdtime_get(&now);
3730			if (now != last) {
3731				last = now;
3732				ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3733					      NS_LOGMODULE_QUERY,
3734					      ISC_LOG_WARNING,
3735					      "recursive-clients soft limit "
3736					      "exceeded (%d/%d/%d), "
3737					      "aborting oldest query",
3738					      client->recursionquota->used,
3739					      client->recursionquota->soft,
3740					      client->recursionquota->max);
3741			}
3742			ns_client_killoldestquery(client);
3743			result = ISC_R_SUCCESS;
3744		} else if (result == ISC_R_QUOTA) {
3745			static isc_stdtime_t last = 0;
3746			isc_stdtime_t now;
3747			isc_stdtime_get(&now);
3748			if (now != last) {
3749				last = now;
3750				ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3751					      NS_LOGMODULE_QUERY,
3752					      ISC_LOG_WARNING,
3753					      "no more recursive clients "
3754					      "(%d/%d/%d): %s",
3755					      ns_g_server->recursionquota.used,
3756					      ns_g_server->recursionquota.soft,
3757					      ns_g_server->recursionquota.max,
3758					      isc_result_totext(result));
3759			}
3760			ns_client_killoldestquery(client);
3761		}
3762		if (result == ISC_R_SUCCESS && !client->mortal &&
3763		    (client->attributes & NS_CLIENTATTR_TCP) == 0) {
3764			result = ns_client_replace(client);
3765			if (result != ISC_R_SUCCESS) {
3766				ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3767					      NS_LOGMODULE_QUERY,
3768					      ISC_LOG_WARNING,
3769					      "ns_client_replace() failed: %s",
3770					      isc_result_totext(result));
3771				isc_quota_detach(&client->recursionquota);
3772			}
3773		}
3774		if (result != ISC_R_SUCCESS)
3775			return (result);
3776		ns_client_recursing(client);
3777	}
3778
3779	/*
3780	 * Invoke the resolver.
3781	 */
3782	REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
3783	REQUIRE(client->query.fetch == NULL);
3784
3785	rdataset = query_newrdataset(client);
3786	if (rdataset == NULL)
3787		return (ISC_R_NOMEMORY);
3788	if (WANTDNSSEC(client)) {
3789		sigrdataset = query_newrdataset(client);
3790		if (sigrdataset == NULL) {
3791			query_putrdataset(client, &rdataset);
3792			return (ISC_R_NOMEMORY);
3793		}
3794	} else
3795		sigrdataset = NULL;
3796
3797	if (client->query.timerset == ISC_FALSE)
3798		ns_client_settimeout(client, 60);
3799	if ((client->attributes & NS_CLIENTATTR_TCP) == 0)
3800		peeraddr = &client->peeraddr;
3801	else
3802		peeraddr = NULL;
3803	result = dns_resolver_createfetch2(client->view->resolver,
3804					   qname, qtype, qdomain, nameservers,
3805					   NULL, peeraddr, client->message->id,
3806					   client->query.fetchoptions,
3807					   client->task,
3808					   query_resume, client,
3809					   rdataset, sigrdataset,
3810					   &client->query.fetch);
3811
3812	if (result == ISC_R_SUCCESS) {
3813		/*
3814		 * Record that we're waiting for an event.  A client which
3815		 * is shutting down will not be destroyed until all the
3816		 * events have been received.
3817		 */
3818	} else {
3819		query_putrdataset(client, &rdataset);
3820		if (sigrdataset != NULL)
3821			query_putrdataset(client, &sigrdataset);
3822	}
3823
3824	return (result);
3825}
3826
3827static inline void
3828rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
3829	  dns_rdataset_t **rdatasetp)
3830{
3831	if (nodep != NULL && *nodep != NULL) {
3832		REQUIRE(dbp != NULL && *dbp != NULL);
3833		dns_db_detachnode(*dbp, nodep);
3834	}
3835	if (dbp != NULL && *dbp != NULL)
3836		dns_db_detach(dbp);
3837	if (zonep != NULL && *zonep != NULL)
3838		dns_zone_detach(zonep);
3839	if (rdatasetp != NULL && *rdatasetp != NULL &&
3840	    dns_rdataset_isassociated(*rdatasetp))
3841		dns_rdataset_disassociate(*rdatasetp);
3842}
3843
3844static void
3845rpz_match_clear(dns_rpz_st_t *st)
3846{
3847	rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
3848	st->m.version = NULL;
3849}
3850
3851static inline isc_result_t
3852rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp,
3853	  dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp)
3854{
3855	REQUIRE(rdatasetp != NULL);
3856
3857	rpz_clean(zonep, dbp, nodep, rdatasetp);
3858	if (*rdatasetp == NULL) {
3859		*rdatasetp = query_newrdataset(client);
3860		if (*rdatasetp == NULL)
3861			return (DNS_R_SERVFAIL);
3862	}
3863	return (ISC_R_SUCCESS);
3864}
3865
3866static void
3867rpz_st_clear(ns_client_t *client) {
3868	dns_rpz_st_t *st = client->query.rpz_st;
3869
3870	if (st->m.rdataset != NULL)
3871		query_putrdataset(client, &st->m.rdataset);
3872	rpz_match_clear(st);
3873
3874	rpz_clean(NULL, &st->r.db, NULL, NULL);
3875	if (st->r.ns_rdataset != NULL)
3876		query_putrdataset(client, &st->r.ns_rdataset);
3877	if (st->r.r_rdataset != NULL)
3878		query_putrdataset(client, &st->r.r_rdataset);
3879
3880	rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL);
3881	if (st->q.rdataset != NULL)
3882		query_putrdataset(client, &st->q.rdataset);
3883	if (st->q.sigrdataset != NULL)
3884		query_putrdataset(client, &st->q.sigrdataset);
3885	st->state = 0;
3886	st->m.type = DNS_RPZ_TYPE_BAD;
3887	st->m.policy = DNS_RPZ_POLICY_MISS;
3888}
3889
3890/*
3891 * Get NS, A, or AAAA rrset for response policy zone checks.
3892 */
3893static isc_result_t
3894rpz_rrset_find(ns_client_t *client, dns_rpz_type_t rpz_type,
3895	       dns_name_t *name, dns_rdatatype_t type,
3896	       dns_db_t **dbp, dns_dbversion_t *version,
3897	       dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
3898{
3899	dns_rpz_st_t *st;
3900	isc_boolean_t is_zone;
3901	dns_dbnode_t *node;
3902	dns_fixedname_t fixed;
3903	dns_name_t *found;
3904	isc_result_t result;
3905	dns_clientinfomethods_t cm;
3906	dns_clientinfo_t ci;
3907
3908	dns_clientinfomethods_init(&cm, ns_client_sourceip);
3909	dns_clientinfo_init(&ci, client);
3910
3911	st = client->query.rpz_st;
3912	if ((st->state & DNS_RPZ_RECURSING) != 0) {
3913		INSIST(st->r.r_type == type);
3914		INSIST(dns_name_equal(name, st->r_name));
3915		INSIST(*rdatasetp == NULL ||
3916		       !dns_rdataset_isassociated(*rdatasetp));
3917		st->state &= ~DNS_RPZ_RECURSING;
3918		*dbp = st->r.db;
3919		st->r.db = NULL;
3920		if (*rdatasetp != NULL)
3921			query_putrdataset(client, rdatasetp);
3922		*rdatasetp = st->r.r_rdataset;
3923		st->r.r_rdataset = NULL;
3924		result = st->r.r_result;
3925		if (result == DNS_R_DELEGATION) {
3926			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
3927				     rpz_type, name,
3928				     "rpz_rrset_find(1) ", result);
3929			st->m.policy = DNS_RPZ_POLICY_ERROR;
3930			result = DNS_R_SERVFAIL;
3931		}
3932		return (result);
3933	}
3934
3935	result = rpz_ready(client, NULL, NULL, NULL, rdatasetp);
3936	if (result != ISC_R_SUCCESS) {
3937		st->m.policy = DNS_RPZ_POLICY_ERROR;
3938		return (result);
3939	}
3940	if (*dbp != NULL) {
3941		is_zone = ISC_FALSE;
3942	} else {
3943		dns_zone_t *zone;
3944
3945		version = NULL;
3946		zone = NULL;
3947		result = query_getdb(client, name, type, 0, &zone, dbp,
3948				     &version, &is_zone);
3949		if (result != ISC_R_SUCCESS) {
3950			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
3951				     rpz_type, name,
3952				     "rpz_rrset_find(2) ", result);
3953			st->m.policy = DNS_RPZ_POLICY_ERROR;
3954			if (zone != NULL)
3955				dns_zone_detach(&zone);
3956			return (result);
3957		}
3958		if (zone != NULL)
3959			dns_zone_detach(&zone);
3960	}
3961
3962	node = NULL;
3963	dns_fixedname_init(&fixed);
3964	found = dns_fixedname_name(&fixed);
3965	result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK,
3966				client->now, &node, found,
3967				&cm, &ci, *rdatasetp, NULL);
3968	if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) {
3969		/*
3970		 * Try the cache if we're authoritative for an
3971		 * ancestor but not the domain itself.
3972		 */
3973		rpz_clean(NULL, dbp, &node, rdatasetp);
3974		version = NULL;
3975		dns_db_attach(client->view->cachedb, dbp);
3976		result = dns_db_findext(*dbp, name, version, dns_rdatatype_ns,
3977					0, client->now, &node, found,
3978					&cm, &ci, *rdatasetp, NULL);
3979	}
3980	rpz_clean(NULL, dbp, &node, NULL);
3981	if (result == DNS_R_DELEGATION) {
3982		rpz_clean(NULL, NULL, NULL, rdatasetp);
3983		/*
3984		 * Recurse for NS rrset or A or AAAA rrset for an NS.
3985		 * Do not recurse for addresses for the query name.
3986		 */
3987		if (rpz_type == DNS_RPZ_TYPE_IP) {
3988			result = DNS_R_NXRRSET;
3989		} else {
3990			dns_name_copy(name, st->r_name, NULL);
3991			result = query_recurse(client, type, st->r_name,
3992					       NULL, NULL, resuming);
3993			if (result == ISC_R_SUCCESS) {
3994				st->state |= DNS_RPZ_RECURSING;
3995				result = DNS_R_DELEGATION;
3996			}
3997		}
3998	}
3999	return (result);
4000}
4001
4002/*
4003 * Check the IP address in an A or AAAA rdataset against
4004 * the IP or NSIP response policy rules of a view.
4005 */
4006static isc_result_t
4007rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset,
4008	       dns_rpz_type_t rpz_type)
4009{
4010	dns_rpz_st_t *st;
4011	dns_dbversion_t *version;
4012	dns_zone_t *zone;
4013	dns_db_t *db;
4014	dns_rpz_zone_t *rpz;
4015	isc_result_t result;
4016
4017	st = client->query.rpz_st;
4018	if (st->m.rdataset == NULL) {
4019		st->m.rdataset = query_newrdataset(client);
4020		if (st->m.rdataset == NULL)
4021			return (DNS_R_SERVFAIL);
4022	}
4023	zone = NULL;
4024	db = NULL;
4025	for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
4026	     rpz != NULL;
4027	     rpz = ISC_LIST_NEXT(rpz, link)) {
4028		if (!RECURSIONOK(client) && rpz->recursive_only)
4029			continue;
4030
4031		/*
4032		 * Do not check policy zones that cannot replace a policy
4033		 * already known to match.
4034		 */
4035		if (st->m.policy != DNS_RPZ_POLICY_MISS) {
4036			if (st->m.rpz->num < rpz->num)
4037				break;
4038			if (st->m.rpz->num == rpz->num &&
4039			    st->m.type < rpz_type)
4040				continue;
4041		}
4042
4043		/*
4044		 * Find the database for this policy zone to get its radix tree.
4045		 */
4046		version = NULL;
4047		result = rpz_getdb(client, rpz_type, &rpz->origin,
4048				   &zone, &db, &version);
4049		if (result != ISC_R_SUCCESS) {
4050			rpz_clean(&zone, &db, NULL, NULL);
4051			continue;
4052		}
4053		/*
4054		 * Look for a better (e.g. longer prefix) hit for an IP address
4055		 * in this rdataset in this radix tree than than the previous
4056		 * hit, if any.  Note the domain name and quality of the
4057		 * best hit.
4058		 */
4059		dns_db_rpz_findips(rpz, rpz_type, zone, db, version,
4060				   rdataset, st, client->query.rpz_st->qname);
4061		rpz_clean(&zone, &db, NULL, NULL);
4062	}
4063	return (ISC_R_SUCCESS);
4064}
4065
4066/*
4067 * Look for an A or AAAA rdataset
4068 * and check for IP or NSIP rewrite policy rules.
4069 */
4070static isc_result_t
4071rpz_rewrite_rrset(ns_client_t *client, dns_rpz_type_t rpz_type,
4072		  dns_rdatatype_t type, dns_name_t *name,
4073		  dns_db_t **dbp, dns_dbversion_t *version,
4074		  dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
4075{
4076	isc_result_t result;
4077
4078	result = rpz_rrset_find(client, rpz_type, name, type, dbp, version,
4079				rdatasetp, resuming);
4080	switch (result) {
4081	case ISC_R_SUCCESS:
4082		result = rpz_rewrite_ip(client, *rdatasetp, rpz_type);
4083		break;
4084	case DNS_R_EMPTYNAME:
4085	case DNS_R_EMPTYWILD:
4086	case DNS_R_NXDOMAIN:
4087	case DNS_R_NCACHENXDOMAIN:
4088	case DNS_R_NXRRSET:
4089	case DNS_R_NCACHENXRRSET:
4090	case ISC_R_NOTFOUND:
4091		result = ISC_R_SUCCESS;
4092		break;
4093	case DNS_R_DELEGATION:
4094	case DNS_R_DUPLICATE:
4095	case DNS_R_DROP:
4096		break;
4097	case DNS_R_CNAME:
4098	case DNS_R_DNAME:
4099		rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, rpz_type,
4100			     name, "NS address rewrite rrset ", result);
4101		result = ISC_R_SUCCESS;
4102		break;
4103	default:
4104		if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
4105			client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR;
4106			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
4107				     name, "NS address rewrite rrset ", result);
4108		}
4109		break;
4110	}
4111	return (result);
4112}
4113
4114/*
4115 * Look for both A and AAAA rdatasets
4116 * and check for IP or NSIP rewrite policy rules.
4117 * Look only for addresses that will be in the ANSWER section
4118 * when checking for IP rules.
4119 */
4120static isc_result_t
4121rpz_rewrite_rrsets(ns_client_t *client, dns_rpz_type_t rpz_type,
4122		   dns_name_t *name, dns_rdatatype_t type,
4123		   dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
4124{
4125	dns_rpz_st_t *st;
4126	dns_dbversion_t *version;
4127	dns_db_t *ipdb;
4128	isc_result_t result;
4129
4130	st = client->query.rpz_st;
4131	version = NULL;
4132	ipdb = NULL;
4133	if ((st->state & DNS_RPZ_DONE_IPv4) == 0 &&
4134	    ((rpz_type == DNS_RPZ_TYPE_NSIP) ?
4135	     (st->state & DNS_RPZ_HAVE_NSIPv4) :
4136	     (st->state & DNS_RPZ_HAVE_IP)) != 0 &&
4137	    (type == dns_rdatatype_any || type == dns_rdatatype_a)) {
4138		result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_a,
4139					   name, &ipdb, version, rdatasetp,
4140					   resuming);
4141		if (result == ISC_R_SUCCESS)
4142			st->state |= DNS_RPZ_DONE_IPv4;
4143	} else {
4144		result = ISC_R_SUCCESS;
4145	}
4146	if (result == ISC_R_SUCCESS &&
4147	    ((rpz_type == DNS_RPZ_TYPE_NSIP) ?
4148	     (st->state & DNS_RPZ_HAVE_NSIPv6) :
4149	     (st->state & DNS_RPZ_HAVE_IP)) != 0 &&
4150	    (type == dns_rdatatype_any || type == dns_rdatatype_aaaa)) {
4151		result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_aaaa,
4152					   name, &ipdb, version, rdatasetp,
4153					   resuming);
4154	}
4155	if (ipdb != NULL)
4156		dns_db_detach(&ipdb);
4157	return (result);
4158}
4159
4160/*
4161 * Get the rrset from a response policy zone.
4162 */
4163static isc_result_t
4164rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
4165	 dns_name_t *sname, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
4166	 dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
4167	 dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
4168	 dns_rpz_policy_t *policyp)
4169{
4170	dns_rpz_policy_t policy;
4171	dns_fixedname_t fixed;
4172	dns_name_t *found;
4173	isc_result_t result;
4174	dns_clientinfomethods_t cm;
4175	dns_clientinfo_t ci;
4176
4177	dns_clientinfomethods_init(&cm, ns_client_sourceip);
4178	dns_clientinfo_init(&ci, client);
4179
4180	result = rpz_ready(client, zonep, dbp, nodep, rdatasetp);
4181	if (result != ISC_R_SUCCESS) {
4182		*policyp = DNS_RPZ_POLICY_ERROR;
4183		return (result);
4184	}
4185
4186	/*
4187	 * Try to get either a CNAME or the type of record demanded by the
4188	 * request from the policy zone.
4189	 */
4190	*versionp = NULL;
4191	result = rpz_getdb(client, rpz_type, qnamef, zonep, dbp, versionp);
4192	if (result != ISC_R_SUCCESS) {
4193		*policyp = DNS_RPZ_POLICY_MISS;
4194		return (DNS_R_NXDOMAIN);
4195	}
4196
4197	dns_fixedname_init(&fixed);
4198	found = dns_fixedname_name(&fixed);
4199	result = dns_db_findext(*dbp, qnamef, *versionp, dns_rdatatype_any, 0,
4200				client->now, nodep, found, &cm, &ci,
4201				*rdatasetp, NULL);
4202	if (result == ISC_R_SUCCESS) {
4203		dns_rdatasetiter_t *rdsiter;
4204
4205		rdsiter = NULL;
4206		result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0,
4207					     &rdsiter);
4208		if (result != ISC_R_SUCCESS) {
4209			dns_db_detachnode(*dbp, nodep);
4210			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
4211				     qnamef, "allrdatasets()", result);
4212			*policyp = DNS_RPZ_POLICY_ERROR;
4213			return (DNS_R_SERVFAIL);
4214		}
4215		for (result = dns_rdatasetiter_first(rdsiter);
4216		     result == ISC_R_SUCCESS;
4217		     result = dns_rdatasetiter_next(rdsiter)) {
4218			dns_rdatasetiter_current(rdsiter, *rdatasetp);
4219			if ((*rdatasetp)->type == dns_rdatatype_cname ||
4220			    (*rdatasetp)->type == qtype)
4221				break;
4222			dns_rdataset_disassociate(*rdatasetp);
4223		}
4224		dns_rdatasetiter_destroy(&rdsiter);
4225		if (result != ISC_R_SUCCESS) {
4226			if (result != ISC_R_NOMORE) {
4227				rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4228					     rpz_type, qnamef, "rdatasetiter",
4229					     result);
4230				*policyp = DNS_RPZ_POLICY_ERROR;
4231				return (DNS_R_SERVFAIL);
4232			}
4233			/*
4234			 * Ask again to get the right DNS_R_DNAME/NXRRSET/...
4235			 * result if there is neither a CNAME nor target type.
4236			 */
4237			if (dns_rdataset_isassociated(*rdatasetp))
4238				dns_rdataset_disassociate(*rdatasetp);
4239			dns_db_detachnode(*dbp, nodep);
4240
4241			if (qtype == dns_rdatatype_rrsig ||
4242			    qtype == dns_rdatatype_sig)
4243				result = DNS_R_NXRRSET;
4244			else
4245				result = dns_db_findext(*dbp, qnamef, *versionp,
4246							qtype, 0, client->now,
4247							nodep, found, &cm, &ci,
4248							*rdatasetp, NULL);
4249		}
4250	}
4251	switch (result) {
4252	case ISC_R_SUCCESS:
4253		if ((*rdatasetp)->type != dns_rdatatype_cname) {
4254			policy = DNS_RPZ_POLICY_RECORD;
4255		} else {
4256			policy = dns_rpz_decode_cname(rpz, *rdatasetp, sname);
4257			if ((policy == DNS_RPZ_POLICY_RECORD ||
4258			     policy == DNS_RPZ_POLICY_WILDCNAME) &&
4259			    qtype != dns_rdatatype_cname &&
4260			    qtype != dns_rdatatype_any)
4261				result = DNS_R_CNAME;
4262		}
4263		break;
4264	case DNS_R_DNAME:
4265		/*
4266		 * DNAME policy RRs have very few if any uses that are not
4267		 * better served with simple wildcards.  Making the work would
4268		 * require complications to get the number of labels matched
4269		 * in the name or the found name to the main DNS_R_DNAME case
4270		 * in query_find(). So fall through to treat them as NODATA.
4271		 */
4272	case DNS_R_NXRRSET:
4273		policy = DNS_RPZ_POLICY_NODATA;
4274		break;
4275	case DNS_R_NXDOMAIN:
4276	case DNS_R_EMPTYNAME:
4277		/*
4278		 * If we don't get a qname hit,
4279		 * see if it is worth looking for other types.
4280		 */
4281		dns_db_rpz_enabled(*dbp, client->query.rpz_st);
4282		dns_db_detach(dbp);
4283		dns_zone_detach(zonep);
4284		policy = DNS_RPZ_POLICY_MISS;
4285		break;
4286	default:
4287		dns_db_detach(dbp);
4288		dns_zone_detach(zonep);
4289		rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, qnamef,
4290			     "", result);
4291		policy = DNS_RPZ_POLICY_ERROR;
4292		result = DNS_R_SERVFAIL;
4293		break;
4294	}
4295
4296	*policyp = policy;
4297	return (result);
4298}
4299
4300/*
4301 * Build and look for a QNAME or NSDNAME owner name in a response policy zone.
4302 */
4303static isc_result_t
4304rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
4305		 dns_rpz_type_t rpz_type, dns_rdataset_t **rdatasetp)
4306{
4307	dns_rpz_st_t *st;
4308	dns_rpz_zone_t *rpz;
4309	dns_fixedname_t prefixf, rpz_qnamef;
4310	dns_name_t *prefix, *suffix, *rpz_qname;
4311	dns_zone_t *zone;
4312	dns_db_t *db;
4313	dns_dbversion_t *version;
4314	dns_dbnode_t *node;
4315	dns_rpz_policy_t policy;
4316	unsigned int labels;
4317	isc_result_t result;
4318
4319	st = client->query.rpz_st;
4320	zone = NULL;
4321	db = NULL;
4322	node = NULL;
4323
4324	for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
4325	     rpz != NULL;
4326	     rpz = ISC_LIST_NEXT(rpz, link)) {
4327		if (!RECURSIONOK(client) && rpz->recursive_only)
4328			continue;
4329
4330		/*
4331		 * Do not check policy zones that cannot replace a policy
4332		 * already known to match.
4333		 */
4334		if (st->m.policy != DNS_RPZ_POLICY_MISS) {
4335			if (st->m.rpz->num < rpz->num)
4336				break;
4337			if (st->m.rpz->num == rpz->num &&
4338			    st->m.type < rpz_type)
4339				continue;
4340		}
4341		/*
4342		 * Construct the policy's owner name.
4343		 */
4344		dns_fixedname_init(&prefixf);
4345		prefix = dns_fixedname_name(&prefixf);
4346		dns_name_split(qname, 1, prefix, NULL);
4347		if (rpz_type == DNS_RPZ_TYPE_NSDNAME)
4348			suffix = &rpz->nsdname;
4349		else
4350			suffix = &rpz->origin;
4351		dns_fixedname_init(&rpz_qnamef);
4352		rpz_qname = dns_fixedname_name(&rpz_qnamef);
4353		for (;;) {
4354			result = dns_name_concatenate(prefix, suffix,
4355						      rpz_qname, NULL);
4356			if (result == ISC_R_SUCCESS)
4357				break;
4358			INSIST(result == DNS_R_NAMETOOLONG);
4359			labels = dns_name_countlabels(prefix);
4360			if (labels < 2) {
4361				rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4362					     rpz_type, suffix,
4363					     "concatentate() ", result);
4364				return (ISC_R_SUCCESS);
4365			}
4366			if (labels+1 == dns_name_countlabels(qname)) {
4367				rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1,
4368					     rpz_type, suffix,
4369					     "concatentate() ", result);
4370			}
4371			dns_name_split(prefix, labels - 1, NULL, prefix);
4372		}
4373
4374		/*
4375		 * See if the policy record exists and get its policy.
4376		 */
4377		result = rpz_find(client, qtype, rpz_qname, qname, rpz,
4378				  rpz_type, &zone, &db, &version, &node,
4379				  rdatasetp, &policy);
4380		switch (result) {
4381		case DNS_R_NXDOMAIN:
4382		case DNS_R_EMPTYNAME:
4383			break;
4384		case DNS_R_SERVFAIL:
4385			rpz_clean(&zone, &db, &node, rdatasetp);
4386			st->m.policy = DNS_RPZ_POLICY_ERROR;
4387			return (DNS_R_SERVFAIL);
4388		default:
4389			/*
4390			 * We are dealing with names here.
4391			 * With more than one applicable policy, prefer
4392			 * the earliest configured policy,
4393			 * QNAME over IP over NSDNAME over NSIP,
4394			 * and the smallest name.
4395			 * Because of the testing above,
4396			 * we known st->m.rpz->num >= rpz->num  and either
4397			 * st->m.rpz->num > rpz->num or st->m.type >= rpz_type
4398			 */
4399			if (st->m.policy != DNS_RPZ_POLICY_MISS &&
4400			    rpz->num == st->m.rpz->num &&
4401			    (st->m.type < rpz_type ||
4402			     (st->m.type == rpz_type &&
4403			      0 >= dns_name_compare(rpz_qname, st->qname))))
4404				continue;
4405
4406			/*
4407			 * Merely log DNS_RPZ_POLICY_DISABLED hits.
4408			 */
4409			if (rpz->policy == DNS_RPZ_POLICY_DISABLED) {
4410				rpz_log_rewrite(client, "disabled ",
4411						policy, rpz_type, rpz_qname);
4412				continue;
4413			}
4414
4415			rpz_match_clear(st);
4416			st->m.rpz = rpz;
4417			st->m.type = rpz_type;
4418			st->m.prefix = 0;
4419			st->m.policy = policy;
4420			st->m.result = result;
4421			dns_name_copy(rpz_qname, st->qname, NULL);
4422			if (*rdatasetp != NULL &&
4423			    dns_rdataset_isassociated(*rdatasetp)) {
4424				dns_rdataset_t *trdataset;
4425
4426				trdataset = st->m.rdataset;
4427				st->m.rdataset = *rdatasetp;
4428				*rdatasetp = trdataset;
4429				st->m.ttl = ISC_MIN(st->m.rdataset->ttl,
4430						    rpz->max_policy_ttl);
4431			} else {
4432				st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT,
4433						    rpz->max_policy_ttl);
4434			}
4435			st->m.node = node;
4436			node = NULL;
4437			st->m.db = db;
4438			db = NULL;
4439			st->m.version = version;
4440			st->m.zone = zone;
4441			zone = NULL;
4442		}
4443	}
4444
4445	rpz_clean(&zone, &db, &node, rdatasetp);
4446	return (ISC_R_SUCCESS);
4447}
4448
4449static void
4450rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname,
4451		    isc_result_t result, int level, const char *str)
4452{
4453	dns_rpz_st_t *st;
4454
4455	st = client->query.rpz_st;
4456
4457	if (str != NULL)
4458		rpz_log_fail(client, level, DNS_RPZ_TYPE_NSIP, nsname,
4459			     str, result);
4460	if (st->r.ns_rdataset != NULL &&
4461	    dns_rdataset_isassociated(st->r.ns_rdataset))
4462		dns_rdataset_disassociate(st->r.ns_rdataset);
4463
4464	st->r.label--;
4465}
4466
4467/*
4468 * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting.
4469 */
4470static isc_result_t
4471rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult,
4472	    isc_boolean_t resuming)
4473{
4474	dns_rpz_st_t *st;
4475	dns_rdataset_t *rdataset;
4476	dns_fixedname_t nsnamef;
4477	dns_name_t *nsname;
4478	isc_boolean_t ck_ip;
4479	isc_result_t result;
4480
4481	st = client->query.rpz_st;
4482	if (st == NULL) {
4483		st = isc_mem_get(client->mctx, sizeof(*st));
4484		if (st == NULL)
4485			return (ISC_R_NOMEMORY);
4486		st->state = 0;
4487		memset(&st->m, 0, sizeof(st->m));
4488		st->m.type = DNS_RPZ_TYPE_BAD;
4489		st->m.policy = DNS_RPZ_POLICY_MISS;
4490		memset(&st->r, 0, sizeof(st->r));
4491		memset(&st->q, 0, sizeof(st->q));
4492		dns_fixedname_init(&st->_qnamef);
4493		dns_fixedname_init(&st->_r_namef);
4494		dns_fixedname_init(&st->_fnamef);
4495		st->qname = dns_fixedname_name(&st->_qnamef);
4496		st->r_name = dns_fixedname_name(&st->_r_namef);
4497		st->fname = dns_fixedname_name(&st->_fnamef);
4498		client->query.rpz_st = st;
4499	}
4500
4501	/*
4502	 * There is nothing to rewrite if the main query failed.
4503	 */
4504	switch (qresult) {
4505	case ISC_R_SUCCESS:
4506	case DNS_R_GLUE:
4507	case DNS_R_ZONECUT:
4508		ck_ip = ISC_TRUE;
4509		break;
4510	case DNS_R_EMPTYNAME:
4511	case DNS_R_NXRRSET:
4512	case DNS_R_NXDOMAIN:
4513	case DNS_R_EMPTYWILD:
4514	case DNS_R_NCACHENXDOMAIN:
4515	case DNS_R_NCACHENXRRSET:
4516	case DNS_R_CNAME:
4517	case DNS_R_DNAME:
4518		ck_ip = ISC_FALSE;
4519		break;
4520	case DNS_R_DELEGATION:
4521	case ISC_R_NOTFOUND:
4522		return (ISC_R_SUCCESS);
4523	case ISC_R_FAILURE:
4524	case ISC_R_TIMEDOUT:
4525	case DNS_R_BROKENCHAIN:
4526		rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, DNS_RPZ_TYPE_QNAME,
4527			     client->query.qname,
4528			     "stop on qresult in rpz_rewrite()",
4529			     qresult);
4530		return (ISC_R_SUCCESS);
4531	default:
4532		rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, DNS_RPZ_TYPE_QNAME,
4533			     client->query.qname,
4534			     "stop on unrecognized qresult in rpz_rewrite()",
4535			     qresult);
4536		return (ISC_R_SUCCESS);
4537	}
4538
4539	rdataset = NULL;
4540	if ((st->state & DNS_RPZ_DONE_QNAME) == 0) {
4541		/*
4542		 * Check rules for the query name if this it the first time
4543		 * for the current qname, i.e. we've not been recursing.
4544		 * There is a first time for each name in a CNAME chain.
4545		 */
4546		result = rpz_rewrite_name(client, qtype, client->query.qname,
4547					  DNS_RPZ_TYPE_QNAME, &rdataset);
4548		if (result != ISC_R_SUCCESS)
4549			goto cleanup;
4550
4551		st->r.label = dns_name_countlabels(client->query.qname);
4552
4553		st->state &= ~(DNS_RPZ_DONE_QNAME_IP | DNS_RPZ_DONE_IPv4);
4554		st->state |= DNS_RPZ_DONE_QNAME;
4555	}
4556
4557	/*
4558	 * Check known IP addresses for the query name.
4559	 * Any recursion required for the query has already happened.
4560	 * Do not check addresses that will not be in the ANSWER section.
4561	 */
4562	if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 &&
4563	    (st->state & DNS_RPZ_HAVE_IP) != 0 && ck_ip) {
4564		result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_IP,
4565					    client->query.qname, qtype,
4566					    &rdataset, resuming);
4567		if (result != ISC_R_SUCCESS)
4568			goto cleanup;
4569		st->state &= ~DNS_RPZ_DONE_IPv4;
4570		st->state |= DNS_RPZ_DONE_QNAME_IP;
4571	}
4572
4573	/*
4574	 * Stop looking for rules if there are none of the other kinds.
4575	 */
4576	if ((st->state & (DNS_RPZ_HAVE_NSIPv4 | DNS_RPZ_HAVE_NSIPv6 |
4577			  DNS_RPZ_HAVE_NSDNAME)) == 0) {
4578		result = ISC_R_SUCCESS;
4579		goto cleanup;
4580	}
4581
4582	dns_fixedname_init(&nsnamef);
4583	dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef));
4584	while (st->r.label > 1) {
4585		/*
4586		 * Get NS rrset for each domain in the current qname.
4587		 */
4588		if (st->r.label == dns_name_countlabels(client->query.qname)) {
4589			nsname = client->query.qname;
4590		} else {
4591			nsname = dns_fixedname_name(&nsnamef);
4592			dns_name_split(client->query.qname, st->r.label,
4593				       NULL, nsname);
4594		}
4595		if (st->r.ns_rdataset == NULL ||
4596		    !dns_rdataset_isassociated(st->r.ns_rdataset)) {
4597			dns_db_t *db = NULL;
4598			result = rpz_rrset_find(client, DNS_RPZ_TYPE_NSDNAME,
4599						nsname, dns_rdatatype_ns,
4600						&db, NULL, &st->r.ns_rdataset,
4601						resuming);
4602			if (db != NULL)
4603				dns_db_detach(&db);
4604			if (st->m.policy == DNS_RPZ_POLICY_ERROR)
4605				goto cleanup;
4606			switch (result) {
4607			case ISC_R_SUCCESS:
4608				result = dns_rdataset_first(st->r.ns_rdataset);
4609				if (result != ISC_R_SUCCESS)
4610					goto cleanup;
4611				st->state &= ~(DNS_RPZ_DONE_NSDNAME |
4612					       DNS_RPZ_DONE_IPv4);
4613				break;
4614			case DNS_R_DELEGATION:
4615				goto cleanup;
4616			case DNS_R_EMPTYNAME:
4617			case DNS_R_NXRRSET:
4618			case DNS_R_EMPTYWILD:
4619			case DNS_R_NXDOMAIN:
4620			case DNS_R_NCACHENXDOMAIN:
4621			case DNS_R_NCACHENXRRSET:
4622			case ISC_R_NOTFOUND:
4623			case DNS_R_CNAME:
4624			case DNS_R_DNAME:
4625				rpz_rewrite_ns_skip(client, nsname, result,
4626						    0, NULL);
4627				continue;
4628			case ISC_R_TIMEDOUT:
4629			case DNS_R_BROKENCHAIN:
4630			case ISC_R_FAILURE:
4631				rpz_rewrite_ns_skip(client, nsname, result,
4632						DNS_RPZ_DEBUG_LEVEL3,
4633						"NS db_find() ");
4634				continue;
4635			default:
4636				rpz_rewrite_ns_skip(client, nsname, result,
4637						DNS_RPZ_INFO_LEVEL,
4638						"unrecognized NS db_find() ");
4639				continue;
4640			}
4641		}
4642		/*
4643		 * Check all NS names.
4644		 */
4645		do {
4646			dns_rdata_ns_t ns;
4647			dns_rdata_t nsrdata = DNS_RDATA_INIT;
4648
4649			dns_rdataset_current(st->r.ns_rdataset, &nsrdata);
4650			result = dns_rdata_tostruct(&nsrdata, &ns, NULL);
4651			dns_rdata_reset(&nsrdata);
4652			if (result != ISC_R_SUCCESS) {
4653				rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4654					     DNS_RPZ_TYPE_NSIP, nsname,
4655					     "rdata_tostruct() ", result);
4656				st->m.policy = DNS_RPZ_POLICY_ERROR;
4657				goto cleanup;
4658			}
4659			/*
4660			 * Do nothing about "NS ."
4661			 */
4662			if (dns_name_equal(&ns.name, dns_rootname)) {
4663				dns_rdata_freestruct(&ns);
4664				result = dns_rdataset_next(st->r.ns_rdataset);
4665				continue;
4666			}
4667			/*
4668			 * Check this NS name if we did not handle it
4669			 * during a previous recursion.
4670			 */
4671			if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0 &&
4672			    (st->state & DNS_RPZ_HAVE_NSDNAME) != 0) {
4673				result = rpz_rewrite_name(client, qtype,
4674							&ns.name,
4675							DNS_RPZ_TYPE_NSDNAME,
4676							&rdataset);
4677				if (result != ISC_R_SUCCESS) {
4678					dns_rdata_freestruct(&ns);
4679					goto cleanup;
4680				}
4681				st->state |= DNS_RPZ_DONE_NSDNAME;
4682			}
4683			/*
4684			 * Check all IP addresses for this NS name.
4685			 */
4686			result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_NSIP,
4687						    &ns.name, dns_rdatatype_any,
4688						    &rdataset, resuming);
4689			dns_rdata_freestruct(&ns);
4690			if (result != ISC_R_SUCCESS)
4691				goto cleanup;
4692			st->state &= ~(DNS_RPZ_DONE_NSDNAME |
4693				       DNS_RPZ_DONE_IPv4);
4694			result = dns_rdataset_next(st->r.ns_rdataset);
4695		} while (result == ISC_R_SUCCESS);
4696		dns_rdataset_disassociate(st->r.ns_rdataset);
4697		st->r.label--;
4698	}
4699
4700	/*
4701	 * Use the best, if any, hit.
4702	 */
4703	result = ISC_R_SUCCESS;
4704
4705cleanup:
4706	if (st->m.policy != DNS_RPZ_POLICY_MISS &&
4707	    st->m.policy != DNS_RPZ_POLICY_ERROR &&
4708	    st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN)
4709		st->m.policy = st->m.rpz->policy;
4710	if (st->m.policy == DNS_RPZ_POLICY_MISS ||
4711	    st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
4712	    st->m.policy == DNS_RPZ_POLICY_ERROR) {
4713		if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
4714		    result != DNS_R_DELEGATION)
4715			rpz_log_rewrite(client, "", st->m.policy, st->m.type,
4716					st->qname);
4717		rpz_match_clear(st);
4718	}
4719	if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
4720		st->m.type = DNS_RPZ_TYPE_BAD;
4721		result = DNS_R_SERVFAIL;
4722	}
4723	query_putrdataset(client, &rdataset);
4724	if ((st->state & DNS_RPZ_RECURSING) == 0)
4725		rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset);
4726
4727	return (result);
4728}
4729
4730/*
4731 * See if response policy zone rewriting is allowed a lack of interest
4732 * by the client in DNSSEC or a lack of signatures.
4733 */
4734static isc_boolean_t
4735rpz_ck_dnssec(ns_client_t *client, isc_result_t result,
4736	      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
4737{
4738	dns_fixedname_t fixed;
4739	dns_name_t *found;
4740	dns_rdataset_t trdataset;
4741	dns_rdatatype_t type;
4742
4743	if (client->view->rpz_break_dnssec)
4744		return (ISC_TRUE);
4745	/*
4746	 * sigrdataset == NULL if and only !WANTDNSSEC(client)
4747	 */
4748	if (sigrdataset == NULL)
4749		return (ISC_TRUE);
4750	if (dns_rdataset_isassociated(sigrdataset))
4751		return (ISC_FALSE);
4752
4753	/*
4754	 * We are happy to rewrite nothing.
4755	 */
4756	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset))
4757		return (ISC_TRUE);
4758	/*
4759	 * Do not rewrite if there is any sign of signatures.
4760	 */
4761	if (rdataset->type == dns_rdatatype_nsec ||
4762	    rdataset->type == dns_rdatatype_nsec3 ||
4763	    rdataset->type == dns_rdatatype_rrsig)
4764		return (ISC_FALSE);
4765
4766	/*
4767	 * Look for a signature in a negative cache rdataset.
4768	 */
4769	if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0)
4770		return (ISC_TRUE);
4771	dns_fixedname_init(&fixed);
4772	found = dns_fixedname_name(&fixed);
4773	dns_rdataset_init(&trdataset);
4774	for (result = dns_rdataset_first(rdataset);
4775	     result == ISC_R_SUCCESS;
4776	     result = dns_rdataset_next(rdataset)) {
4777		dns_ncache_current(rdataset, found, &trdataset);
4778		type = trdataset.type;
4779		dns_rdataset_disassociate(&trdataset);
4780		if (type == dns_rdatatype_nsec ||
4781		    type == dns_rdatatype_nsec3 ||
4782		    type == dns_rdatatype_rrsig)
4783			return (ISC_FALSE);
4784	}
4785	return (ISC_TRUE);
4786}
4787
4788/*
4789 * Add a CNAME to the query response, including translating foo.evil.com and
4790 *	*.evil.com CNAME *.example.com
4791 * to
4792 *	foo.evil.com CNAME foo.evil.com.example.com
4793 */
4794static isc_result_t
4795rpz_add_cname(ns_client_t *client, dns_rpz_st_t *st,
4796	      dns_name_t *cname, dns_name_t *fname, isc_buffer_t *dbuf)
4797{
4798	dns_fixedname_t prefix, suffix;
4799	unsigned int labels;
4800	isc_result_t result;
4801
4802	labels = dns_name_countlabels(cname);
4803	if (labels > 2 && dns_name_iswildcard(cname)) {
4804		dns_fixedname_init(&prefix);
4805		dns_name_split(client->query.qname, 1,
4806			       dns_fixedname_name(&prefix), NULL);
4807		dns_fixedname_init(&suffix);
4808		dns_name_split(cname, labels-1,
4809			       NULL, dns_fixedname_name(&suffix));
4810		result = dns_name_concatenate(dns_fixedname_name(&prefix),
4811					      dns_fixedname_name(&suffix),
4812					      fname, NULL);
4813		if (result == DNS_R_NAMETOOLONG)
4814			client->message->rcode = dns_rcode_yxdomain;
4815	} else {
4816		result = dns_name_copy(cname, fname, NULL);
4817		RUNTIME_CHECK(result == ISC_R_SUCCESS);
4818	}
4819	if (result != ISC_R_SUCCESS)
4820		return (result);
4821	query_keepname(client, fname, dbuf);
4822	result = query_add_cname(client, client->query.qname,
4823				 fname, dns_trust_authanswer, st->m.ttl);
4824	if (result != ISC_R_SUCCESS)
4825		return (result);
4826	rpz_log_rewrite(client, "", st->m.policy, st->m.type, st->qname);
4827	ns_client_qnamereplace(client, fname);
4828	/*
4829	 * Turn off DNSSEC because the results of a
4830	 * response policy zone cannot verify.
4831	 */
4832	client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
4833				DNS_MESSAGEFLAG_AD);
4834	return (ISC_R_SUCCESS);
4835}
4836
4837#define MAX_RESTARTS 16
4838
4839#define QUERY_ERROR(r) \
4840do { \
4841	eresult = r; \
4842	want_restart = ISC_FALSE; \
4843	line = __LINE__; \
4844} while (/*CONSTCOND*/0)
4845
4846#define RECURSE_ERROR(r) \
4847do { \
4848	if ((r) == DNS_R_DUPLICATE || (r) == DNS_R_DROP) \
4849		QUERY_ERROR(r); \
4850	else \
4851		QUERY_ERROR(DNS_R_SERVFAIL); \
4852} while (/*CONSTCOND*/0)
4853
4854/*
4855 * Extract a network address from the RDATA of an A or AAAA
4856 * record.
4857 *
4858 * Returns:
4859 *	ISC_R_SUCCESS
4860 *	ISC_R_NOTIMPLEMENTED	The rdata is not a known address type.
4861 */
4862static isc_result_t
4863rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
4864	struct in_addr ina;
4865	struct in6_addr in6a;
4866
4867	switch (rdata->type) {
4868	case dns_rdatatype_a:
4869		INSIST(rdata->length == 4);
4870		memcpy(&ina.s_addr, rdata->data, 4);
4871		isc_netaddr_fromin(netaddr, &ina);
4872		return (ISC_R_SUCCESS);
4873	case dns_rdatatype_aaaa:
4874		INSIST(rdata->length == 16);
4875		memcpy(in6a.s6_addr, rdata->data, 16);
4876		isc_netaddr_fromin6(netaddr, &in6a);
4877		return (ISC_R_SUCCESS);
4878	default:
4879		return (ISC_R_NOTIMPLEMENTED);
4880	}
4881}
4882
4883/*
4884 * Find the sort order of 'rdata' in the topology-like
4885 * ACL forming the second element in a 2-element top-level
4886 * sortlist statement.
4887 */
4888static int
4889query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) {
4890	isc_netaddr_t netaddr;
4891
4892	if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
4893		return (INT_MAX);
4894	return (ns_sortlist_addrorder2(&netaddr, arg));
4895}
4896
4897/*
4898 * Find the sort order of 'rdata' in the matching element
4899 * of a 1-element top-level sortlist statement.
4900 */
4901static int
4902query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) {
4903	isc_netaddr_t netaddr;
4904
4905	if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
4906		return (INT_MAX);
4907	return (ns_sortlist_addrorder1(&netaddr, arg));
4908}
4909
4910/*
4911 * Find the sortlist statement that applies to 'client' and set up
4912 * the sortlist info in in client->message appropriately.
4913 */
4914static void
4915setup_query_sortlist(ns_client_t *client) {
4916	isc_netaddr_t netaddr;
4917	dns_rdatasetorderfunc_t order = NULL;
4918	const void *order_arg = NULL;
4919
4920	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
4921	switch (ns_sortlist_setup(client->view->sortlist,
4922			       &netaddr, &order_arg)) {
4923	case NS_SORTLISTTYPE_1ELEMENT:
4924		order = query_sortlist_order_1element;
4925		break;
4926	case NS_SORTLISTTYPE_2ELEMENT:
4927		order = query_sortlist_order_2element;
4928		break;
4929	case NS_SORTLISTTYPE_NONE:
4930		order = NULL;
4931		break;
4932	default:
4933		INSIST(0);
4934		break;
4935	}
4936	dns_message_setsortorder(client->message, order, order_arg);
4937}
4938
4939static void
4940query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
4941	isc_buffer_t *dbuf, b;
4942	dns_name_t *fname;
4943	dns_rdataset_t *neg, *negsig;
4944	isc_result_t result = ISC_R_NOMEMORY;
4945
4946	CTRACE("query_addnoqnameproof");
4947
4948	fname = NULL;
4949	neg = NULL;
4950	negsig = NULL;
4951
4952	dbuf = query_getnamebuf(client);
4953	if (dbuf == NULL)
4954		goto cleanup;
4955	fname = query_newname(client, dbuf, &b);
4956	neg = query_newrdataset(client);
4957	negsig = query_newrdataset(client);
4958	if (fname == NULL || neg == NULL || negsig == NULL)
4959		goto cleanup;
4960
4961	result = dns_rdataset_getnoqname(rdataset, fname, neg, negsig);
4962	RUNTIME_CHECK(result == ISC_R_SUCCESS);
4963
4964	query_addrrset(client, &fname, &neg, &negsig, dbuf,
4965		       DNS_SECTION_AUTHORITY);
4966
4967	if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) == 0)
4968		goto cleanup;
4969
4970	if (fname == NULL) {
4971		dbuf = query_getnamebuf(client);
4972		if (dbuf == NULL)
4973			goto cleanup;
4974		fname = query_newname(client, dbuf, &b);
4975	}
4976	if (neg == NULL)
4977		neg = query_newrdataset(client);
4978	else if (dns_rdataset_isassociated(neg))
4979		dns_rdataset_disassociate(neg);
4980	if (negsig == NULL)
4981		negsig = query_newrdataset(client);
4982	else if (dns_rdataset_isassociated(negsig))
4983		dns_rdataset_disassociate(negsig);
4984	if (fname == NULL || neg == NULL || negsig == NULL)
4985		goto cleanup;
4986	result = dns_rdataset_getclosest(rdataset, fname, neg, negsig);
4987	RUNTIME_CHECK(result == ISC_R_SUCCESS);
4988
4989	query_addrrset(client, &fname, &neg, &negsig, dbuf,
4990		       DNS_SECTION_AUTHORITY);
4991
4992 cleanup:
4993	if (neg != NULL)
4994		query_putrdataset(client, &neg);
4995	if (negsig != NULL)
4996		query_putrdataset(client, &negsig);
4997	if (fname != NULL)
4998		query_releasename(client, &fname);
4999}
5000
5001static inline void
5002answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
5003	dns_name_t *name;
5004	dns_message_t *msg;
5005	dns_section_t section = DNS_SECTION_ADDITIONAL;
5006	dns_rdataset_t *rdataset = NULL;
5007
5008	msg = client->message;
5009	for (name = ISC_LIST_HEAD(msg->sections[section]);
5010	     name != NULL;
5011	     name = ISC_LIST_NEXT(name, link))
5012		if (dns_name_equal(name, client->query.qname)) {
5013			for (rdataset = ISC_LIST_HEAD(name->list);
5014			     rdataset != NULL;
5015			     rdataset = ISC_LIST_NEXT(rdataset, link))
5016				if (rdataset->type == qtype)
5017					break;
5018			break;
5019		}
5020	if (rdataset != NULL) {
5021		ISC_LIST_UNLINK(msg->sections[section], name, link);
5022		ISC_LIST_PREPEND(msg->sections[section], name, link);
5023		ISC_LIST_UNLINK(name->list, rdataset, link);
5024		ISC_LIST_PREPEND(name->list, rdataset, link);
5025		rdataset->attributes |= DNS_RDATASETATTR_REQUIREDGLUE;
5026	}
5027}
5028
5029#define NS_NAME_INIT(A,B) \
5030	 { \
5031		DNS_NAME_MAGIC, \
5032		A, sizeof(A), sizeof(B), \
5033		DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
5034		B, NULL, { (void *)-1, (void *)-1}, \
5035		{NULL, NULL} \
5036	}
5037
5038static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
5039static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
5040static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
5041
5042static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
5043
5044static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
5045static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
5046static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
5047static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
5048static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
5049static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
5050static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
5051static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
5052static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
5053static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
5054static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
5055static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
5056static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
5057static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
5058static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
5059static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
5060
5061static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
5062
5063static dns_name_t rfc1918names[] = {
5064	NS_NAME_INIT(inaddr10, inaddr10_offsets),
5065	NS_NAME_INIT(inaddr16172, inaddr172_offsets),
5066	NS_NAME_INIT(inaddr17172, inaddr172_offsets),
5067	NS_NAME_INIT(inaddr18172, inaddr172_offsets),
5068	NS_NAME_INIT(inaddr19172, inaddr172_offsets),
5069	NS_NAME_INIT(inaddr20172, inaddr172_offsets),
5070	NS_NAME_INIT(inaddr21172, inaddr172_offsets),
5071	NS_NAME_INIT(inaddr22172, inaddr172_offsets),
5072	NS_NAME_INIT(inaddr23172, inaddr172_offsets),
5073	NS_NAME_INIT(inaddr24172, inaddr172_offsets),
5074	NS_NAME_INIT(inaddr25172, inaddr172_offsets),
5075	NS_NAME_INIT(inaddr26172, inaddr172_offsets),
5076	NS_NAME_INIT(inaddr27172, inaddr172_offsets),
5077	NS_NAME_INIT(inaddr28172, inaddr172_offsets),
5078	NS_NAME_INIT(inaddr29172, inaddr172_offsets),
5079	NS_NAME_INIT(inaddr30172, inaddr172_offsets),
5080	NS_NAME_INIT(inaddr31172, inaddr172_offsets),
5081	NS_NAME_INIT(inaddr168192, inaddr192_offsets)
5082};
5083
5084
5085static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
5086static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org";
5087
5088static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
5089static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
5090
5091static dns_name_t prisoner = NS_NAME_INIT(prisoner_data, prisoner_offsets);
5092static dns_name_t hostmaster = NS_NAME_INIT(hostmaster_data, hostmaster_offsets);
5093
5094static void
5095warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
5096	unsigned int i;
5097	dns_rdata_t rdata = DNS_RDATA_INIT;
5098	dns_rdata_soa_t soa;
5099	dns_rdataset_t found;
5100	isc_result_t result;
5101
5102	for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) {
5103		if (dns_name_issubdomain(fname, &rfc1918names[i])) {
5104			dns_rdataset_init(&found);
5105			result = dns_ncache_getrdataset(rdataset,
5106							&rfc1918names[i],
5107							dns_rdatatype_soa,
5108							&found);
5109			if (result != ISC_R_SUCCESS)
5110				return;
5111
5112			result = dns_rdataset_first(&found);
5113			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5114			dns_rdataset_current(&found, &rdata);
5115			result = dns_rdata_tostruct(&rdata, &soa, NULL);
5116			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5117			if (dns_name_equal(&soa.origin, &prisoner) &&
5118			    dns_name_equal(&soa.contact, &hostmaster)) {
5119				char buf[DNS_NAME_FORMATSIZE];
5120				dns_name_format(fname, buf, sizeof(buf));
5121				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
5122					      NS_LOGMODULE_QUERY,
5123					      ISC_LOG_WARNING,
5124					      "RFC 1918 response from "
5125					      "Internet for %s", buf);
5126			}
5127			dns_rdataset_disassociate(&found);
5128			return;
5129		}
5130	}
5131}
5132
5133static void
5134query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
5135		       dns_dbversion_t *version, ns_client_t *client,
5136		       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
5137		       dns_name_t *fname, isc_boolean_t exact,
5138		       dns_name_t *found)
5139{
5140	unsigned char salt[256];
5141	size_t salt_length;
5142	isc_uint16_t iterations;
5143	isc_result_t result;
5144	unsigned int dboptions;
5145	dns_fixedname_t fixed;
5146	dns_hash_t hash;
5147	dns_name_t name;
5148	unsigned int skip = 0, labels;
5149	dns_rdata_nsec3_t nsec3;
5150	dns_rdata_t rdata = DNS_RDATA_INIT;
5151	isc_boolean_t optout;
5152	dns_clientinfomethods_t cm;
5153	dns_clientinfo_t ci;
5154
5155	salt_length = sizeof(salt);
5156	result = dns_db_getnsec3parameters(db, version, &hash, NULL,
5157					   &iterations, salt, &salt_length);
5158	if (result != ISC_R_SUCCESS)
5159		return;
5160
5161	dns_name_init(&name, NULL);
5162	dns_name_clone(qname, &name);
5163	labels = dns_name_countlabels(&name);
5164	dns_clientinfomethods_init(&cm, ns_client_sourceip);
5165	dns_clientinfo_init(&ci, client);
5166
5167	/*
5168	 * Map unknown algorithm to known value.
5169	 */
5170	if (hash == DNS_NSEC3_UNKNOWNALG)
5171		hash = 1;
5172
5173 again:
5174	dns_fixedname_init(&fixed);
5175	result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
5176				    dns_db_origin(db), hash,
5177				    iterations, salt, salt_length);
5178	if (result != ISC_R_SUCCESS)
5179		return;
5180
5181	dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
5182	result = dns_db_findext(db, dns_fixedname_name(&fixed), version,
5183				dns_rdatatype_nsec3, dboptions, client->now,
5184				NULL, fname, &cm, &ci, rdataset, sigrdataset);
5185
5186	if (result == DNS_R_NXDOMAIN) {
5187		if (!dns_rdataset_isassociated(rdataset)) {
5188			return;
5189		}
5190		result = dns_rdataset_first(rdataset);
5191		INSIST(result == ISC_R_SUCCESS);
5192		dns_rdataset_current(rdataset, &rdata);
5193		dns_rdata_tostruct(&rdata, &nsec3, NULL);
5194		dns_rdata_reset(&rdata);
5195		optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
5196		if (found != NULL && optout &&
5197		    dns_name_issubdomain(&name, dns_db_origin(db)))
5198		{
5199			dns_rdataset_disassociate(rdataset);
5200			if (dns_rdataset_isassociated(sigrdataset))
5201				dns_rdataset_disassociate(sigrdataset);
5202			skip++;
5203			dns_name_getlabelsequence(qname, skip, labels - skip,
5204			                          &name);
5205			ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
5206				      NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3),
5207				      "looking for closest provable encloser");
5208			goto again;
5209		}
5210		if (exact)
5211			ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
5212				      NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
5213				      "expected a exact match NSEC3, got "
5214				      "a covering record");
5215
5216	} else if (result != ISC_R_SUCCESS) {
5217		return;
5218	} else if (!exact)
5219		ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
5220			      NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
5221			      "expected covering NSEC3, got an exact match");
5222	if (found == qname) {
5223		if (skip != 0U)
5224			dns_name_getlabelsequence(qname, skip, labels - skip,
5225			                          found);
5226	} else if (found != NULL)
5227		dns_name_copy(&name, found, NULL);
5228	return;
5229}
5230
5231#ifdef ALLOW_FILTER_AAAA_ON_V4
5232static isc_boolean_t
5233is_v4_client(ns_client_t *client) {
5234	if (isc_sockaddr_pf(&client->peeraddr) == AF_INET)
5235		return (ISC_TRUE);
5236	if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
5237	    IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
5238		return (ISC_TRUE);
5239	return (ISC_FALSE);
5240}
5241#endif
5242
5243static isc_uint32_t
5244dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
5245	dns_dbnode_t *node = NULL;
5246	dns_rdata_soa_t soa;
5247	dns_rdata_t rdata = DNS_RDATA_INIT;
5248	dns_rdataset_t rdataset;
5249	isc_result_t result;
5250	isc_uint32_t ttl = ISC_UINT32_MAX;
5251
5252	dns_rdataset_init(&rdataset);
5253
5254	result = dns_db_getoriginnode(db, &node);
5255	if (result != ISC_R_SUCCESS)
5256		goto cleanup;
5257
5258	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5259				     0, 0, &rdataset, NULL);
5260	if (result != ISC_R_SUCCESS)
5261		goto cleanup;
5262	result = dns_rdataset_first(&rdataset);
5263	if (result != ISC_R_SUCCESS)
5264		goto cleanup;
5265
5266	dns_rdataset_current(&rdataset, &rdata);
5267	result = dns_rdata_tostruct(&rdata, &soa, NULL);
5268	RUNTIME_CHECK(result == ISC_R_SUCCESS);
5269	ttl = ISC_MIN(rdataset.ttl, soa.minimum);
5270
5271cleanup:
5272	if (dns_rdataset_isassociated(&rdataset))
5273		dns_rdataset_disassociate(&rdataset);
5274	if (node != NULL)
5275		dns_db_detachnode(db, &node);
5276	return (ttl);
5277}
5278
5279static isc_boolean_t
5280dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
5281	     dns_rdataset_t *sigrdataset)
5282{
5283	isc_netaddr_t netaddr;
5284	dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
5285	unsigned int flags = 0;
5286	unsigned int i, count;
5287	isc_boolean_t *aaaaok;
5288
5289	INSIST(client->query.dns64_aaaaok == NULL);
5290	INSIST(client->query.dns64_aaaaoklen == 0);
5291	INSIST(client->query.dns64_aaaa == NULL);
5292	INSIST(client->query.dns64_sigaaaa == NULL);
5293
5294	if (dns64 == NULL)
5295		return (ISC_TRUE);
5296
5297	if (RECURSIONOK(client))
5298		flags |= DNS_DNS64_RECURSIVE;
5299
5300	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
5301		flags |= DNS_DNS64_DNSSEC;
5302
5303	count = dns_rdataset_count(rdataset);
5304	aaaaok = isc_mem_get(client->mctx, sizeof(isc_boolean_t) * count);
5305
5306	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
5307	if (dns_dns64_aaaaok(dns64, &netaddr, client->signer,
5308			     &ns_g_server->aclenv, flags, rdataset,
5309			     aaaaok, count)) {
5310		for (i = 0; i < count; i++) {
5311			if (aaaaok != NULL && !aaaaok[i]) {
5312				client->query.dns64_aaaaok = aaaaok;
5313				client->query.dns64_aaaaoklen = count;
5314				break;
5315			}
5316		}
5317		if (i == count && aaaaok != NULL)
5318			isc_mem_put(client->mctx, aaaaok,
5319				    sizeof(isc_boolean_t) * count);
5320		return (ISC_TRUE);
5321	}
5322	if (aaaaok != NULL)
5323		isc_mem_put(client->mctx, aaaaok,
5324			    sizeof(isc_boolean_t) * count);
5325	return (ISC_FALSE);
5326}
5327
5328/*
5329 * Look for the name and type in the redirection zone.  If found update
5330 * the arguments as appropriate.  Return ISC_TRUE if a update was
5331 * performed.
5332 *
5333 * Only perform the update if the client is in the allow query acl and
5334 * returning the update would not cause a DNSSEC validation failure.
5335 */
5336static isc_boolean_t
5337redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
5338	 dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
5339	 dns_rdatatype_t qtype)
5340{
5341	dns_db_t *db = NULL;
5342	dns_dbnode_t *node = NULL;
5343	dns_fixedname_t fixed;
5344	dns_name_t *found;
5345	dns_rdataset_t trdataset;
5346	isc_result_t result;
5347	dns_rdatatype_t type;
5348	dns_clientinfomethods_t cm;
5349	dns_clientinfo_t ci;
5350	ns_dbversion_t *dbversion;
5351
5352	CTRACE("redirect");
5353
5354	if (client->view->redirect == NULL)
5355		return (ISC_FALSE);
5356
5357	dns_fixedname_init(&fixed);
5358	found = dns_fixedname_name(&fixed);
5359	dns_rdataset_init(&trdataset);
5360
5361	dns_clientinfomethods_init(&cm, ns_client_sourceip);
5362	dns_clientinfo_init(&ci, client);
5363
5364	if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
5365		return (ISC_FALSE);
5366
5367	if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
5368		if (rdataset->trust == dns_trust_secure)
5369			return (ISC_FALSE);
5370		if (rdataset->trust == dns_trust_ultimate &&
5371		    (rdataset->type == dns_rdatatype_nsec ||
5372		     rdataset->type == dns_rdatatype_nsec3))
5373			return (ISC_FALSE);
5374		if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
5375			for (result = dns_rdataset_first(rdataset);
5376			     result == ISC_R_SUCCESS;
5377			     result = dns_rdataset_next(rdataset)) {
5378				dns_ncache_current(rdataset, found, &trdataset);
5379				type = trdataset.type;
5380				dns_rdataset_disassociate(&trdataset);
5381				if (type == dns_rdatatype_nsec ||
5382				    type == dns_rdatatype_nsec3 ||
5383				    type == dns_rdatatype_rrsig)
5384					return (ISC_FALSE);
5385			}
5386		}
5387	}
5388
5389	result = ns_client_checkaclsilent(client, NULL,
5390				 dns_zone_getqueryacl(client->view->redirect),
5391					  ISC_TRUE);
5392	if (result != ISC_R_SUCCESS)
5393		return (ISC_FALSE);
5394
5395	result = dns_zone_getdb(client->view->redirect, &db);
5396	if (result != ISC_R_SUCCESS)
5397		return (ISC_FALSE);
5398
5399	dbversion = query_findversion(client, db);
5400	if (dbversion == NULL) {
5401		dns_db_detach(&db);
5402		return (ISC_FALSE);
5403	}
5404
5405	/*
5406	 * Lookup the requested data in the redirect zone.
5407	 */
5408	result = dns_db_findext(db, client->query.qname, dbversion->version,
5409				qtype, 0, client->now, &node, found, &cm, &ci,
5410				&trdataset, NULL);
5411	if (result != ISC_R_SUCCESS) {
5412		if (dns_rdataset_isassociated(&trdataset))
5413			dns_rdataset_disassociate(&trdataset);
5414		if (node != NULL)
5415			dns_db_detachnode(db, &node);
5416		dns_db_detach(&db);
5417		return (ISC_FALSE);
5418	}
5419	CTRACE("redirect: found data: done");
5420
5421	dns_name_copy(found, name, NULL);
5422	if (dns_rdataset_isassociated(rdataset))
5423		dns_rdataset_disassociate(rdataset);
5424	if (dns_rdataset_isassociated(&trdataset)) {
5425		dns_rdataset_clone(&trdataset, rdataset);
5426		dns_rdataset_disassociate(&trdataset);
5427	}
5428	if (*nodep != NULL)
5429		dns_db_detachnode(*dbp, nodep);
5430	dns_db_detach(dbp);
5431	dns_db_attachnode(db, node, nodep);
5432	dns_db_attach(db, dbp);
5433	dns_db_detachnode(db, &node);
5434	dns_db_detach(&db);
5435	*versionp = dbversion->version;
5436
5437	client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
5438				     NS_QUERYATTR_NOADDITIONAL);
5439
5440	return (ISC_TRUE);
5441}
5442
5443/*
5444 * Do the bulk of query processing for the current query of 'client'.
5445 * If 'event' is non-NULL, we are returning from recursion and 'qtype'
5446 * is ignored.  Otherwise, 'qtype' is the query type.
5447 */
5448static isc_result_t
5449query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
5450{
5451	dns_db_t *db, *zdb;
5452	dns_dbnode_t *node;
5453	dns_rdatatype_t type;
5454	dns_name_t *fname, *zfname, *tname, *prefix;
5455	dns_rdataset_t *rdataset, *trdataset;
5456	dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset;
5457	dns_rdataset_t **sigrdatasetp;
5458	dns_rdata_t rdata = DNS_RDATA_INIT;
5459	dns_rdatasetiter_t *rdsiter;
5460	isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof;
5461	isc_boolean_t is_staticstub_zone;
5462	unsigned int n, nlabels;
5463	dns_namereln_t namereln;
5464	int order;
5465	isc_buffer_t *dbuf;
5466	isc_buffer_t b;
5467	isc_result_t result, eresult;
5468	dns_fixedname_t fixed;
5469	dns_fixedname_t wildcardname;
5470	dns_dbversion_t *version, *zversion;
5471	dns_zone_t *zone;
5472	dns_rdata_cname_t cname;
5473	dns_rdata_dname_t dname;
5474	unsigned int options;
5475	isc_boolean_t empty_wild;
5476	dns_rdataset_t *noqname;
5477	dns_rpz_st_t *rpz_st;
5478	isc_boolean_t resuming;
5479	int line = -1;
5480	isc_boolean_t dns64_exclude, dns64;
5481	dns_clientinfomethods_t cm;
5482	dns_clientinfo_t ci;
5483
5484	CTRACE("query_find");
5485
5486	/*
5487	 * One-time initialization.
5488	 *
5489	 * It's especially important to initialize anything that the cleanup
5490	 * code might cleanup.
5491	 */
5492
5493	eresult = ISC_R_SUCCESS;
5494	fname = NULL;
5495	zfname = NULL;
5496	rdataset = NULL;
5497	zrdataset = NULL;
5498	sigrdataset = NULL;
5499	zsigrdataset = NULL;
5500	zversion = NULL;
5501	node = NULL;
5502	db = NULL;
5503	zdb = NULL;
5504	version = NULL;
5505	zone = NULL;
5506	need_wildcardproof = ISC_FALSE;
5507	empty_wild = ISC_FALSE;
5508	dns64_exclude = dns64 = ISC_FALSE;
5509	options = 0;
5510	resuming = ISC_FALSE;
5511	is_zone = ISC_FALSE;
5512	is_staticstub_zone = ISC_FALSE;
5513
5514	dns_clientinfomethods_init(&cm, ns_client_sourceip);
5515	dns_clientinfo_init(&ci, client);
5516
5517	if (event != NULL) {
5518		/*
5519		 * We're returning from recursion.  Restore the query context
5520		 * and resume.
5521		 */
5522		want_restart = ISC_FALSE;
5523
5524		rpz_st = client->query.rpz_st;
5525		if (rpz_st != NULL &&
5526		    (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
5527			is_zone = rpz_st->q.is_zone;
5528			authoritative = rpz_st->q.authoritative;
5529			zone = rpz_st->q.zone;
5530			rpz_st->q.zone = NULL;
5531			node = rpz_st->q.node;
5532			rpz_st->q.node = NULL;
5533			db = rpz_st->q.db;
5534			rpz_st->q.db = NULL;
5535			rdataset = rpz_st->q.rdataset;
5536			rpz_st->q.rdataset = NULL;
5537			sigrdataset = rpz_st->q.sigrdataset;
5538			rpz_st->q.sigrdataset = NULL;
5539			qtype = rpz_st->q.qtype;
5540
5541			rpz_st->r.db = event->db;
5542			if (event->node != NULL)
5543				dns_db_detachnode(event->db, &event->node);
5544			rpz_st->r.r_type = event->qtype;
5545			rpz_st->r.r_rdataset = event->rdataset;
5546			query_putrdataset(client, &event->sigrdataset);
5547		} else {
5548			authoritative = ISC_FALSE;
5549
5550			qtype = event->qtype;
5551			db = event->db;
5552			node = event->node;
5553			rdataset = event->rdataset;
5554			sigrdataset = event->sigrdataset;
5555		}
5556
5557		if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
5558			type = dns_rdatatype_any;
5559		else
5560			type = qtype;
5561
5562		if (DNS64(client)) {
5563			client->query.attributes &= ~NS_QUERYATTR_DNS64;
5564			dns64 = ISC_TRUE;
5565		}
5566		if (DNS64EXCLUDE(client)) {
5567			client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE;
5568			dns64_exclude = ISC_TRUE;
5569		}
5570
5571		/*
5572		 * We'll need some resources...
5573		 */
5574		dbuf = query_getnamebuf(client);
5575		if (dbuf == NULL) {
5576			QUERY_ERROR(DNS_R_SERVFAIL);
5577			goto cleanup;
5578		}
5579		fname = query_newname(client, dbuf, &b);
5580		if (fname == NULL) {
5581			QUERY_ERROR(DNS_R_SERVFAIL);
5582			goto cleanup;
5583		}
5584		if (rpz_st != NULL &&
5585		    (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
5586			tname = rpz_st->fname;
5587		} else {
5588			tname = dns_fixedname_name(&event->foundname);
5589		}
5590		result = dns_name_copy(tname, fname, NULL);
5591		if (result != ISC_R_SUCCESS) {
5592			QUERY_ERROR(DNS_R_SERVFAIL);
5593			goto cleanup;
5594		}
5595		if (rpz_st != NULL &&
5596		    (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
5597			rpz_st->r.r_result = event->result;
5598			result = rpz_st->q.result;
5599			isc_event_free(ISC_EVENT_PTR(&event));
5600		} else {
5601			result = event->result;
5602		}
5603		resuming = ISC_TRUE;
5604		goto resume;
5605	}
5606
5607	/*
5608	 * Not returning from recursion.
5609	 */
5610
5611	/*
5612	 * If it's a SIG query, we'll iterate the node.
5613	 */
5614	if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
5615		type = dns_rdatatype_any;
5616	else
5617		type = qtype;
5618
5619 restart:
5620	CTRACE("query_find: restart");
5621	want_restart = ISC_FALSE;
5622	authoritative = ISC_FALSE;
5623	version = NULL;
5624	need_wildcardproof = ISC_FALSE;
5625
5626	if (client->view->checknames &&
5627	    !dns_rdata_checkowner(client->query.qname,
5628				  client->message->rdclass,
5629				  qtype, ISC_FALSE)) {
5630		char namebuf[DNS_NAME_FORMATSIZE];
5631		char typename[DNS_RDATATYPE_FORMATSIZE];
5632		char classname[DNS_RDATACLASS_FORMATSIZE];
5633
5634		dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
5635		dns_rdatatype_format(qtype, typename, sizeof(typename));
5636		dns_rdataclass_format(client->message->rdclass, classname,
5637				      sizeof(classname));
5638		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
5639			      NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
5640			      "check-names failure %s/%s/%s", namebuf,
5641			      typename, classname);
5642		QUERY_ERROR(DNS_R_REFUSED);
5643		goto cleanup;
5644	}
5645
5646	/*
5647	 * First we must find the right database.
5648	 */
5649	options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */
5650	if (dns_rdatatype_atparent(qtype) &&
5651	    !dns_name_equal(client->query.qname, dns_rootname))
5652		options |= DNS_GETDB_NOEXACT;
5653	result = query_getdb(client, client->query.qname, qtype, options,
5654			     &zone, &db, &version, &is_zone);
5655	if ((result != ISC_R_SUCCESS || !is_zone) && !RECURSIONOK(client) &&
5656	    (options & DNS_GETDB_NOEXACT) != 0 && qtype == dns_rdatatype_ds) {
5657		/*
5658		 * Look to see if we are authoritative for the
5659		 * child zone if the query type is DS.
5660		 */
5661		dns_db_t *tdb = NULL;
5662		dns_zone_t *tzone = NULL;
5663		dns_dbversion_t *tversion = NULL;
5664		isc_result_t tresult;
5665
5666		tresult = query_getzonedb(client, client->query.qname, qtype,
5667					 DNS_GETDB_PARTIAL, &tzone, &tdb,
5668					 &tversion);
5669		if (tresult == ISC_R_SUCCESS) {
5670			options &= ~DNS_GETDB_NOEXACT;
5671			query_putrdataset(client, &rdataset);
5672			if (db != NULL)
5673				dns_db_detach(&db);
5674			if (zone != NULL)
5675				dns_zone_detach(&zone);
5676			version = tversion;
5677			db = tdb;
5678			zone = tzone;
5679			is_zone = ISC_TRUE;
5680			result = ISC_R_SUCCESS;
5681		} else {
5682			if (tdb != NULL)
5683				dns_db_detach(&tdb);
5684			if (tzone != NULL)
5685				dns_zone_detach(&tzone);
5686		}
5687	}
5688	if (result != ISC_R_SUCCESS) {
5689		if (result == DNS_R_REFUSED) {
5690			if (WANTRECURSION(client)) {
5691				inc_stats(client,
5692					  dns_nsstatscounter_recurserej);
5693			} else
5694				inc_stats(client, dns_nsstatscounter_authrej);
5695			if (!PARTIALANSWER(client))
5696				QUERY_ERROR(DNS_R_REFUSED);
5697		} else
5698			QUERY_ERROR(DNS_R_SERVFAIL);
5699		goto cleanup;
5700	}
5701
5702	is_staticstub_zone = ISC_FALSE;
5703	if (is_zone) {
5704		authoritative = ISC_TRUE;
5705		if (zone != NULL &&
5706		    dns_zone_gettype(zone) == dns_zone_staticstub)
5707			is_staticstub_zone = ISC_TRUE;
5708	}
5709
5710	if (event == NULL && client->query.restarts == 0) {
5711		if (is_zone) {
5712			if (zone != NULL) {
5713				/*
5714				 * if is_zone = true, zone = NULL then this is
5715				 * a DLZ zone.  Don't attempt to attach zone.
5716				 */
5717				dns_zone_attach(zone, &client->query.authzone);
5718			}
5719			dns_db_attach(db, &client->query.authdb);
5720		}
5721		client->query.authdbset = ISC_TRUE;
5722	}
5723
5724 db_find:
5725	CTRACE("query_find: db_find");
5726	/*
5727	 * We'll need some resources...
5728	 */
5729	dbuf = query_getnamebuf(client);
5730	if (dbuf == NULL) {
5731		QUERY_ERROR(DNS_R_SERVFAIL);
5732		goto cleanup;
5733	}
5734	fname = query_newname(client, dbuf, &b);
5735	rdataset = query_newrdataset(client);
5736	if (fname == NULL || rdataset == NULL) {
5737		QUERY_ERROR(DNS_R_SERVFAIL);
5738		goto cleanup;
5739	}
5740	if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) {
5741		sigrdataset = query_newrdataset(client);
5742		if (sigrdataset == NULL) {
5743			QUERY_ERROR(DNS_R_SERVFAIL);
5744			goto cleanup;
5745		}
5746	}
5747
5748	/*
5749	 * Now look for an answer in the database.
5750	 */
5751	result = dns_db_findext(db, client->query.qname, version, type,
5752				client->query.dboptions, client->now,
5753				&node, fname, &cm, &ci, rdataset, sigrdataset);
5754
5755 resume:
5756	CTRACE("query_find: resume");
5757
5758	if (!ISC_LIST_EMPTY(client->view->rpz_zones) &&
5759	    (RECURSIONOK(client) || !client->view->rpz_recursive_only) &&
5760	    rpz_ck_dnssec(client, result, rdataset, sigrdataset) &&
5761	    !RECURSING(client) &&
5762	    (client->query.rpz_st == NULL ||
5763	     (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) &&
5764	    !dns_name_equal(client->query.qname, dns_rootname)) {
5765		isc_result_t rresult;
5766
5767		rresult = rpz_rewrite(client, qtype, result, resuming);
5768		rpz_st = client->query.rpz_st;
5769		switch (rresult) {
5770		case ISC_R_SUCCESS:
5771			break;
5772		case DNS_R_DELEGATION:
5773			/*
5774			 * recursing for NS names or addresses,
5775			 * so save the main query state
5776			 */
5777			rpz_st->q.qtype = qtype;
5778			rpz_st->q.is_zone = is_zone;
5779			rpz_st->q.authoritative = authoritative;
5780			rpz_st->q.zone = zone;
5781			zone = NULL;
5782			rpz_st->q.db = db;
5783			db = NULL;
5784			rpz_st->q.node = node;
5785			node = NULL;
5786			rpz_st->q.rdataset = rdataset;
5787			rdataset = NULL;
5788			rpz_st->q.sigrdataset = sigrdataset;
5789			sigrdataset = NULL;
5790			dns_name_copy(fname, rpz_st->fname, NULL);
5791			rpz_st->q.result = result;
5792			client->query.attributes |= NS_QUERYATTR_RECURSING;
5793			goto cleanup;
5794		default:
5795			RECURSE_ERROR(rresult);
5796			goto cleanup;
5797		}
5798		if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS)
5799			rpz_st->state |= DNS_RPZ_REWRITTEN;
5800		if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS &&
5801		    rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU &&
5802		    rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
5803			if (rpz_st->m.type == DNS_RPZ_TYPE_QNAME) {
5804				result = dns_name_copy(client->query.qname,
5805						       fname, NULL);
5806				RUNTIME_CHECK(result == ISC_R_SUCCESS);
5807			}
5808			rpz_clean(&zone, &db, &node, NULL);
5809			if (rpz_st->m.rdataset != NULL) {
5810				query_putrdataset(client, &rdataset);
5811				rdataset = rpz_st->m.rdataset;
5812				rpz_st->m.rdataset = NULL;
5813			} else if (rdataset != NULL &&
5814				   dns_rdataset_isassociated(rdataset)) {
5815				dns_rdataset_disassociate(rdataset);
5816			}
5817			node = rpz_st->m.node;
5818			rpz_st->m.node = NULL;
5819			db = rpz_st->m.db;
5820			rpz_st->m.db = NULL;
5821			version = rpz_st->m.version;
5822			rpz_st->m.version = NULL;
5823			zone = rpz_st->m.zone;
5824			rpz_st->m.zone = NULL;
5825
5826			switch (rpz_st->m.policy) {
5827			case DNS_RPZ_POLICY_NXDOMAIN:
5828				result = DNS_R_NXDOMAIN;
5829				break;
5830			case DNS_RPZ_POLICY_NODATA:
5831				result = DNS_R_NXRRSET;
5832				break;
5833			case DNS_RPZ_POLICY_RECORD:
5834				result = rpz_st->m.result;
5835				if (qtype == dns_rdatatype_any &&
5836				    result != DNS_R_CNAME) {
5837					/*
5838					 * We will add all of the rdatasets of
5839					 * the node by iterating, setting the
5840					 * TTL then.
5841					 */
5842					if (dns_rdataset_isassociated(rdataset))
5843					dns_rdataset_disassociate(rdataset);
5844				} else {
5845					/*
5846					 * We will add this rdataset.
5847					 */
5848					rdataset->ttl = ISC_MIN(rdataset->ttl,
5849							    rpz_st->m.ttl);
5850				}
5851				break;
5852			case DNS_RPZ_POLICY_WILDCNAME:
5853				result = dns_rdataset_first(rdataset);
5854				RUNTIME_CHECK(result == ISC_R_SUCCESS);
5855				dns_rdataset_current(rdataset, &rdata);
5856				result = dns_rdata_tostruct(&rdata, &cname,
5857							    NULL);
5858				RUNTIME_CHECK(result == ISC_R_SUCCESS);
5859				dns_rdata_reset(&rdata);
5860				result = rpz_add_cname(client, rpz_st,
5861						       &cname.cname,
5862						       fname, dbuf);
5863				if (result != ISC_R_SUCCESS)
5864					goto cleanup;
5865				fname = NULL;
5866				want_restart = ISC_TRUE;
5867				goto cleanup;
5868			case DNS_RPZ_POLICY_CNAME:
5869				/*
5870				 * Add overridding CNAME from a named.conf
5871				 * response-policy statement
5872				 */
5873				result = rpz_add_cname(client, rpz_st,
5874						       &rpz_st->m.rpz->cname,
5875						       fname, dbuf);
5876				if (result != ISC_R_SUCCESS)
5877					goto cleanup;
5878				fname = NULL;
5879				want_restart = ISC_TRUE;
5880				goto cleanup;
5881			default:
5882				INSIST(0);
5883			}
5884
5885			/*
5886			 * Turn off DNSSEC because the results of a
5887			 * response policy zone cannot verify.
5888			 */
5889			client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
5890						DNS_MESSAGEFLAG_AD);
5891			query_putrdataset(client, &sigrdataset);
5892			is_zone = ISC_TRUE;
5893			rpz_log_rewrite(client, "", rpz_st->m.policy,
5894					rpz_st->m.type, rpz_st->qname);
5895		}
5896	}
5897
5898	switch (result) {
5899	case ISC_R_SUCCESS:
5900		/*
5901		 * This case is handled in the main line below.
5902		 */
5903		break;
5904	case DNS_R_GLUE:
5905	case DNS_R_ZONECUT:
5906		/*
5907		 * These cases are handled in the main line below.
5908		 */
5909		INSIST(is_zone);
5910		authoritative = ISC_FALSE;
5911		break;
5912	case ISC_R_NOTFOUND:
5913		/*
5914		 * The cache doesn't even have the root NS.  Get them from
5915		 * the hints DB.
5916		 */
5917		INSIST(!is_zone);
5918		if (db != NULL)
5919			dns_db_detach(&db);
5920
5921		if (client->view->hints == NULL) {
5922			/* We have no hints. */
5923			result = ISC_R_FAILURE;
5924		} else {
5925			dns_db_attach(client->view->hints, &db);
5926			result = dns_db_findext(db, dns_rootname,
5927						NULL, dns_rdatatype_ns,
5928						0, client->now, &node,
5929						fname, &cm, &ci,
5930						rdataset, sigrdataset);
5931		}
5932		if (result != ISC_R_SUCCESS) {
5933			/*
5934			 * Nonsensical root hints may require cleanup.
5935			 */
5936			if (dns_rdataset_isassociated(rdataset))
5937				dns_rdataset_disassociate(rdataset);
5938			if (sigrdataset != NULL &&
5939			    dns_rdataset_isassociated(sigrdataset))
5940				dns_rdataset_disassociate(sigrdataset);
5941			if (node != NULL)
5942				dns_db_detachnode(db, &node);
5943
5944			/*
5945			 * We don't have any root server hints, but
5946			 * we may have working forwarders, so try to
5947			 * recurse anyway.
5948			 */
5949			if (RECURSIONOK(client)) {
5950				result = query_recurse(client, qtype,
5951						       client->query.qname,
5952						       NULL, NULL, resuming);
5953				if (result == ISC_R_SUCCESS) {
5954					client->query.attributes |=
5955						NS_QUERYATTR_RECURSING;
5956					if (dns64)
5957						client->query.attributes |=
5958							NS_QUERYATTR_DNS64;
5959					if (dns64_exclude)
5960						client->query.attributes |=
5961						      NS_QUERYATTR_DNS64EXCLUDE;
5962				} else
5963					RECURSE_ERROR(result);
5964				goto cleanup;
5965			} else {
5966				/* Unable to give root server referral. */
5967				QUERY_ERROR(DNS_R_SERVFAIL);
5968				goto cleanup;
5969			}
5970		}
5971		/*
5972		 * XXXRTH  We should trigger root server priming here.
5973		 */
5974		/* FALLTHROUGH */
5975	case DNS_R_DELEGATION:
5976		authoritative = ISC_FALSE;
5977		if (is_zone) {
5978			/*
5979			 * Look to see if we are authoritative for the
5980			 * child zone if the query type is DS.
5981			 */
5982			if (!RECURSIONOK(client) &&
5983			    (options & DNS_GETDB_NOEXACT) != 0 &&
5984			    qtype == dns_rdatatype_ds) {
5985				dns_db_t *tdb = NULL;
5986				dns_zone_t *tzone = NULL;
5987				dns_dbversion_t *tversion = NULL;
5988				result = query_getzonedb(client,
5989							 client->query.qname,
5990							 qtype,
5991							 DNS_GETDB_PARTIAL,
5992							 &tzone, &tdb,
5993							 &tversion);
5994				if (result == ISC_R_SUCCESS) {
5995					options &= ~DNS_GETDB_NOEXACT;
5996					query_putrdataset(client, &rdataset);
5997					if (sigrdataset != NULL)
5998						query_putrdataset(client,
5999								  &sigrdataset);
6000					if (fname != NULL)
6001						query_releasename(client,
6002								  &fname);
6003					if (node != NULL)
6004						dns_db_detachnode(db, &node);
6005					if (db != NULL)
6006						dns_db_detach(&db);
6007					if (zone != NULL)
6008						dns_zone_detach(&zone);
6009					version = tversion;
6010					db = tdb;
6011					zone = tzone;
6012					authoritative = ISC_TRUE;
6013					goto db_find;
6014				}
6015				if (tdb != NULL)
6016					dns_db_detach(&tdb);
6017				if (tzone != NULL)
6018					dns_zone_detach(&tzone);
6019			}
6020			/*
6021			 * We're authoritative for an ancestor of QNAME.
6022			 */
6023			if (!USECACHE(client) || !RECURSIONOK(client)) {
6024				dns_fixedname_t fixed;
6025
6026				dns_fixedname_init(&fixed);
6027				dns_name_copy(fname,
6028					      dns_fixedname_name(&fixed), NULL);
6029
6030				/*
6031				 * If we don't have a cache, this is the best
6032				 * answer.
6033				 *
6034				 * If the client is making a nonrecursive
6035				 * query we always give out the authoritative
6036				 * delegation.  This way even if we get
6037				 * junk in our cache, we won't fail in our
6038				 * role as the delegating authority if another
6039				 * nameserver asks us about a delegated
6040				 * subzone.
6041				 *
6042				 * We enable the retrieval of glue for this
6043				 * database by setting client->query.gluedb.
6044				 */
6045				client->query.gluedb = db;
6046				client->query.isreferral = ISC_TRUE;
6047				/*
6048				 * We must ensure NOADDITIONAL is off,
6049				 * because the generation of
6050				 * additional data is required in
6051				 * delegations.
6052				 */
6053				client->query.attributes &=
6054					~NS_QUERYATTR_NOADDITIONAL;
6055				if (sigrdataset != NULL)
6056					sigrdatasetp = &sigrdataset;
6057				else
6058					sigrdatasetp = NULL;
6059				query_addrrset(client, &fname,
6060					       &rdataset, sigrdatasetp,
6061					       dbuf, DNS_SECTION_AUTHORITY);
6062				client->query.gluedb = NULL;
6063				if (WANTDNSSEC(client))
6064					query_addds(client, db, node, version,
6065						   dns_fixedname_name(&fixed));
6066			} else {
6067				/*
6068				 * We might have a better answer or delegation
6069				 * in the cache.  We'll remember the current
6070				 * values of fname, rdataset, and sigrdataset.
6071				 * We'll then go looking for QNAME in the
6072				 * cache.  If we find something better, we'll
6073				 * use it instead.
6074				 */
6075				query_keepname(client, fname, dbuf);
6076				zdb = db;
6077				zfname = fname;
6078				fname = NULL;
6079				zrdataset = rdataset;
6080				rdataset = NULL;
6081				zsigrdataset = sigrdataset;
6082				sigrdataset = NULL;
6083				dns_db_detachnode(db, &node);
6084				zversion = version;
6085				version = NULL;
6086				db = NULL;
6087				dns_db_attach(client->view->cachedb, &db);
6088				is_zone = ISC_FALSE;
6089				goto db_find;
6090			}
6091		} else {
6092			if (zfname != NULL &&
6093			    (!dns_name_issubdomain(fname, zfname) ||
6094			     (is_staticstub_zone &&
6095			      dns_name_equal(fname, zfname)))) {
6096				/*
6097				 * In the following cases use "authoritative"
6098				 * data instead of the cache delegation:
6099				 * 1. We've already got a delegation from
6100				 *    authoritative data, and it is better
6101				 *    than what we found in the cache.
6102				 * 2. The query name matches the origin name
6103				 *    of a static-stub zone.  This needs to be
6104				 *    considered for the case where the NS of
6105				 *    the static-stub zone and the cached NS
6106				 *    are different.  We still need to contact
6107				 *    the nameservers configured in the
6108				 *    static-stub zone.
6109				 */
6110				query_releasename(client, &fname);
6111				fname = zfname;
6112				zfname = NULL;
6113				/*
6114				 * We've already done query_keepname() on
6115				 * zfname, so we must set dbuf to NULL to
6116				 * prevent query_addrrset() from trying to
6117				 * call query_keepname() again.
6118				 */
6119				dbuf = NULL;
6120				query_putrdataset(client, &rdataset);
6121				if (sigrdataset != NULL)
6122					query_putrdataset(client,
6123							  &sigrdataset);
6124				rdataset = zrdataset;
6125				zrdataset = NULL;
6126				sigrdataset = zsigrdataset;
6127				zsigrdataset = NULL;
6128				version = zversion;
6129				zversion = NULL;
6130				/*
6131				 * We don't clean up zdb here because we
6132				 * may still need it.  It will get cleaned
6133				 * up by the main cleanup code.
6134				 */
6135			}
6136
6137			if (RECURSIONOK(client)) {
6138				/*
6139				 * Recurse!
6140				 */
6141				if (dns_rdatatype_atparent(type))
6142					result = query_recurse(client, qtype,
6143							 client->query.qname,
6144							 NULL, NULL, resuming);
6145				else if (dns64)
6146					result = query_recurse(client,
6147							 dns_rdatatype_a,
6148							 client->query.qname,
6149							 NULL, NULL, resuming);
6150				else
6151					result = query_recurse(client, qtype,
6152							 client->query.qname,
6153							 fname, rdataset,
6154							 resuming);
6155
6156				if (result == ISC_R_SUCCESS) {
6157					client->query.attributes |=
6158						NS_QUERYATTR_RECURSING;
6159					if (dns64)
6160						client->query.attributes |=
6161							NS_QUERYATTR_DNS64;
6162					if (dns64_exclude)
6163						client->query.attributes |=
6164						      NS_QUERYATTR_DNS64EXCLUDE;
6165				} else if (result == DNS_R_DUPLICATE ||
6166					 result == DNS_R_DROP)
6167					QUERY_ERROR(result);
6168				else
6169					RECURSE_ERROR(result);
6170			} else {
6171				dns_fixedname_t fixed;
6172
6173				dns_fixedname_init(&fixed);
6174				dns_name_copy(fname,
6175					      dns_fixedname_name(&fixed), NULL);
6176				/*
6177				 * This is the best answer.
6178				 */
6179				client->query.attributes |=
6180					NS_QUERYATTR_CACHEGLUEOK;
6181				client->query.gluedb = zdb;
6182				client->query.isreferral = ISC_TRUE;
6183				/*
6184				 * We must ensure NOADDITIONAL is off,
6185				 * because the generation of
6186				 * additional data is required in
6187				 * delegations.
6188				 */
6189				client->query.attributes &=
6190					~NS_QUERYATTR_NOADDITIONAL;
6191				if (sigrdataset != NULL)
6192					sigrdatasetp = &sigrdataset;
6193				else
6194					sigrdatasetp = NULL;
6195				query_addrrset(client, &fname,
6196					       &rdataset, sigrdatasetp,
6197					       dbuf, DNS_SECTION_AUTHORITY);
6198				client->query.gluedb = NULL;
6199				client->query.attributes &=
6200					~NS_QUERYATTR_CACHEGLUEOK;
6201				if (WANTDNSSEC(client))
6202					query_addds(client, db, node, version,
6203						   dns_fixedname_name(&fixed));
6204			}
6205		}
6206		goto cleanup;
6207
6208	case DNS_R_EMPTYNAME:
6209	case DNS_R_NXRRSET:
6210	iszone_nxrrset:
6211		INSIST(is_zone);
6212
6213#ifdef dns64_bis_return_excluded_addresses
6214		if (dns64)
6215#else
6216		if (dns64 && !dns64_exclude)
6217#endif
6218		{
6219			/*
6220			 * Restore the answers from the previous AAAA lookup.
6221			 */
6222			if (rdataset != NULL)
6223				query_putrdataset(client, &rdataset);
6224			if (sigrdataset != NULL)
6225				query_putrdataset(client, &sigrdataset);
6226			rdataset = client->query.dns64_aaaa;
6227			sigrdataset = client->query.dns64_sigaaaa;
6228			client->query.dns64_aaaa = NULL;
6229			client->query.dns64_sigaaaa = NULL;
6230			if (fname == NULL) {
6231				dbuf = query_getnamebuf(client);
6232				if (dbuf == NULL) {
6233					QUERY_ERROR(DNS_R_SERVFAIL);
6234					goto cleanup;
6235				}
6236				fname = query_newname(client, dbuf, &b);
6237				if (fname == NULL) {
6238					QUERY_ERROR(DNS_R_SERVFAIL);
6239					goto cleanup;
6240				}
6241			}
6242			dns_name_copy(client->query.qname, fname, NULL);
6243			dns64 = ISC_FALSE;
6244#ifdef dns64_bis_return_excluded_addresses
6245			/*
6246			 * Resume the diverted processing of the AAAA response?
6247			 */
6248			if (dns64_excluded)
6249				break;
6250#endif
6251		} else if (result == DNS_R_NXRRSET &&
6252			   !ISC_LIST_EMPTY(client->view->dns64) &&
6253			   client->message->rdclass == dns_rdataclass_in &&
6254			   qtype == dns_rdatatype_aaaa)
6255		{
6256			/*
6257			 * Look to see if there are A records for this
6258			 * name.
6259			 */
6260			INSIST(client->query.dns64_aaaa == NULL);
6261			INSIST(client->query.dns64_sigaaaa == NULL);
6262			client->query.dns64_aaaa = rdataset;
6263			client->query.dns64_sigaaaa = sigrdataset;
6264			client->query.dns64_ttl = dns64_ttl(db, version);
6265			query_releasename(client, &fname);
6266			dns_db_detachnode(db, &node);
6267			rdataset = NULL;
6268			sigrdataset = NULL;
6269			type = qtype = dns_rdatatype_a;
6270			dns64 = ISC_TRUE;
6271			goto db_find;
6272		}
6273
6274		/*
6275		 * Look for a NSEC3 record if we don't have a NSEC record.
6276		 */
6277 nxrrset_rrsig:
6278		if (!dns_rdataset_isassociated(rdataset) &&
6279		     WANTDNSSEC(client)) {
6280			if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
6281				dns_name_t *found;
6282				dns_name_t *qname;
6283
6284				dns_fixedname_init(&fixed);
6285				found = dns_fixedname_name(&fixed);
6286				qname = client->query.qname;
6287
6288				query_findclosestnsec3(qname, db, version,
6289						       client, rdataset,
6290						       sigrdataset, fname,
6291						       ISC_TRUE, found);
6292				/*
6293				 * Did we find the closest provable encloser
6294				 * instead? If so add the nearest to the
6295				 * closest provable encloser.
6296				 */
6297				if (dns_rdataset_isassociated(rdataset) &&
6298				    !dns_name_equal(qname, found)) {
6299					unsigned int count;
6300					unsigned int skip;
6301
6302					/*
6303					 * Add the closest provable encloser.
6304					 */
6305					query_addrrset(client, &fname,
6306						       &rdataset, &sigrdataset,
6307						       dbuf,
6308						       DNS_SECTION_AUTHORITY);
6309
6310					count = dns_name_countlabels(found)
6311							 + 1;
6312					skip = dns_name_countlabels(qname) -
6313							 count;
6314					dns_name_getlabelsequence(qname, skip,
6315								  count,
6316								  found);
6317
6318					fixfname(client, &fname, &dbuf, &b);
6319					fixrdataset(client, &rdataset);
6320					fixrdataset(client, &sigrdataset);
6321					if (fname == NULL ||
6322					    rdataset == NULL ||
6323					    sigrdataset == NULL) {
6324						QUERY_ERROR(DNS_R_SERVFAIL);
6325						goto cleanup;
6326					}
6327					/*
6328					 * 'nearest' doesn't exist so
6329					 * 'exist' is set to ISC_FALSE.
6330					 */
6331					query_findclosestnsec3(found, db,
6332							       version,
6333							       client,
6334							       rdataset,
6335							       sigrdataset,
6336							       fname,
6337							       ISC_FALSE,
6338							       NULL);
6339				}
6340			} else {
6341				query_releasename(client, &fname);
6342				query_addwildcardproof(client, db, version,
6343						       client->query.qname,
6344						       ISC_FALSE, ISC_TRUE);
6345			}
6346		}
6347		if (dns_rdataset_isassociated(rdataset)) {
6348			/*
6349			 * If we've got a NSEC record, we need to save the
6350			 * name now because we're going call query_addsoa()
6351			 * below, and it needs to use the name buffer.
6352			 */
6353			query_keepname(client, fname, dbuf);
6354		} else if (fname != NULL) {
6355			/*
6356			 * We're not going to use fname, and need to release
6357			 * our hold on the name buffer so query_addsoa()
6358			 * may use it.
6359			 */
6360			query_releasename(client, &fname);
6361		}
6362		/*
6363		 * Add SOA.
6364		 */
6365		result = query_addsoa(client, db, version, ISC_UINT32_MAX,
6366				      dns_rdataset_isassociated(rdataset));
6367		if (result != ISC_R_SUCCESS) {
6368			QUERY_ERROR(result);
6369			goto cleanup;
6370		}
6371		/*
6372		 * Add NSEC record if we found one.
6373		 */
6374		if (WANTDNSSEC(client)) {
6375			if (dns_rdataset_isassociated(rdataset))
6376				query_addnxrrsetnsec(client, db, version,
6377						     &fname, &rdataset,
6378						     &sigrdataset);
6379		}
6380		goto cleanup;
6381
6382	case DNS_R_EMPTYWILD:
6383		empty_wild = ISC_TRUE;
6384		/* FALLTHROUGH */
6385
6386	case DNS_R_NXDOMAIN:
6387		INSIST(is_zone);
6388		if (!empty_wild &&
6389		    redirect(client, fname, rdataset, &node, &db, &version,
6390			     type))
6391			break;
6392		if (dns_rdataset_isassociated(rdataset)) {
6393			/*
6394			 * If we've got a NSEC record, we need to save the
6395			 * name now because we're going call query_addsoa()
6396			 * below, and it needs to use the name buffer.
6397			 */
6398			query_keepname(client, fname, dbuf);
6399		} else if (fname != NULL) {
6400			/*
6401			 * We're not going to use fname, and need to release
6402			 * our hold on the name buffer so query_addsoa()
6403			 * may use it.
6404			 */
6405			query_releasename(client, &fname);
6406		}
6407
6408		/*
6409		 * Add SOA.  If the query was for a SOA record force the
6410		 * ttl to zero so that it is possible for clients to find
6411		 * the containing zone of an arbitrary name with a stub
6412		 * resolver and not have it cached.
6413		 */
6414		if (qtype == dns_rdatatype_soa &&
6415		    zone != NULL &&
6416		    dns_zone_getzeronosoattl(zone))
6417			result = query_addsoa(client, db, version, 0,
6418					  dns_rdataset_isassociated(rdataset));
6419		else
6420			result = query_addsoa(client, db, version,
6421					      ISC_UINT32_MAX,
6422					  dns_rdataset_isassociated(rdataset));
6423		if (result != ISC_R_SUCCESS) {
6424			QUERY_ERROR(result);
6425			goto cleanup;
6426		}
6427
6428		if (WANTDNSSEC(client)) {
6429			/*
6430			 * Add NSEC record if we found one.
6431			 */
6432			if (dns_rdataset_isassociated(rdataset))
6433				query_addrrset(client, &fname, &rdataset,
6434					       &sigrdataset,
6435					       NULL, DNS_SECTION_AUTHORITY);
6436			query_addwildcardproof(client, db, version,
6437					       client->query.qname, ISC_FALSE,
6438					       ISC_FALSE);
6439		}
6440
6441		/*
6442		 * Set message rcode.
6443		 */
6444		if (empty_wild)
6445			client->message->rcode = dns_rcode_noerror;
6446		else
6447			client->message->rcode = dns_rcode_nxdomain;
6448		goto cleanup;
6449
6450	case DNS_R_NCACHENXDOMAIN:
6451		if (redirect(client, fname, rdataset, &node, &db, &version,
6452			     type))
6453			break;
6454	case DNS_R_NCACHENXRRSET:
6455	ncache_nxrrset:
6456		INSIST(!is_zone);
6457		authoritative = ISC_FALSE;
6458		/*
6459		 * Set message rcode, if required.
6460		 */
6461		if (result == DNS_R_NCACHENXDOMAIN)
6462			client->message->rcode = dns_rcode_nxdomain;
6463		/*
6464		 * Look for RFC 1918 leakage from Internet.
6465		 */
6466		if (result == DNS_R_NCACHENXDOMAIN &&
6467		    qtype == dns_rdatatype_ptr &&
6468		    client->message->rdclass == dns_rdataclass_in &&
6469		    dns_name_countlabels(fname) == 7)
6470			warn_rfc1918(client, fname, rdataset);
6471
6472#ifdef dns64_bis_return_excluded_addresses
6473		if (dns64)
6474#else
6475		if (dns64 && !dns64_exclude)
6476#endif
6477		{
6478			/*
6479			 * Restore the answers from the previous AAAA lookup.
6480			 */
6481			if (rdataset != NULL)
6482				query_putrdataset(client, &rdataset);
6483			if (sigrdataset != NULL)
6484				query_putrdataset(client, &sigrdataset);
6485			rdataset = client->query.dns64_aaaa;
6486			sigrdataset = client->query.dns64_sigaaaa;
6487			client->query.dns64_aaaa = NULL;
6488			client->query.dns64_sigaaaa = NULL;
6489			if (fname == NULL) {
6490				dbuf = query_getnamebuf(client);
6491				if (dbuf == NULL) {
6492					QUERY_ERROR(DNS_R_SERVFAIL);
6493					goto cleanup;
6494				}
6495				fname = query_newname(client, dbuf, &b);
6496				if (fname == NULL) {
6497					QUERY_ERROR(DNS_R_SERVFAIL);
6498					goto cleanup;
6499				}
6500			}
6501			dns_name_copy(client->query.qname, fname, NULL);
6502			dns64 = ISC_FALSE;
6503#ifdef dns64_bis_return_excluded_addresses
6504			if (dns64_excluded)
6505				break;
6506#endif
6507		} else if (result == DNS_R_NCACHENXRRSET &&
6508			   !ISC_LIST_EMPTY(client->view->dns64) &&
6509			   client->message->rdclass == dns_rdataclass_in &&
6510			   qtype == dns_rdatatype_aaaa)
6511		{
6512			/*
6513			 * Look to see if there are A records for this
6514			 * name.
6515			 */
6516			INSIST(client->query.dns64_aaaa == NULL);
6517			INSIST(client->query.dns64_sigaaaa == NULL);
6518			client->query.dns64_aaaa = rdataset;
6519			client->query.dns64_sigaaaa = sigrdataset;
6520			/*
6521			 * If the ttl is zero we need to workout if we have just
6522			 * decremented to zero or if there was no negative cache
6523			 * ttl in the answer.
6524			 */
6525			if (rdataset->ttl != 0)
6526				client->query.dns64_ttl = rdataset->ttl;
6527			else if (dns_rdataset_first(rdataset) == ISC_R_SUCCESS)
6528				client->query.dns64_ttl = 0;
6529			query_releasename(client, &fname);
6530			dns_db_detachnode(db, &node);
6531			rdataset = NULL;
6532			sigrdataset = NULL;
6533			fname = NULL;
6534			type = qtype = dns_rdatatype_a;
6535			dns64 = ISC_TRUE;
6536			goto db_find;
6537		}
6538
6539		/*
6540		 * We don't call query_addrrset() because we don't need any
6541		 * of its extra features (and things would probably break!).
6542		 */
6543		query_keepname(client, fname, dbuf);
6544		dns_message_addname(client->message, fname,
6545				    DNS_SECTION_AUTHORITY);
6546		ISC_LIST_APPEND(fname->list, rdataset, link);
6547		fname = NULL;
6548		rdataset = NULL;
6549		goto cleanup;
6550
6551	case DNS_R_CNAME:
6552		/*
6553		 * Keep a copy of the rdataset.  We have to do this because
6554		 * query_addrrset may clear 'rdataset' (to prevent the
6555		 * cleanup code from cleaning it up).
6556		 */
6557		trdataset = rdataset;
6558		/*
6559		 * Add the CNAME to the answer section.
6560		 */
6561		if (sigrdataset != NULL)
6562			sigrdatasetp = &sigrdataset;
6563		else
6564			sigrdatasetp = NULL;
6565		if (WANTDNSSEC(client) &&
6566		    (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
6567		{
6568			dns_fixedname_init(&wildcardname);
6569			dns_name_copy(fname, dns_fixedname_name(&wildcardname),
6570				      NULL);
6571			need_wildcardproof = ISC_TRUE;
6572		}
6573		if (NOQNAME(rdataset) && WANTDNSSEC(client))
6574			noqname = rdataset;
6575		else
6576			noqname = NULL;
6577		query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
6578			       DNS_SECTION_ANSWER);
6579		if (noqname != NULL)
6580			query_addnoqnameproof(client, noqname);
6581		/*
6582		 * We set the PARTIALANSWER attribute so that if anything goes
6583		 * wrong later on, we'll return what we've got so far.
6584		 */
6585		client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
6586		/*
6587		 * Reset qname to be the target name of the CNAME and restart
6588		 * the query.
6589		 */
6590		tname = NULL;
6591		result = dns_message_gettempname(client->message, &tname);
6592		if (result != ISC_R_SUCCESS)
6593			goto cleanup;
6594		result = dns_rdataset_first(trdataset);
6595		if (result != ISC_R_SUCCESS) {
6596			dns_message_puttempname(client->message, &tname);
6597			goto cleanup;
6598		}
6599		dns_rdataset_current(trdataset, &rdata);
6600		result = dns_rdata_tostruct(&rdata, &cname, NULL);
6601		dns_rdata_reset(&rdata);
6602		if (result != ISC_R_SUCCESS) {
6603			dns_message_puttempname(client->message, &tname);
6604			goto cleanup;
6605		}
6606		dns_name_init(tname, NULL);
6607		result = dns_name_dup(&cname.cname, client->mctx, tname);
6608		if (result != ISC_R_SUCCESS) {
6609			dns_message_puttempname(client->message, &tname);
6610			dns_rdata_freestruct(&cname);
6611			goto cleanup;
6612		}
6613		dns_rdata_freestruct(&cname);
6614		ns_client_qnamereplace(client, tname);
6615		want_restart = ISC_TRUE;
6616		if (!WANTRECURSION(client))
6617			options |= DNS_GETDB_NOLOG;
6618		goto addauth;
6619	case DNS_R_DNAME:
6620		/*
6621		 * Compare the current qname to the found name.  We need
6622		 * to know how many labels and bits are in common because
6623		 * we're going to have to split qname later on.
6624		 */
6625		namereln = dns_name_fullcompare(client->query.qname, fname,
6626						&order, &nlabels);
6627		INSIST(namereln == dns_namereln_subdomain);
6628		/*
6629		 * Keep a copy of the rdataset.  We have to do this because
6630		 * query_addrrset may clear 'rdataset' (to prevent the
6631		 * cleanup code from cleaning it up).
6632		 */
6633		trdataset = rdataset;
6634		/*
6635		 * Add the DNAME to the answer section.
6636		 */
6637		if (sigrdataset != NULL)
6638			sigrdatasetp = &sigrdataset;
6639		else
6640			sigrdatasetp = NULL;
6641		if (WANTDNSSEC(client) &&
6642		    (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
6643		{
6644			dns_fixedname_init(&wildcardname);
6645			dns_name_copy(fname, dns_fixedname_name(&wildcardname),
6646				      NULL);
6647			need_wildcardproof = ISC_TRUE;
6648		}
6649		query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
6650			       DNS_SECTION_ANSWER);
6651		/*
6652		 * We set the PARTIALANSWER attribute so that if anything goes
6653		 * wrong later on, we'll return what we've got so far.
6654		 */
6655		client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
6656		/*
6657		 * Get the target name of the DNAME.
6658		 */
6659		tname = NULL;
6660		result = dns_message_gettempname(client->message, &tname);
6661		if (result != ISC_R_SUCCESS)
6662			goto cleanup;
6663		result = dns_rdataset_first(trdataset);
6664		if (result != ISC_R_SUCCESS) {
6665			dns_message_puttempname(client->message, &tname);
6666			goto cleanup;
6667		}
6668		dns_rdataset_current(trdataset, &rdata);
6669		result = dns_rdata_tostruct(&rdata, &dname, NULL);
6670		dns_rdata_reset(&rdata);
6671		if (result != ISC_R_SUCCESS) {
6672			dns_message_puttempname(client->message, &tname);
6673			goto cleanup;
6674		}
6675		dns_name_clone(&dname.dname, tname);
6676		dns_rdata_freestruct(&dname);
6677		/*
6678		 * Construct the new qname consisting of
6679		 * <found name prefix>.<dname target>
6680		 */
6681		dns_fixedname_init(&fixed);
6682		prefix = dns_fixedname_name(&fixed);
6683		dns_name_split(client->query.qname, nlabels, prefix, NULL);
6684		INSIST(fname == NULL);
6685		dbuf = query_getnamebuf(client);
6686		if (dbuf == NULL) {
6687			dns_message_puttempname(client->message, &tname);
6688			goto cleanup;
6689		}
6690		fname = query_newname(client, dbuf, &b);
6691		if (fname == NULL) {
6692			dns_message_puttempname(client->message, &tname);
6693			goto cleanup;
6694		}
6695		result = dns_name_concatenate(prefix, tname, fname, NULL);
6696		dns_message_puttempname(client->message, &tname);
6697
6698		/*
6699		 * RFC2672, section 4.1, subsection 3c says
6700		 * we should return YXDOMAIN if the constructed
6701		 * name would be too long.
6702		 */
6703		if (result == DNS_R_NAMETOOLONG)
6704			client->message->rcode = dns_rcode_yxdomain;
6705		if (result != ISC_R_SUCCESS)
6706			goto cleanup;
6707
6708		query_keepname(client, fname, dbuf);
6709		/*
6710		 * Synthesize a CNAME consisting of
6711		 *   <old qname> <dname ttl> CNAME <new qname>
6712		 *	    with <dname trust value>
6713		 *
6714		 * Synthesize a CNAME so old old clients that don't understand
6715		 * DNAME can chain.
6716		 *
6717		 * We do not try to synthesize a signature because we hope
6718		 * that security aware servers will understand DNAME.  Also,
6719		 * even if we had an online key, making a signature
6720		 * on-the-fly is costly, and not really legitimate anyway
6721		 * since the synthesized CNAME is NOT in the zone.
6722		 */
6723		result = query_add_cname(client, client->query.qname, fname,
6724					 trdataset->trust, trdataset->ttl);
6725		if (result != ISC_R_SUCCESS)
6726			goto cleanup;
6727		/*
6728		 * Switch to the new qname and restart.
6729		 */
6730		ns_client_qnamereplace(client, fname);
6731		fname = NULL;
6732		want_restart = ISC_TRUE;
6733		if (!WANTRECURSION(client))
6734			options |= DNS_GETDB_NOLOG;
6735		goto addauth;
6736	default:
6737		/*
6738		 * Something has gone wrong.
6739		 */
6740		QUERY_ERROR(DNS_R_SERVFAIL);
6741		goto cleanup;
6742	}
6743
6744	if (WANTDNSSEC(client) &&
6745	    (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
6746	{
6747		dns_fixedname_init(&wildcardname);
6748		dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL);
6749		need_wildcardproof = ISC_TRUE;
6750	}
6751
6752#ifdef ALLOW_FILTER_AAAA_ON_V4
6753	if (client->view->v4_aaaa != dns_v4_aaaa_ok &&
6754	    is_v4_client(client) &&
6755	    ns_client_checkaclsilent(client, NULL,
6756				     client->view->v4_aaaa_acl,
6757				     ISC_TRUE) == ISC_R_SUCCESS)
6758		client->filter_aaaa = client->view->v4_aaaa;
6759	else
6760		client->filter_aaaa = dns_v4_aaaa_ok;
6761
6762#endif
6763
6764	if (type == dns_rdatatype_any) {
6765#ifdef ALLOW_FILTER_AAAA_ON_V4
6766		isc_boolean_t have_aaaa, have_a, have_sig;
6767
6768		/*
6769		 * The filter-aaaa-on-v4 option should
6770		 * suppress AAAAs for IPv4 clients if there is an A.
6771		 * If we are not authoritative, assume there is a A
6772		 * even in if it is not in our cache.  This assumption could
6773		 * be wrong but it is a good bet.
6774		 */
6775		have_aaaa = ISC_FALSE;
6776		have_a = !authoritative;
6777		have_sig = ISC_FALSE;
6778#endif
6779		/*
6780		 * XXXRTH  Need to handle zonecuts with special case
6781		 * code.
6782		 */
6783		n = 0;
6784		rdsiter = NULL;
6785		result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
6786		if (result != ISC_R_SUCCESS) {
6787			QUERY_ERROR(DNS_R_SERVFAIL);
6788			goto cleanup;
6789		}
6790
6791		/*
6792		 * Calling query_addrrset() with a non-NULL dbuf is going
6793		 * to either keep or release the name.  We don't want it to
6794		 * release fname, since we may have to call query_addrrset()
6795		 * more than once.  That means we have to call query_keepname()
6796		 * now, and pass a NULL dbuf to query_addrrset().
6797		 *
6798		 * If we do a query_addrrset() below, we must set fname to
6799		 * NULL before leaving this block, otherwise we might try to
6800		 * cleanup fname even though we're using it!
6801		 */
6802		query_keepname(client, fname, dbuf);
6803		tname = fname;
6804		result = dns_rdatasetiter_first(rdsiter);
6805		while (result == ISC_R_SUCCESS) {
6806			dns_rdatasetiter_current(rdsiter, rdataset);
6807#ifdef ALLOW_FILTER_AAAA_ON_V4
6808			/*
6809			 * Notice the presence of A and AAAAs so
6810			 * that AAAAs can be hidden from IPv4 clients.
6811			 */
6812			if (client->filter_aaaa != dns_v4_aaaa_ok) {
6813				if (rdataset->type == dns_rdatatype_aaaa)
6814					have_aaaa = ISC_TRUE;
6815				else if (rdataset->type == dns_rdatatype_a)
6816					have_a = ISC_TRUE;
6817			}
6818#endif
6819			if (is_zone && qtype == dns_rdatatype_any &&
6820			    !dns_db_issecure(db) &&
6821			    dns_rdatatype_isdnssec(rdataset->type)) {
6822				/*
6823				 * The zone is transitioning from insecure
6824				 * to secure. Hide the dnssec records from
6825				 * ANY queries.
6826				 */
6827				dns_rdataset_disassociate(rdataset);
6828			} else if ((qtype == dns_rdatatype_any ||
6829			     rdataset->type == qtype) && rdataset->type != 0) {
6830#ifdef ALLOW_FILTER_AAAA_ON_V4
6831				if (dns_rdatatype_isdnssec(rdataset->type))
6832					have_sig = ISC_TRUE;
6833#endif
6834				if (NOQNAME(rdataset) && WANTDNSSEC(client))
6835					noqname = rdataset;
6836				else
6837					noqname = NULL;
6838				rpz_st = client->query.rpz_st;
6839				if (rpz_st != NULL)
6840					rdataset->ttl = ISC_MIN(rdataset->ttl,
6841							    rpz_st->m.ttl);
6842				query_addrrset(client,
6843					       fname != NULL ? &fname : &tname,
6844					       &rdataset, NULL,
6845					       NULL, DNS_SECTION_ANSWER);
6846				if (noqname != NULL)
6847					query_addnoqnameproof(client, noqname);
6848				n++;
6849				INSIST(tname != NULL);
6850				/*
6851				 * rdataset is non-NULL only in certain
6852				 * pathological cases involving DNAMEs.
6853				 */
6854				if (rdataset != NULL)
6855					query_putrdataset(client, &rdataset);
6856				rdataset = query_newrdataset(client);
6857				if (rdataset == NULL)
6858					break;
6859			} else {
6860				/*
6861				 * We're not interested in this rdataset.
6862				 */
6863				dns_rdataset_disassociate(rdataset);
6864			}
6865			result = dns_rdatasetiter_next(rdsiter);
6866		}
6867
6868#ifdef ALLOW_FILTER_AAAA_ON_V4
6869		/*
6870		 * Filter AAAAs if there is an A and there is no signature
6871		 * or we are supposed to break DNSSEC.
6872		 */
6873		if (client->filter_aaaa == dns_v4_aaaa_break_dnssec)
6874			client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
6875		else if (client->filter_aaaa != dns_v4_aaaa_ok &&
6876			 have_aaaa && have_a &&
6877			 (!have_sig || !WANTDNSSEC(client)))
6878			  client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
6879#endif
6880		if (fname != NULL)
6881			dns_message_puttempname(client->message, &fname);
6882
6883		if (n == 0) {
6884			/*
6885			 * No matching rdatasets found in cache. If we were
6886			 * searching for RRSIG/SIG, that's probably okay;
6887			 * otherwise this is an error condition.
6888			 */
6889			if ((qtype == dns_rdatatype_rrsig ||
6890			     qtype == dns_rdatatype_sig) &&
6891			    result == ISC_R_NOMORE) {
6892				if (!is_zone) {
6893					authoritative = ISC_FALSE;
6894					dns_rdatasetiter_destroy(&rdsiter);
6895					client->attributes &= ~NS_CLIENTATTR_RA;
6896					goto addauth;
6897				}
6898
6899				if (dns_db_issecure(db)) {
6900					char namebuf[DNS_NAME_FORMATSIZE];
6901					dns_name_format(client->query.qname,
6902							namebuf,
6903							sizeof(namebuf));
6904					ns_client_log(client,
6905						      DNS_LOGCATEGORY_DNSSEC,
6906						      NS_LOGMODULE_QUERY,
6907						      ISC_LOG_WARNING,
6908						      "missing signature "
6909						      "for %s", namebuf);
6910				}
6911
6912				dns_rdatasetiter_destroy(&rdsiter);
6913				fname = query_newname(client, dbuf, &b);
6914				goto nxrrset_rrsig;
6915			} else
6916				result = DNS_R_SERVFAIL;
6917		}
6918
6919		dns_rdatasetiter_destroy(&rdsiter);
6920		if (result != ISC_R_NOMORE) {
6921			QUERY_ERROR(DNS_R_SERVFAIL);
6922			goto cleanup;
6923		}
6924	} else {
6925		/*
6926		 * This is the "normal" case -- an ordinary question to which
6927		 * we know the answer.
6928		 */
6929
6930#ifdef ALLOW_FILTER_AAAA_ON_V4
6931		/*
6932		 * Optionally hide AAAAs from IPv4 clients if there is an A.
6933		 * We add the AAAAs now, but might refuse to render them later
6934		 * after DNSSEC is figured out.
6935		 * This could be more efficient, but the whole idea is
6936		 * so fundamentally wrong, unavoidably inaccurate, and
6937		 * unneeded that it is best to keep it as short as possible.
6938		 */
6939		if (client->filter_aaaa == dns_v4_aaaa_break_dnssec ||
6940		    (client->filter_aaaa == dns_v4_aaaa_filter &&
6941		     (!WANTDNSSEC(client) || sigrdataset == NULL ||
6942		     !dns_rdataset_isassociated(sigrdataset))))
6943		{
6944			if (qtype == dns_rdatatype_aaaa) {
6945				trdataset = query_newrdataset(client);
6946				result = dns_db_findrdataset(db, node, version,
6947							     dns_rdatatype_a, 0,
6948							     client->now,
6949							     trdataset, NULL);
6950				if (dns_rdataset_isassociated(trdataset))
6951					dns_rdataset_disassociate(trdataset);
6952				query_putrdataset(client, &trdataset);
6953
6954				/*
6955				 * We have an AAAA but the A is not in our cache.
6956				 * Assume any result other than DNS_R_DELEGATION
6957				 * or ISC_R_NOTFOUND means there is no A and
6958				 * so AAAAs are ok.
6959				 * Assume there is no A if we can't recurse
6960				 * for this client, although that could be
6961				 * the wrong answer. What else can we do?
6962				 * Besides, that we have the AAAA and are using
6963				 * this mechanism suggests that we care more
6964				 * about As than AAAAs and would have cached
6965				 * the A if it existed.
6966				 */
6967				if (result == ISC_R_SUCCESS) {
6968					client->attributes |=
6969						    NS_CLIENTATTR_FILTER_AAAA;
6970
6971				} else if (authoritative ||
6972					   !RECURSIONOK(client) ||
6973					   (result != DNS_R_DELEGATION &&
6974					    result != ISC_R_NOTFOUND)) {
6975					client->attributes &=
6976						    ~NS_CLIENTATTR_FILTER_AAAA;
6977				} else {
6978					/*
6979					 * This is an ugly kludge to recurse
6980					 * for the A and discard the result.
6981					 *
6982					 * Continue to add the AAAA now.
6983					 * We'll make a note to not render it
6984					 * if the recursion for the A succeeds.
6985					 */
6986					result = query_recurse(client,
6987							dns_rdatatype_a,
6988							client->query.qname,
6989							NULL, NULL, resuming);
6990					if (result == ISC_R_SUCCESS) {
6991					    client->attributes |=
6992						    NS_CLIENTATTR_FILTER_AAAA_RC;
6993					    client->query.attributes |=
6994							NS_QUERYATTR_RECURSING;
6995					}
6996				}
6997
6998			} else if (qtype == dns_rdatatype_a &&
6999				   (client->attributes &
7000					    NS_CLIENTATTR_FILTER_AAAA_RC) != 0) {
7001				client->attributes &=
7002					    ~NS_CLIENTATTR_FILTER_AAAA_RC;
7003				client->attributes |=
7004					    NS_CLIENTATTR_FILTER_AAAA;
7005				dns_rdataset_disassociate(rdataset);
7006				if (sigrdataset != NULL &&
7007				    dns_rdataset_isassociated(sigrdataset))
7008					dns_rdataset_disassociate(sigrdataset);
7009				goto cleanup;
7010			}
7011		}
7012#endif
7013		/*
7014		 * Check to see if the AAAA RRset has non-excluded addresses
7015		 * in it.  If not look for a A RRset.
7016		 */
7017		INSIST(client->query.dns64_aaaaok == NULL);
7018
7019		if (qtype == dns_rdatatype_aaaa && !dns64_exclude &&
7020		    !ISC_LIST_EMPTY(client->view->dns64) &&
7021		    client->message->rdclass == dns_rdataclass_in &&
7022		    !dns64_aaaaok(client, rdataset, sigrdataset)) {
7023			/*
7024			 * Look to see if there are A records for this
7025			 * name.
7026			 */
7027			client->query.dns64_aaaa = rdataset;
7028			client->query.dns64_sigaaaa = sigrdataset;
7029			client->query.dns64_ttl = rdataset->ttl;
7030			query_releasename(client, &fname);
7031			dns_db_detachnode(db, &node);
7032			rdataset = NULL;
7033			sigrdataset = NULL;
7034			type = qtype = dns_rdatatype_a;
7035			dns64_exclude = dns64 = ISC_TRUE;
7036			goto db_find;
7037		}
7038
7039		if (sigrdataset != NULL)
7040			sigrdatasetp = &sigrdataset;
7041		else
7042			sigrdatasetp = NULL;
7043		if (NOQNAME(rdataset) && WANTDNSSEC(client))
7044			noqname = rdataset;
7045		else
7046			noqname = NULL;
7047		/*
7048		 * BIND 8 priming queries need the additional section.
7049		 */
7050		if (is_zone && qtype == dns_rdatatype_ns &&
7051		    dns_name_equal(client->query.qname, dns_rootname))
7052			client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL;
7053
7054		if (dns64) {
7055			qtype = type = dns_rdatatype_aaaa;
7056			result = query_dns64(client, &fname, rdataset,
7057					     sigrdataset, dbuf,
7058					     DNS_SECTION_ANSWER);
7059			dns_rdataset_disassociate(rdataset);
7060			dns_message_puttemprdataset(client->message, &rdataset);
7061			if (result == ISC_R_NOMORE) {
7062#ifndef dns64_bis_return_excluded_addresses
7063				if (dns64_exclude) {
7064					if (!is_zone)
7065						goto cleanup;
7066					/*
7067					 * Add a fake SOA record.
7068					 */
7069					(void)query_addsoa(client, db, version,
7070							   600, ISC_FALSE);
7071					goto cleanup;
7072				}
7073#endif
7074				if (is_zone)
7075					goto iszone_nxrrset;
7076				else
7077					goto ncache_nxrrset;
7078			} else if (result != ISC_R_SUCCESS) {
7079				eresult = result;
7080				goto cleanup;
7081			}
7082		} else if (client->query.dns64_aaaaok != NULL) {
7083			query_filter64(client, &fname, rdataset, dbuf,
7084				       DNS_SECTION_ANSWER);
7085			query_putrdataset(client, &rdataset);
7086		} else
7087			query_addrrset(client, &fname, &rdataset,
7088				       sigrdatasetp, dbuf, DNS_SECTION_ANSWER);
7089
7090		if (noqname != NULL)
7091			query_addnoqnameproof(client, noqname);
7092		/*
7093		 * We shouldn't ever fail to add 'rdataset'
7094		 * because it's already in the answer.
7095		 */
7096		INSIST(rdataset == NULL);
7097	}
7098
7099 addauth:
7100	CTRACE("query_find: addauth");
7101	/*
7102	 * Add NS records to the authority section (if we haven't already
7103	 * added them to the answer section).
7104	 */
7105	if (!want_restart && !NOAUTHORITY(client)) {
7106		if (is_zone) {
7107			if (!((qtype == dns_rdatatype_ns ||
7108			       qtype == dns_rdatatype_any) &&
7109			      dns_name_equal(client->query.qname,
7110					     dns_db_origin(db))))
7111				(void)query_addns(client, db, version);
7112		} else if (qtype != dns_rdatatype_ns) {
7113			if (fname != NULL)
7114				query_releasename(client, &fname);
7115			query_addbestns(client);
7116		}
7117	}
7118
7119	/*
7120	 * Add NSEC records to the authority section if they're needed for
7121	 * DNSSEC wildcard proofs.
7122	 */
7123	if (need_wildcardproof && dns_db_issecure(db))
7124		query_addwildcardproof(client, db, version,
7125				       dns_fixedname_name(&wildcardname),
7126				       ISC_TRUE, ISC_FALSE);
7127 cleanup:
7128	CTRACE("query_find: cleanup");
7129	/*
7130	 * General cleanup.
7131	 */
7132	rpz_st = client->query.rpz_st;
7133	if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) {
7134		rpz_match_clear(rpz_st);
7135		rpz_st->state &= ~DNS_RPZ_DONE_QNAME;
7136	}
7137	if (rdataset != NULL)
7138		query_putrdataset(client, &rdataset);
7139	if (sigrdataset != NULL)
7140		query_putrdataset(client, &sigrdataset);
7141	if (fname != NULL)
7142		query_releasename(client, &fname);
7143	if (node != NULL)
7144		dns_db_detachnode(db, &node);
7145	if (db != NULL)
7146		dns_db_detach(&db);
7147	if (zone != NULL)
7148		dns_zone_detach(&zone);
7149	if (zdb != NULL) {
7150		query_putrdataset(client, &zrdataset);
7151		if (zsigrdataset != NULL)
7152			query_putrdataset(client, &zsigrdataset);
7153		if (zfname != NULL)
7154			query_releasename(client, &zfname);
7155		dns_db_detach(&zdb);
7156	}
7157	if (event != NULL)
7158		isc_event_free(ISC_EVENT_PTR(&event));
7159
7160	/*
7161	 * AA bit.
7162	 */
7163	if (client->query.restarts == 0 && !authoritative) {
7164		/*
7165		 * We're not authoritative, so we must ensure the AA bit
7166		 * isn't set.
7167		 */
7168		client->message->flags &= ~DNS_MESSAGEFLAG_AA;
7169	}
7170
7171	/*
7172	 * Restart the query?
7173	 */
7174	if (want_restart && client->query.restarts < MAX_RESTARTS) {
7175		client->query.restarts++;
7176		goto restart;
7177	}
7178
7179	if (eresult != ISC_R_SUCCESS &&
7180	    (!PARTIALANSWER(client) || WANTRECURSION(client))) {
7181		if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) {
7182			/*
7183			 * This was a duplicate query that we are
7184			 * recursing on.  Don't send a response now.
7185			 * The original query will still cause a response.
7186			 */
7187			query_next(client, eresult);
7188		} else {
7189			/*
7190			 * If we don't have any answer to give the client,
7191			 * or if the client requested recursion and thus wanted
7192			 * the complete answer, send an error response.
7193			 */
7194			INSIST(line >= 0);
7195			query_error(client, eresult, line);
7196		}
7197		ns_client_detach(&client);
7198	} else if (!RECURSING(client)) {
7199		/*
7200		 * We are done.  Set up sortlist data for the message
7201		 * rendering code, make a final tweak to the AA bit if the
7202		 * auth-nxdomain config option says so, then render and
7203		 * send the response.
7204		 */
7205		setup_query_sortlist(client);
7206
7207		/*
7208		 * If this is a referral and the answer to the question
7209		 * is in the glue sort it to the start of the additional
7210		 * section.
7211		 */
7212		if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) &&
7213		    client->message->rcode == dns_rcode_noerror &&
7214		    (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa))
7215			answer_in_glue(client, qtype);
7216
7217		if (client->message->rcode == dns_rcode_nxdomain &&
7218		    client->view->auth_nxdomain == ISC_TRUE)
7219			client->message->flags |= DNS_MESSAGEFLAG_AA;
7220
7221		/*
7222		 * If the response is somehow unexpected for the client and this
7223		 * is a result of recursion, return an error to the caller
7224		 * to indicate it may need to be logged.
7225		 */
7226		if (resuming &&
7227		    (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) ||
7228		     client->message->rcode != dns_rcode_noerror))
7229			eresult = ISC_R_FAILURE;
7230
7231		query_send(client);
7232		ns_client_detach(&client);
7233	}
7234	CTRACE("query_find: done");
7235
7236	return (eresult);
7237}
7238
7239static inline void
7240log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
7241	char namebuf[DNS_NAME_FORMATSIZE];
7242	char typename[DNS_RDATATYPE_FORMATSIZE];
7243	char classname[DNS_RDATACLASS_FORMATSIZE];
7244	char onbuf[ISC_NETADDR_FORMATSIZE];
7245	dns_rdataset_t *rdataset;
7246	int level = ISC_LOG_INFO;
7247
7248	if (! isc_log_wouldlog(ns_g_lctx, level))
7249		return;
7250
7251	rdataset = ISC_LIST_HEAD(client->query.qname->list);
7252	INSIST(rdataset != NULL);
7253	dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
7254	dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname));
7255	dns_rdatatype_format(rdataset->type, typename, sizeof(typename));
7256	isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf));
7257
7258	ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
7259		      level, "query: %s %s %s %s%s%s%s%s%s (%s)", namebuf,
7260		      classname, typename, WANTRECURSION(client) ? "+" : "-",
7261		      (client->signer != NULL) ? "S": "",
7262		      (client->opt != NULL) ? "E" : "",
7263		      ((client->attributes & NS_CLIENTATTR_TCP) != 0) ?
7264				 "T" : "",
7265		      ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
7266		      ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "",
7267		      onbuf);
7268}
7269
7270static inline void
7271log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) {
7272	char namebuf[DNS_NAME_FORMATSIZE];
7273	char typename[DNS_RDATATYPE_FORMATSIZE];
7274	char classname[DNS_RDATACLASS_FORMATSIZE];
7275	const char *namep, *typep, *classp, *sep1, *sep2;
7276	dns_rdataset_t *rdataset;
7277
7278	if (!isc_log_wouldlog(ns_g_lctx, level))
7279		return;
7280
7281	namep = typep = classp = sep1 = sep2 = "";
7282
7283	/*
7284	 * Query errors can happen for various reasons.  In some cases we cannot
7285	 * even assume the query contains a valid question section, so we should
7286	 * expect exceptional cases.
7287	 */
7288	if (client->query.origqname != NULL) {
7289		dns_name_format(client->query.origqname, namebuf,
7290				sizeof(namebuf));
7291		namep = namebuf;
7292		sep1 = " for ";
7293
7294		rdataset = ISC_LIST_HEAD(client->query.origqname->list);
7295		if (rdataset != NULL) {
7296			dns_rdataclass_format(rdataset->rdclass, classname,
7297					      sizeof(classname));
7298			classp = classname;
7299			dns_rdatatype_format(rdataset->type, typename,
7300					     sizeof(typename));
7301			typep = typename;
7302			sep2 = "/";
7303		}
7304	}
7305
7306	ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, NS_LOGMODULE_QUERY,
7307		      level, "query failed (%s)%s%s%s%s%s%s at %s:%d",
7308		      isc_result_totext(result), sep1, namep, sep2,
7309		      classp, sep2, typep, __FILE__, line);
7310}
7311
7312void
7313ns_query_start(ns_client_t *client) {
7314	isc_result_t result;
7315	dns_message_t *message = client->message;
7316	dns_rdataset_t *rdataset;
7317	ns_client_t *qclient;
7318	dns_rdatatype_t qtype;
7319	unsigned int saved_extflags = client->extflags;
7320	unsigned int saved_flags = client->message->flags;
7321	isc_boolean_t want_ad;
7322
7323	CTRACE("ns_query_start");
7324
7325	/*
7326	 * Test only.
7327	 */
7328	if (ns_g_clienttest && (client->attributes & NS_CLIENTATTR_TCP) == 0)
7329		RUNTIME_CHECK(ns_client_replace(client) == ISC_R_SUCCESS);
7330
7331	/*
7332	 * Ensure that appropriate cleanups occur.
7333	 */
7334	client->next = query_next_callback;
7335
7336	/*
7337	 * Behave as if we don't support DNSSEC if not enabled.
7338	 */
7339	if (!client->view->enablednssec) {
7340		message->flags &= ~DNS_MESSAGEFLAG_CD;
7341		client->extflags &= ~DNS_MESSAGEEXTFLAG_DO;
7342		if (client->opt != NULL)
7343			client->opt->ttl &= ~DNS_MESSAGEEXTFLAG_DO;
7344	}
7345
7346	if ((message->flags & DNS_MESSAGEFLAG_RD) != 0)
7347		client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
7348
7349	if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0)
7350		client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
7351
7352	if (client->view->minimalresponses)
7353		client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
7354					     NS_QUERYATTR_NOADDITIONAL);
7355
7356	if ((client->view->cachedb == NULL)
7357	    || (!client->view->additionalfromcache)) {
7358		/*
7359		 * We don't have a cache.  Turn off cache support and
7360		 * recursion.
7361		 */
7362		client->query.attributes &=
7363			~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK);
7364	} else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
7365		   (message->flags & DNS_MESSAGEFLAG_RD) == 0) {
7366		/*
7367		 * If the client isn't allowed to recurse (due to
7368		 * "recursion no", the allow-recursion ACL, or the
7369		 * lack of a resolver in this view), or if it
7370		 * doesn't want recursion, turn recursion off.
7371		 */
7372		client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
7373	}
7374
7375	/*
7376	 * Get the question name.
7377	 */
7378	result = dns_message_firstname(message, DNS_SECTION_QUESTION);
7379	if (result != ISC_R_SUCCESS) {
7380		query_error(client, result, __LINE__);
7381		return;
7382	}
7383	dns_message_currentname(message, DNS_SECTION_QUESTION,
7384				&client->query.qname);
7385	client->query.origqname = client->query.qname;
7386	result = dns_message_nextname(message, DNS_SECTION_QUESTION);
7387	if (result != ISC_R_NOMORE) {
7388		if (result == ISC_R_SUCCESS) {
7389			/*
7390			 * There's more than one QNAME in the question
7391			 * section.
7392			 */
7393			query_error(client, DNS_R_FORMERR, __LINE__);
7394		} else
7395			query_error(client, result, __LINE__);
7396		return;
7397	}
7398
7399	if (ns_g_server->log_queries)
7400		log_query(client, saved_flags, saved_extflags);
7401
7402	/*
7403	 * Check for multiple question queries, since edns1 is dead.
7404	 */
7405	if (message->counts[DNS_SECTION_QUESTION] > 1) {
7406		query_error(client, DNS_R_FORMERR, __LINE__);
7407		return;
7408	}
7409
7410	/*
7411	 * Check for meta-queries like IXFR and AXFR.
7412	 */
7413	rdataset = ISC_LIST_HEAD(client->query.qname->list);
7414	INSIST(rdataset != NULL);
7415	qtype = rdataset->type;
7416	dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype);
7417	if (dns_rdatatype_ismeta(qtype)) {
7418		switch (qtype) {
7419		case dns_rdatatype_any:
7420			break; /* Let query_find handle it. */
7421		case dns_rdatatype_ixfr:
7422		case dns_rdatatype_axfr:
7423			ns_xfr_start(client, rdataset->type);
7424			return;
7425		case dns_rdatatype_maila:
7426		case dns_rdatatype_mailb:
7427			query_error(client, DNS_R_NOTIMP, __LINE__);
7428			return;
7429		case dns_rdatatype_tkey:
7430			result = dns_tkey_processquery(client->message,
7431						ns_g_server->tkeyctx,
7432						client->view->dynamickeys);
7433			if (result == ISC_R_SUCCESS)
7434				query_send(client);
7435			else
7436				query_error(client, result, __LINE__);
7437			return;
7438		default: /* TSIG, etc. */
7439			query_error(client, DNS_R_FORMERR, __LINE__);
7440			return;
7441		}
7442	}
7443
7444	/*
7445	 * Turn on minimal response for DNSKEY and DS queries.
7446	 */
7447	if (qtype == dns_rdatatype_dnskey || qtype == dns_rdatatype_ds)
7448		client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
7449					     NS_QUERYATTR_NOADDITIONAL);
7450
7451	/*
7452	 * Turn on minimal responses for EDNS/UDP bufsize 512 queries.
7453	 */
7454	if (client->opt != NULL && client->udpsize <= 512U &&
7455	    (client->attributes & NS_CLIENTATTR_TCP) == 0)
7456		client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
7457					     NS_QUERYATTR_NOADDITIONAL);
7458
7459	/*
7460	 * If the client has requested that DNSSEC checking be disabled,
7461	 * allow lookups to return pending data and instruct the resolver
7462	 * to return data before validation has completed.
7463	 *
7464	 * We don't need to set DNS_DBFIND_PENDINGOK when validation is
7465	 * disabled as there will be no pending data.
7466	 */
7467	if (message->flags & DNS_MESSAGEFLAG_CD ||
7468	    qtype == dns_rdatatype_rrsig)
7469	{
7470		client->query.dboptions |= DNS_DBFIND_PENDINGOK;
7471		client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
7472	} else if (!client->view->enablevalidation)
7473		client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
7474
7475	/*
7476	 * Allow glue NS records to be added to the authority section
7477	 * if the answer is secure.
7478	 */
7479	if (message->flags & DNS_MESSAGEFLAG_CD)
7480		client->query.attributes &= ~NS_QUERYATTR_SECURE;
7481
7482	/*
7483	 * Set 'want_ad' if the client has set AD in the query.
7484	 * This allows AD to be returned on queries without DO set.
7485	 */
7486	if ((message->flags & DNS_MESSAGEFLAG_AD) != 0)
7487		want_ad = ISC_TRUE;
7488	else
7489		want_ad = ISC_FALSE;
7490
7491	/*
7492	 * This is an ordinary query.
7493	 */
7494	result = dns_message_reply(message, ISC_TRUE);
7495	if (result != ISC_R_SUCCESS) {
7496		query_next(client, result);
7497		return;
7498	}
7499
7500	/*
7501	 * Assume authoritative response until it is known to be
7502	 * otherwise.
7503	 *
7504	 * If "-T noaa" has been set on the command line don't set
7505	 * AA on authoritative answers.
7506	 */
7507	if (!ns_g_noaa)
7508		message->flags |= DNS_MESSAGEFLAG_AA;
7509
7510	/*
7511	 * Set AD.  We must clear it if we add non-validated data to a
7512	 * response.
7513	 */
7514	if (WANTDNSSEC(client) || want_ad)
7515		message->flags |= DNS_MESSAGEFLAG_AD;
7516
7517	qclient = NULL;
7518	ns_client_attach(client, &qclient);
7519	(void)query_find(qclient, NULL, qtype);
7520}
7521