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