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