]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/bind9/bin/named/query.c
Copy stable/9 to releng/9.3 as part of the 9.3-RELEASE cycle.
[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_createfetch2(client->view->resolver,
3876                                            qname, qtype, qdomain, nameservers,
3877                                            NULL, peeraddr, client->message->id,
3878                                            client->query.fetchoptions,
3879                                            client->task,
3880                                            query_resume, client,
3881                                            rdataset, sigrdataset,
3882                                            &client->query.fetch);
3883
3884         if (result == ISC_R_SUCCESS) {
3885                 /*
3886                  * Record that we're waiting for an event.  A client which
3887                  * is shutting down will not be destroyed until all the
3888                  * events have been received.
3889                  */
3890         } else {
3891                 query_putrdataset(client, &rdataset);
3892                 if (sigrdataset != NULL)
3893                         query_putrdataset(client, &sigrdataset);
3894         }
3895
3896         return (result);
3897 }
3898
3899 static inline void
3900 rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
3901           dns_rdataset_t **rdatasetp)
3902 {
3903         if (nodep != NULL && *nodep != NULL) {
3904                 REQUIRE(dbp != NULL && *dbp != NULL);
3905                 dns_db_detachnode(*dbp, nodep);
3906         }
3907         if (dbp != NULL && *dbp != NULL)
3908                 dns_db_detach(dbp);
3909         if (zonep != NULL && *zonep != NULL)
3910                 dns_zone_detach(zonep);
3911         if (rdatasetp != NULL && *rdatasetp != NULL &&
3912             dns_rdataset_isassociated(*rdatasetp))
3913                 dns_rdataset_disassociate(*rdatasetp);
3914 }
3915
3916 static void
3917 rpz_match_clear(dns_rpz_st_t *st)
3918 {
3919         rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
3920         st->m.version = NULL;
3921 }
3922
3923 static inline isc_result_t
3924 rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp,
3925           dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp)
3926 {
3927         REQUIRE(rdatasetp != NULL);
3928
3929         rpz_clean(zonep, dbp, nodep, rdatasetp);
3930         if (*rdatasetp == NULL) {
3931                 *rdatasetp = query_newrdataset(client);
3932                 if (*rdatasetp == NULL)
3933                         return (DNS_R_SERVFAIL);
3934         }
3935         return (ISC_R_SUCCESS);
3936 }
3937
3938 static void
3939 rpz_st_clear(ns_client_t *client) {
3940         dns_rpz_st_t *st = client->query.rpz_st;
3941
3942         if (st->m.rdataset != NULL)
3943                 query_putrdataset(client, &st->m.rdataset);
3944         rpz_match_clear(st);
3945
3946         rpz_clean(NULL, &st->r.db, NULL, NULL);
3947         if (st->r.ns_rdataset != NULL)
3948                 query_putrdataset(client, &st->r.ns_rdataset);
3949         if (st->r.r_rdataset != NULL)
3950                 query_putrdataset(client, &st->r.r_rdataset);
3951
3952         rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL);
3953         if (st->q.rdataset != NULL)
3954                 query_putrdataset(client, &st->q.rdataset);
3955         if (st->q.sigrdataset != NULL)
3956                 query_putrdataset(client, &st->q.sigrdataset);
3957         st->state = 0;
3958         st->m.type = DNS_RPZ_TYPE_BAD;
3959         st->m.policy = DNS_RPZ_POLICY_MISS;
3960 }
3961
3962 /*
3963  * Get NS, A, or AAAA rrset for response policy zone checks.
3964  */
3965 static isc_result_t
3966 rpz_rrset_find(ns_client_t *client, dns_rpz_type_t rpz_type,
3967                dns_name_t *name, dns_rdatatype_t type,
3968                dns_db_t **dbp, dns_dbversion_t *version,
3969                dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
3970 {
3971         dns_rpz_st_t *st;
3972         isc_boolean_t is_zone;
3973         dns_dbnode_t *node;
3974         dns_fixedname_t fixed;
3975         dns_name_t *found;
3976         isc_result_t result;
3977         dns_clientinfomethods_t cm;
3978         dns_clientinfo_t ci;
3979
3980         dns_clientinfomethods_init(&cm, ns_client_sourceip);
3981         dns_clientinfo_init(&ci, client);
3982
3983         st = client->query.rpz_st;
3984         if ((st->state & DNS_RPZ_RECURSING) != 0) {
3985                 INSIST(st->r.r_type == type);
3986                 INSIST(dns_name_equal(name, st->r_name));
3987                 INSIST(*rdatasetp == NULL ||
3988                        !dns_rdataset_isassociated(*rdatasetp));
3989                 st->state &= ~DNS_RPZ_RECURSING;
3990                 *dbp = st->r.db;
3991                 st->r.db = NULL;
3992                 if (*rdatasetp != NULL)
3993                         query_putrdataset(client, rdatasetp);
3994                 *rdatasetp = st->r.r_rdataset;
3995                 st->r.r_rdataset = NULL;
3996                 result = st->r.r_result;
3997                 if (result == DNS_R_DELEGATION) {
3998                         rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
3999                                      rpz_type, name,
4000                                      "rpz_rrset_find(1) ", result);
4001                         st->m.policy = DNS_RPZ_POLICY_ERROR;
4002                         result = DNS_R_SERVFAIL;
4003                 }
4004                 return (result);
4005         }
4006
4007         result = rpz_ready(client, NULL, NULL, NULL, rdatasetp);
4008         if (result != ISC_R_SUCCESS) {
4009                 st->m.policy = DNS_RPZ_POLICY_ERROR;
4010                 return (result);
4011         }
4012         if (*dbp != NULL) {
4013                 is_zone = ISC_FALSE;
4014         } else {
4015                 dns_zone_t *zone;
4016
4017                 version = NULL;
4018                 zone = NULL;
4019                 result = query_getdb(client, name, type, 0, &zone, dbp,
4020                                      &version, &is_zone);
4021                 if (result != ISC_R_SUCCESS) {
4022                         rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4023                                      rpz_type, name,
4024                                      "rpz_rrset_find(2) ", result);
4025                         st->m.policy = DNS_RPZ_POLICY_ERROR;
4026                         if (zone != NULL)
4027                                 dns_zone_detach(&zone);
4028                         return (result);
4029                 }
4030                 if (zone != NULL)
4031                         dns_zone_detach(&zone);
4032         }
4033
4034         node = NULL;
4035         dns_fixedname_init(&fixed);
4036         found = dns_fixedname_name(&fixed);
4037         result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK,
4038                                 client->now, &node, found,
4039                                 &cm, &ci, *rdatasetp, NULL);
4040         if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) {
4041                 /*
4042                  * Try the cache if we're authoritative for an
4043                  * ancestor but not the domain itself.
4044                  */
4045                 rpz_clean(NULL, dbp, &node, rdatasetp);
4046                 version = NULL;
4047                 dns_db_attach(client->view->cachedb, dbp);
4048                 result = dns_db_findext(*dbp, name, version, dns_rdatatype_ns,
4049                                         0, client->now, &node, found,
4050                                         &cm, &ci, *rdatasetp, NULL);
4051         }
4052         rpz_clean(NULL, dbp, &node, NULL);
4053         if (result == DNS_R_DELEGATION) {
4054                 rpz_clean(NULL, NULL, NULL, rdatasetp);
4055                 /*
4056                  * Recurse for NS rrset or A or AAAA rrset for an NS.
4057                  * Do not recurse for addresses for the query name.
4058                  */
4059                 if (rpz_type == DNS_RPZ_TYPE_IP) {
4060                         result = DNS_R_NXRRSET;
4061                 } else {
4062                         dns_name_copy(name, st->r_name, NULL);
4063                         result = query_recurse(client, type, st->r_name,
4064                                                NULL, NULL, resuming);
4065                         if (result == ISC_R_SUCCESS) {
4066                                 st->state |= DNS_RPZ_RECURSING;
4067                                 result = DNS_R_DELEGATION;
4068                         }
4069                 }
4070         }
4071         return (result);
4072 }
4073
4074 /*
4075  * Check the IP address in an A or AAAA rdataset against
4076  * the IP or NSIP response policy rules of a view.
4077  */
4078 static isc_result_t
4079 rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset,
4080                dns_rpz_type_t rpz_type)
4081 {
4082         dns_rpz_st_t *st;
4083         dns_dbversion_t *version;
4084         dns_zone_t *zone;
4085         dns_db_t *db;
4086         dns_rpz_zone_t *rpz;
4087         isc_result_t result;
4088
4089         st = client->query.rpz_st;
4090         if (st->m.rdataset == NULL) {
4091                 st->m.rdataset = query_newrdataset(client);
4092                 if (st->m.rdataset == NULL)
4093                         return (DNS_R_SERVFAIL);
4094         }
4095         zone = NULL;
4096         db = NULL;
4097         for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
4098              rpz != NULL;
4099              rpz = ISC_LIST_NEXT(rpz, link)) {
4100                 if (!RECURSIONOK(client) && rpz->recursive_only)
4101                         continue;
4102
4103                 /*
4104                  * Do not check policy zones that cannot replace a policy
4105                  * already known to match.
4106                  */
4107                 if (st->m.policy != DNS_RPZ_POLICY_MISS) {
4108                         if (st->m.rpz->num < rpz->num)
4109                                 break;
4110                         if (st->m.rpz->num == rpz->num &&
4111                             st->m.type < rpz_type)
4112                                 continue;
4113                 }
4114
4115                 /*
4116                  * Find the database for this policy zone to get its radix tree.
4117                  */
4118                 version = NULL;
4119                 result = rpz_getdb(client, rpz_type, &rpz->origin,
4120                                    &zone, &db, &version);
4121                 if (result != ISC_R_SUCCESS) {
4122                         rpz_clean(&zone, &db, NULL, NULL);
4123                         continue;
4124                 }
4125                 /*
4126                  * Look for a better (e.g. longer prefix) hit for an IP address
4127                  * in this rdataset in this radix tree than than the previous
4128                  * hit, if any.  Note the domain name and quality of the
4129                  * best hit.
4130                  */
4131                 dns_db_rpz_findips(rpz, rpz_type, zone, db, version,
4132                                    rdataset, st, client->query.rpz_st->qname);
4133                 rpz_clean(&zone, &db, NULL, NULL);
4134         }
4135         return (ISC_R_SUCCESS);
4136 }
4137
4138 /*
4139  * Look for an A or AAAA rdataset
4140  * and check for IP or NSIP rewrite policy rules.
4141  */
4142 static isc_result_t
4143 rpz_rewrite_rrset(ns_client_t *client, dns_rpz_type_t rpz_type,
4144                   dns_rdatatype_t type, dns_name_t *name,
4145                   dns_db_t **dbp, dns_dbversion_t *version,
4146                   dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
4147 {
4148         isc_result_t result;
4149
4150         result = rpz_rrset_find(client, rpz_type, name, type, dbp, version,
4151                                 rdatasetp, resuming);
4152         switch (result) {
4153         case ISC_R_SUCCESS:
4154         case DNS_R_GLUE:
4155         case DNS_R_ZONECUT:
4156                 result = rpz_rewrite_ip(client, *rdatasetp, rpz_type);
4157                 break;
4158         case DNS_R_EMPTYNAME:
4159         case DNS_R_EMPTYWILD:
4160         case DNS_R_NXDOMAIN:
4161         case DNS_R_NCACHENXDOMAIN:
4162         case DNS_R_NXRRSET:
4163         case DNS_R_NCACHENXRRSET:
4164         case ISC_R_NOTFOUND:
4165                 result = ISC_R_SUCCESS;
4166                 break;
4167         case DNS_R_DELEGATION:
4168         case DNS_R_DUPLICATE:
4169         case DNS_R_DROP:
4170                 break;
4171         case DNS_R_CNAME:
4172         case DNS_R_DNAME:
4173                 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, rpz_type,
4174                              name, "NS address rewrite rrset ", result);
4175                 result = ISC_R_SUCCESS;
4176                 break;
4177         default:
4178                 if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
4179                         client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR;
4180                         rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
4181                                      name, "NS address rewrite rrset ", result);
4182                 }
4183                 break;
4184         }
4185         return (result);
4186 }
4187
4188 /*
4189  * Look for both A and AAAA rdatasets
4190  * and check for IP or NSIP rewrite policy rules.
4191  * Look only for addresses that will be in the ANSWER section
4192  * when checking for IP rules.
4193  */
4194 static isc_result_t
4195 rpz_rewrite_rrsets(ns_client_t *client, dns_rpz_type_t rpz_type,
4196                    dns_name_t *name, dns_rdatatype_t type,
4197                    dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
4198 {
4199         dns_rpz_st_t *st;
4200         dns_dbversion_t *version;
4201         dns_db_t *ipdb;
4202         isc_result_t result;
4203
4204         st = client->query.rpz_st;
4205         version = NULL;
4206         ipdb = NULL;
4207         if ((st->state & DNS_RPZ_DONE_IPv4) == 0 &&
4208             ((rpz_type == DNS_RPZ_TYPE_NSIP) ?
4209              (st->state & DNS_RPZ_HAVE_NSIPv4) :
4210              (st->state & DNS_RPZ_HAVE_IP)) != 0 &&
4211             (type == dns_rdatatype_any || type == dns_rdatatype_a)) {
4212                 result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_a,
4213                                            name, &ipdb, version, rdatasetp,
4214                                            resuming);
4215                 if (result == ISC_R_SUCCESS)
4216                         st->state |= DNS_RPZ_DONE_IPv4;
4217         } else {
4218                 result = ISC_R_SUCCESS;
4219         }
4220         if (result == ISC_R_SUCCESS &&
4221             ((rpz_type == DNS_RPZ_TYPE_NSIP) ?
4222              (st->state & DNS_RPZ_HAVE_NSIPv6) :
4223              (st->state & DNS_RPZ_HAVE_IP)) != 0 &&
4224             (type == dns_rdatatype_any || type == dns_rdatatype_aaaa)) {
4225                 result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_aaaa,
4226                                            name, &ipdb, version, rdatasetp,
4227                                            resuming);
4228         }
4229         if (ipdb != NULL)
4230                 dns_db_detach(&ipdb);
4231         return (result);
4232 }
4233
4234 /*
4235  * Get the rrset from a response policy zone.
4236  */
4237 static isc_result_t
4238 rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
4239          dns_name_t *sname, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
4240          dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
4241          dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
4242          dns_rpz_policy_t *policyp)
4243 {
4244         dns_rpz_policy_t policy;
4245         dns_fixedname_t fixed;
4246         dns_name_t *found;
4247         isc_result_t result;
4248         dns_clientinfomethods_t cm;
4249         dns_clientinfo_t ci;
4250
4251         REQUIRE(nodep != NULL);
4252
4253         dns_clientinfomethods_init(&cm, ns_client_sourceip);
4254         dns_clientinfo_init(&ci, client);
4255
4256         result = rpz_ready(client, zonep, dbp, nodep, rdatasetp);
4257         if (result != ISC_R_SUCCESS) {
4258                 *policyp = DNS_RPZ_POLICY_ERROR;
4259                 return (result);
4260         }
4261
4262         /*
4263          * Try to get either a CNAME or the type of record demanded by the
4264          * request from the policy zone.
4265          */
4266         *versionp = NULL;
4267         result = rpz_getdb(client, rpz_type, qnamef, zonep, dbp, versionp);
4268         if (result != ISC_R_SUCCESS) {
4269                 *policyp = DNS_RPZ_POLICY_MISS;
4270                 return (DNS_R_NXDOMAIN);
4271         }
4272
4273         dns_fixedname_init(&fixed);
4274         found = dns_fixedname_name(&fixed);
4275         result = dns_db_findext(*dbp, qnamef, *versionp, dns_rdatatype_any, 0,
4276                                 client->now, nodep, found, &cm, &ci,
4277                                 *rdatasetp, NULL);
4278         if (result == ISC_R_SUCCESS) {
4279                 dns_rdatasetiter_t *rdsiter;
4280
4281                 rdsiter = NULL;
4282                 result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0,
4283                                              &rdsiter);
4284                 if (result != ISC_R_SUCCESS) {
4285                         dns_db_detachnode(*dbp, nodep);
4286                         rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
4287                                      qnamef, "allrdatasets() ", result);
4288                         *policyp = DNS_RPZ_POLICY_ERROR;
4289                         return (DNS_R_SERVFAIL);
4290                 }
4291                 for (result = dns_rdatasetiter_first(rdsiter);
4292                      result == ISC_R_SUCCESS;
4293                      result = dns_rdatasetiter_next(rdsiter)) {
4294                         dns_rdatasetiter_current(rdsiter, *rdatasetp);
4295                         if ((*rdatasetp)->type == dns_rdatatype_cname ||
4296                             (*rdatasetp)->type == qtype)
4297                                 break;
4298                         dns_rdataset_disassociate(*rdatasetp);
4299                 }
4300                 dns_rdatasetiter_destroy(&rdsiter);
4301                 if (result != ISC_R_SUCCESS) {
4302                         if (result != ISC_R_NOMORE) {
4303                                 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4304                                              rpz_type, qnamef, "rdatasetiter ",
4305                                              result);
4306                                 *policyp = DNS_RPZ_POLICY_ERROR;
4307                                 return (DNS_R_SERVFAIL);
4308                         }
4309                         /*
4310                          * Ask again to get the right DNS_R_DNAME/NXRRSET/...
4311                          * result if there is neither a CNAME nor target type.
4312                          */
4313                         if (dns_rdataset_isassociated(*rdatasetp))
4314                                 dns_rdataset_disassociate(*rdatasetp);
4315                         dns_db_detachnode(*dbp, nodep);
4316
4317                         if (qtype == dns_rdatatype_rrsig ||
4318                             qtype == dns_rdatatype_sig)
4319                                 result = DNS_R_NXRRSET;
4320                         else
4321                                 result = dns_db_findext(*dbp, qnamef, *versionp,
4322                                                         qtype, 0, client->now,
4323                                                         nodep, found, &cm, &ci,
4324                                                         *rdatasetp, NULL);
4325                 }
4326         }
4327         switch (result) {
4328         case ISC_R_SUCCESS:
4329                 if ((*rdatasetp)->type != dns_rdatatype_cname) {
4330                         policy = DNS_RPZ_POLICY_RECORD;
4331                 } else {
4332                         policy = dns_rpz_decode_cname(rpz, *rdatasetp, sname);
4333                         if ((policy == DNS_RPZ_POLICY_RECORD ||
4334                              policy == DNS_RPZ_POLICY_WILDCNAME) &&
4335                             qtype != dns_rdatatype_cname &&
4336                             qtype != dns_rdatatype_any)
4337                                 result = DNS_R_CNAME;
4338                 }
4339                 break;
4340         case DNS_R_NXRRSET:
4341                 policy = DNS_RPZ_POLICY_NODATA;
4342                 break;
4343         case DNS_R_DNAME:
4344                 /*
4345                  * DNAME policy RRs have very few if any uses that are not
4346                  * better served with simple wildcards.  Making the work would
4347                  * require complications to get the number of labels matched
4348                  * in the name or the found name to the main DNS_R_DNAME case
4349                  * in query_find().
4350                  */
4351                 dns_rdataset_disassociate(*rdatasetp);
4352                 dns_db_detachnode(*dbp, nodep);
4353                 /*
4354                  * Fall through to treat it as a miss.
4355                  */
4356         case DNS_R_NXDOMAIN:
4357         case DNS_R_EMPTYNAME:
4358                 /*
4359                  * If we don't get a qname hit,
4360                  * see if it is worth looking for other types.
4361                  */
4362                 (void)dns_db_rpz_enabled(*dbp, client->query.rpz_st);
4363                 dns_db_detach(dbp);
4364                 dns_zone_detach(zonep);
4365                 result = DNS_R_NXDOMAIN;
4366                 policy = DNS_RPZ_POLICY_MISS;
4367                 break;
4368         default:
4369                 dns_db_detach(dbp);
4370                 dns_zone_detach(zonep);
4371                 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, qnamef,
4372                              "", result);
4373                 return (DNS_R_SERVFAIL);
4374         }
4375
4376         *policyp = policy;
4377         return (result);
4378 }
4379
4380 /*
4381  * Build and look for a QNAME or NSDNAME owner name in a response policy zone.
4382  */
4383 static isc_result_t
4384 rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
4385                  dns_rpz_type_t rpz_type, dns_rdataset_t **rdatasetp)
4386 {
4387         dns_rpz_st_t *st;
4388         dns_rpz_zone_t *rpz;
4389         dns_fixedname_t prefixf, rpz_qnamef;
4390         dns_name_t *prefix, *suffix, *rpz_qname;
4391         dns_zone_t *zone;
4392         dns_db_t *db;
4393         dns_dbversion_t *version;
4394         dns_dbnode_t *node;
4395         dns_rpz_policy_t policy;
4396         unsigned int labels;
4397         isc_result_t result;
4398
4399         st = client->query.rpz_st;
4400         zone = NULL;
4401         db = NULL;
4402         node = NULL;
4403
4404         for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
4405              rpz != NULL;
4406              rpz = ISC_LIST_NEXT(rpz, link)) {
4407                 if (!RECURSIONOK(client) && rpz->recursive_only)
4408                         continue;
4409
4410                 /*
4411                  * Do not check policy zones that cannot replace a policy
4412                  * already known to match.
4413                  */
4414                 if (st->m.policy != DNS_RPZ_POLICY_MISS) {
4415                         if (st->m.rpz->num < rpz->num)
4416                                 break;
4417                         if (st->m.rpz->num == rpz->num &&
4418                             st->m.type < rpz_type)
4419                                 continue;
4420                 }
4421                 /*
4422                  * Construct the policy's owner name.
4423                  */
4424                 dns_fixedname_init(&prefixf);
4425                 prefix = dns_fixedname_name(&prefixf);
4426                 dns_name_split(qname, 1, prefix, NULL);
4427                 if (rpz_type == DNS_RPZ_TYPE_NSDNAME)
4428                         suffix = &rpz->nsdname;
4429                 else
4430                         suffix = &rpz->origin;
4431                 dns_fixedname_init(&rpz_qnamef);
4432                 rpz_qname = dns_fixedname_name(&rpz_qnamef);
4433                 for (;;) {
4434                         result = dns_name_concatenate(prefix, suffix,
4435                                                       rpz_qname, NULL);
4436                         if (result == ISC_R_SUCCESS)
4437                                 break;
4438                         INSIST(result == DNS_R_NAMETOOLONG);
4439                         /*
4440                          * Trim the name until it is not too long.
4441                          */
4442                         labels = dns_name_countlabels(prefix);
4443                         if (labels < 2) {
4444                                 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4445                                              rpz_type, suffix,
4446                                              "concatentate() ", result);
4447                                 return (ISC_R_SUCCESS);
4448                         }
4449                         if (labels+1 == dns_name_countlabels(qname)) {
4450                                 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1,
4451                                              rpz_type, suffix,
4452                                              "concatentate() ", result);
4453                         }
4454                         dns_name_split(prefix, labels - 1, NULL, prefix);
4455                 }
4456
4457                 /*
4458                  * See if the policy record exists and get its policy.
4459                  */
4460                 result = rpz_find(client, qtype, rpz_qname, qname, rpz,
4461                                   rpz_type, &zone, &db, &version, &node,
4462                                   rdatasetp, &policy);
4463                 switch (result) {
4464                 case DNS_R_NXDOMAIN:
4465                         break;
4466                 case DNS_R_SERVFAIL:
4467                         rpz_clean(&zone, &db, &node, rdatasetp);
4468                         st->m.policy = DNS_RPZ_POLICY_ERROR;
4469                         return (DNS_R_SERVFAIL);
4470                 default:
4471                         /*
4472                          * We are dealing with names here.
4473                          * With more than one applicable policy, prefer
4474                          * the earliest configured policy,
4475                          * QNAME over IP over NSDNAME over NSIP,
4476                          * and the smallest name.
4477                          * Because of the testing above,
4478                          * we known st->m.rpz->num >= rpz->num  and either
4479                          * st->m.rpz->num > rpz->num or st->m.type >= rpz_type
4480                          */
4481                         if (st->m.policy != DNS_RPZ_POLICY_MISS &&
4482                             rpz->num == st->m.rpz->num &&
4483                             (st->m.type < rpz_type ||
4484                              (st->m.type == rpz_type &&
4485                               0 >= dns_name_compare(rpz_qname, st->qname))))
4486                                 continue;
4487 #if 0
4488                         /*
4489                          * This code would block a customer reported information
4490                          * leak of rpz rules by rewriting requests in the
4491                          * rpz-ip, rpz-nsip, rpz-nsdname,and rpz-passthru TLDs.
4492                          * Without this code, a bad guy could request
4493                          * 24.0.3.2.10.rpz-ip. to find the policy rule for
4494                          * 10.2.3.0/14.  It is an insignificant leak and this
4495                          * code is not worth its cost, because the bad guy
4496                          * could publish "evil.com A 10.2.3.4" and request
4497                          * evil.com to get the same information.
4498                          * Keep code with "#if 0" in case customer demand
4499                          * is irresistible.
4500                          *
4501                          * We have the less frequent case of a triggered
4502                          * policy.  Check that we have not trigger on one
4503                          * of the pretend RPZ TLDs.
4504                          * This test would make it impossible to rewrite
4505                          * names in TLDs that start with "rpz-" should
4506                          * ICANN ever allow such TLDs.
4507                          */
4508                         labels = dns_name_countlabels(qname);
4509                         if (labels >= 2) {
4510                                 dns_label_t label;
4511
4512                                 dns_name_getlabel(qname, labels-2, &label);
4513                                 if (label.length >= sizeof(DNS_RPZ_PREFIX)-1 &&
4514                                     strncasecmp((const char *)label.base+1,
4515                                                 DNS_RPZ_PREFIX,
4516                                                 sizeof(DNS_RPZ_PREFIX)-1) == 0)
4517                                         continue;
4518                         }
4519 #endif
4520                         /*
4521                          * Merely log DNS_RPZ_POLICY_DISABLED hits.
4522                          */
4523                         if (rpz->policy == DNS_RPZ_POLICY_DISABLED) {
4524                                 rpz_log_rewrite(client, ISC_TRUE, policy,
4525                                                 rpz_type, zone, rpz_qname);
4526                                 continue;
4527                         }
4528
4529                         rpz_match_clear(st);
4530                         st->m.rpz = rpz;
4531                         st->m.type = rpz_type;
4532                         st->m.prefix = 0;
4533                         st->m.policy = policy;
4534                         st->m.result = result;
4535                         dns_name_copy(rpz_qname, st->qname, NULL);
4536                         if (*rdatasetp != NULL &&
4537                             dns_rdataset_isassociated(*rdatasetp)) {
4538                                 dns_rdataset_t *trdataset;
4539
4540                                 trdataset = st->m.rdataset;
4541                                 st->m.rdataset = *rdatasetp;
4542                                 *rdatasetp = trdataset;
4543                                 st->m.ttl = ISC_MIN(st->m.rdataset->ttl,
4544                                                     rpz->max_policy_ttl);
4545                         } else {
4546                                 st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT,
4547                                                     rpz->max_policy_ttl);
4548                         }
4549                         st->m.node = node;
4550                         node = NULL;
4551                         st->m.db = db;
4552                         db = NULL;
4553                         st->m.version = version;
4554                         st->m.zone = zone;
4555                         zone = NULL;
4556                 }
4557         }
4558
4559         rpz_clean(&zone, &db, &node, rdatasetp);
4560         return (ISC_R_SUCCESS);
4561 }
4562
4563 static void
4564 rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname,
4565                     isc_result_t result, int level, const char *str)
4566 {
4567         dns_rpz_st_t *st;
4568
4569         st = client->query.rpz_st;
4570
4571         if (str != NULL)
4572                 rpz_log_fail(client, level, DNS_RPZ_TYPE_NSIP, nsname,
4573                              str, result);
4574         if (st->r.ns_rdataset != NULL &&
4575             dns_rdataset_isassociated(st->r.ns_rdataset))
4576                 dns_rdataset_disassociate(st->r.ns_rdataset);
4577
4578         st->r.label--;
4579 }
4580
4581 /*
4582  * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting.
4583  */
4584 static isc_result_t
4585 rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult,
4586             isc_boolean_t resuming)
4587 {
4588         dns_rpz_st_t *st;
4589         dns_rdataset_t *rdataset;
4590         dns_fixedname_t nsnamef;
4591         dns_name_t *nsname;
4592         isc_boolean_t ck_ip;
4593         isc_result_t result;
4594
4595         st = client->query.rpz_st;
4596         if (st == NULL) {
4597                 st = isc_mem_get(client->mctx, sizeof(*st));
4598                 if (st == NULL)
4599                         return (ISC_R_NOMEMORY);
4600                 st->state = 0;
4601                 memset(&st->m, 0, sizeof(st->m));
4602                 st->m.type = DNS_RPZ_TYPE_BAD;
4603                 st->m.policy = DNS_RPZ_POLICY_MISS;
4604                 st->m.ttl = ~0;
4605                 memset(&st->r, 0, sizeof(st->r));
4606                 memset(&st->q, 0, sizeof(st->q));
4607                 dns_fixedname_init(&st->_qnamef);
4608                 dns_fixedname_init(&st->_r_namef);
4609                 dns_fixedname_init(&st->_fnamef);
4610                 st->qname = dns_fixedname_name(&st->_qnamef);
4611                 st->r_name = dns_fixedname_name(&st->_r_namef);
4612                 st->fname = dns_fixedname_name(&st->_fnamef);
4613                 client->query.rpz_st = st;
4614         }
4615
4616         /*
4617          * There is nothing to rewrite if the main query failed.
4618          */
4619         switch (qresult) {
4620         case ISC_R_SUCCESS:
4621         case DNS_R_GLUE:
4622         case DNS_R_ZONECUT:
4623                 ck_ip = ISC_TRUE;
4624                 break;
4625         case DNS_R_EMPTYNAME:
4626         case DNS_R_NXRRSET:
4627         case DNS_R_NXDOMAIN:
4628         case DNS_R_EMPTYWILD:
4629         case DNS_R_NCACHENXDOMAIN:
4630         case DNS_R_NCACHENXRRSET:
4631         case DNS_R_CNAME:
4632         case DNS_R_DNAME:
4633                 ck_ip = ISC_FALSE;
4634                 break;
4635         case DNS_R_DELEGATION:
4636         case ISC_R_NOTFOUND:
4637                 return (ISC_R_SUCCESS);
4638         case ISC_R_FAILURE:
4639         case ISC_R_TIMEDOUT:
4640         case DNS_R_BROKENCHAIN:
4641                 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, DNS_RPZ_TYPE_QNAME,
4642                              client->query.qname,
4643                              "stop on qresult in rpz_rewrite() ",
4644                              qresult);
4645                 return (ISC_R_SUCCESS);
4646         default:
4647                 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, DNS_RPZ_TYPE_QNAME,
4648                              client->query.qname,
4649                              "stop on unrecognized qresult in rpz_rewrite() ",
4650                              qresult);
4651                 return (ISC_R_SUCCESS);
4652         }
4653
4654         rdataset = NULL;
4655         if ((st->state & DNS_RPZ_DONE_QNAME) == 0) {
4656                 /*
4657                  * Check rules for the query name if this is the first time
4658                  * for the current qname, i.e. we've not been recursing.
4659                  * There is a first time for each name in a CNAME chain.
4660                  */
4661                 result = rpz_rewrite_name(client, qtype, client->query.qname,
4662                                           DNS_RPZ_TYPE_QNAME, &rdataset);
4663                 if (result != ISC_R_SUCCESS)
4664                         goto cleanup;
4665
4666                 st->r.label = dns_name_countlabels(client->query.qname);
4667
4668                 st->state &= ~(DNS_RPZ_DONE_QNAME_IP | DNS_RPZ_DONE_IPv4);
4669                 st->state |= DNS_RPZ_DONE_QNAME;
4670         }
4671
4672         /*
4673          * Check known IP addresses for the query name.
4674          * Any recursion required for the query has already happened.
4675          * Do not check addresses that will not be in the ANSWER section.
4676          */
4677         if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 &&
4678             (st->state & DNS_RPZ_HAVE_IP) != 0 && ck_ip) {
4679                 result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_IP,
4680                                             client->query.qname, qtype,
4681                                             &rdataset, resuming);
4682                 if (result != ISC_R_SUCCESS)
4683                         goto cleanup;
4684                 st->state &= ~DNS_RPZ_DONE_IPv4;
4685                 st->state |= DNS_RPZ_DONE_QNAME_IP;
4686         }
4687
4688         /*
4689          * Stop looking for rules if there are none of the other kinds.
4690          */
4691         if ((st->state & (DNS_RPZ_HAVE_NSIPv4 | DNS_RPZ_HAVE_NSIPv6 |
4692                           DNS_RPZ_HAVE_NSDNAME)) == 0) {
4693                 result = ISC_R_SUCCESS;
4694                 goto cleanup;
4695         }
4696
4697         dns_fixedname_init(&nsnamef);
4698         dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef));
4699         while (st->r.label > client->view->rpz_min_ns_labels) {
4700                 /*
4701                  * Get NS rrset for each domain in the current qname.
4702                  */
4703                 if (st->r.label == dns_name_countlabels(client->query.qname)) {
4704                         nsname = client->query.qname;
4705                 } else {
4706                         nsname = dns_fixedname_name(&nsnamef);
4707                         dns_name_split(client->query.qname, st->r.label,
4708                                        NULL, nsname);
4709                 }
4710                 if (st->r.ns_rdataset == NULL ||
4711                     !dns_rdataset_isassociated(st->r.ns_rdataset)) {
4712                         dns_db_t *db = NULL;
4713                         result = rpz_rrset_find(client, DNS_RPZ_TYPE_NSDNAME,
4714                                                 nsname, dns_rdatatype_ns,
4715                                                 &db, NULL, &st->r.ns_rdataset,
4716                                                 resuming);
4717                         if (db != NULL)
4718                                 dns_db_detach(&db);
4719                         if (st->m.policy == DNS_RPZ_POLICY_ERROR)
4720                                 goto cleanup;
4721                         switch (result) {
4722                         case ISC_R_SUCCESS:
4723                                 result = dns_rdataset_first(st->r.ns_rdataset);
4724                                 if (result != ISC_R_SUCCESS)
4725                                         goto cleanup;
4726                                 st->state &= ~(DNS_RPZ_DONE_NSDNAME |
4727                                                DNS_RPZ_DONE_IPv4);
4728                                 break;
4729                         case DNS_R_DELEGATION:
4730                                 goto cleanup;
4731                         case DNS_R_EMPTYNAME:
4732                         case DNS_R_NXRRSET:
4733                         case DNS_R_EMPTYWILD:
4734                         case DNS_R_NXDOMAIN:
4735                         case DNS_R_NCACHENXDOMAIN:
4736                         case DNS_R_NCACHENXRRSET:
4737                         case ISC_R_NOTFOUND:
4738                         case DNS_R_CNAME:
4739                         case DNS_R_DNAME:
4740                                 rpz_rewrite_ns_skip(client, nsname, result,
4741                                                     0, NULL);
4742                                 continue;
4743                         case ISC_R_TIMEDOUT:
4744                         case DNS_R_BROKENCHAIN:
4745                         case ISC_R_FAILURE:
4746                                 rpz_rewrite_ns_skip(client, nsname, result,
4747                                                 DNS_RPZ_DEBUG_LEVEL3,
4748                                                 "NS db_find() ");
4749                                 continue;
4750                         default:
4751                                 rpz_rewrite_ns_skip(client, nsname, result,
4752                                                 DNS_RPZ_INFO_LEVEL,
4753                                                 "unrecognized NS db_find() ");
4754                                 continue;
4755                         }
4756                 }
4757                 /*
4758                  * Check all NS names.
4759                  */
4760                 do {
4761                         dns_rdata_ns_t ns;
4762                         dns_rdata_t nsrdata = DNS_RDATA_INIT;
4763
4764                         dns_rdataset_current(st->r.ns_rdataset, &nsrdata);
4765                         result = dns_rdata_tostruct(&nsrdata, &ns, NULL);
4766                         dns_rdata_reset(&nsrdata);
4767                         if (result != ISC_R_SUCCESS) {
4768                                 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
4769                                              DNS_RPZ_TYPE_NSIP, nsname,
4770                                              "rdata_tostruct() ", result);
4771                                 st->m.policy = DNS_RPZ_POLICY_ERROR;
4772                                 goto cleanup;
4773                         }
4774                         /*
4775                          * Do nothing about "NS ."
4776                          */
4777                         if (dns_name_equal(&ns.name, dns_rootname)) {
4778                                 dns_rdata_freestruct(&ns);
4779                                 result = dns_rdataset_next(st->r.ns_rdataset);
4780                                 continue;
4781                         }
4782                         /*
4783                          * Check this NS name if we did not handle it
4784                          * during a previous recursion.
4785                          */
4786                         if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0 &&
4787                             (st->state & DNS_RPZ_HAVE_NSDNAME) != 0) {
4788                                 result = rpz_rewrite_name(client, qtype,
4789                                                         &ns.name,
4790                                                         DNS_RPZ_TYPE_NSDNAME,
4791                                                         &rdataset);
4792                                 if (result != ISC_R_SUCCESS) {
4793                                         dns_rdata_freestruct(&ns);
4794                                         goto cleanup;
4795                                 }
4796                                 st->state |= DNS_RPZ_DONE_NSDNAME;
4797                         }
4798                         /*
4799                          * Check all IP addresses for this NS name.
4800                          */
4801                         result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_NSIP,
4802                                                     &ns.name, dns_rdatatype_any,
4803                                                     &rdataset, resuming);
4804                         dns_rdata_freestruct(&ns);
4805                         if (result != ISC_R_SUCCESS)
4806                                 goto cleanup;
4807                         st->state &= ~(DNS_RPZ_DONE_NSDNAME |
4808                                        DNS_RPZ_DONE_IPv4);
4809                         result = dns_rdataset_next(st->r.ns_rdataset);
4810                 } while (result == ISC_R_SUCCESS);
4811                 dns_rdataset_disassociate(st->r.ns_rdataset);
4812                 st->r.label--;
4813         }
4814
4815         /*
4816          * Use the best, if any, hit.
4817          */
4818         result = ISC_R_SUCCESS;
4819
4820 cleanup:
4821         if (st->m.policy != DNS_RPZ_POLICY_MISS &&
4822             st->m.policy != DNS_RPZ_POLICY_ERROR &&
4823             st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN)
4824                 st->m.policy = st->m.rpz->policy;
4825         if (st->m.policy == DNS_RPZ_POLICY_MISS ||
4826             st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
4827             st->m.policy == DNS_RPZ_POLICY_ERROR) {
4828                 if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
4829                     result != DNS_R_DELEGATION)
4830                         rpz_log_rewrite(client, ISC_FALSE, st->m.policy,
4831                                         st->m.type, st->m.zone, st->qname);
4832                 rpz_match_clear(st);
4833         }
4834         if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
4835                 st->m.type = DNS_RPZ_TYPE_BAD;
4836                 result = DNS_R_SERVFAIL;
4837         }
4838         query_putrdataset(client, &rdataset);
4839         if ((st->state & DNS_RPZ_RECURSING) == 0)
4840                 rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset);
4841
4842         return (result);
4843 }
4844
4845 /*
4846  * See if response policy zone rewriting is allowed by a lack of interest
4847  * by the client in DNSSEC or a lack of signatures.
4848  */
4849 static isc_boolean_t
4850 rpz_ck_dnssec(ns_client_t *client, isc_result_t result,
4851               dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
4852 {
4853         dns_fixedname_t fixed;
4854         dns_name_t *found;
4855         dns_rdataset_t trdataset;
4856         dns_rdatatype_t type;
4857
4858         if (client->view->rpz_break_dnssec)
4859                 return (ISC_TRUE);
4860         /*
4861          * sigrdataset == NULL if and only !WANTDNSSEC(client)
4862          */
4863         if (sigrdataset == NULL)
4864                 return (ISC_TRUE);
4865         if (dns_rdataset_isassociated(sigrdataset))
4866                 return (ISC_FALSE);
4867
4868         /*
4869          * We are happy to rewrite nothing.
4870          */
4871         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset))
4872                 return (ISC_TRUE);
4873         /*
4874          * Do not rewrite if there is any sign of signatures.
4875          */
4876         if (rdataset->type == dns_rdatatype_nsec ||
4877             rdataset->type == dns_rdatatype_nsec3 ||
4878             rdataset->type == dns_rdatatype_rrsig)
4879                 return (ISC_FALSE);
4880
4881         /*
4882          * Look for a signature in a negative cache rdataset.
4883          */
4884         if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0)
4885                 return (ISC_TRUE);
4886         dns_fixedname_init(&fixed);
4887         found = dns_fixedname_name(&fixed);
4888         dns_rdataset_init(&trdataset);
4889         for (result = dns_rdataset_first(rdataset);
4890              result == ISC_R_SUCCESS;
4891              result = dns_rdataset_next(rdataset)) {
4892                 dns_ncache_current(rdataset, found, &trdataset);
4893                 type = trdataset.type;
4894                 dns_rdataset_disassociate(&trdataset);
4895                 if (type == dns_rdatatype_nsec ||
4896                     type == dns_rdatatype_nsec3 ||
4897                     type == dns_rdatatype_rrsig)
4898                         return (ISC_FALSE);
4899         }
4900         return (ISC_TRUE);
4901 }
4902
4903 /*
4904  * Add a CNAME to the query response, including translating foo.evil.com and
4905  *      *.evil.com CNAME *.example.com
4906  * to
4907  *      foo.evil.com CNAME foo.evil.com.example.com
4908  */
4909 static isc_result_t
4910 rpz_add_cname(ns_client_t *client, dns_rpz_st_t *st,
4911               dns_name_t *cname, dns_name_t *fname, isc_buffer_t *dbuf)
4912 {
4913         dns_fixedname_t prefix, suffix;
4914         unsigned int labels;
4915         isc_result_t result;
4916
4917         labels = dns_name_countlabels(cname);
4918         if (labels > 2 && dns_name_iswildcard(cname)) {
4919                 dns_fixedname_init(&prefix);
4920                 dns_name_split(client->query.qname, 1,
4921                                dns_fixedname_name(&prefix), NULL);
4922                 dns_fixedname_init(&suffix);
4923                 dns_name_split(cname, labels-1,
4924                                NULL, dns_fixedname_name(&suffix));
4925                 result = dns_name_concatenate(dns_fixedname_name(&prefix),
4926                                               dns_fixedname_name(&suffix),
4927                                               fname, NULL);
4928                 if (result == DNS_R_NAMETOOLONG)
4929                         client->message->rcode = dns_rcode_yxdomain;
4930         } else {
4931                 result = dns_name_copy(cname, fname, NULL);
4932                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4933         }
4934         if (result != ISC_R_SUCCESS)
4935                 return (result);
4936         query_keepname(client, fname, dbuf);
4937         result = query_add_cname(client, client->query.qname,
4938                                  fname, dns_trust_authanswer, st->m.ttl);
4939         if (result != ISC_R_SUCCESS)
4940                 return (result);
4941         rpz_log_rewrite(client, ISC_FALSE, st->m.policy,
4942                         st->m.type, st->m.zone, st->qname);
4943         ns_client_qnamereplace(client, fname);
4944         /*
4945          * Turn off DNSSEC because the results of a
4946          * response policy zone cannot verify.
4947          */
4948         client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
4949                                 DNS_MESSAGEFLAG_AD);
4950         return (ISC_R_SUCCESS);
4951 }
4952
4953 #define MAX_RESTARTS 16
4954
4955 #define QUERY_ERROR(r) \
4956 do { \
4957         eresult = r; \
4958         want_restart = ISC_FALSE; \
4959         line = __LINE__; \
4960 } while (0)
4961
4962 #define RECURSE_ERROR(r) \
4963 do { \
4964         if ((r) == DNS_R_DUPLICATE || (r) == DNS_R_DROP) \
4965                 QUERY_ERROR(r); \
4966         else \
4967                 QUERY_ERROR(DNS_R_SERVFAIL); \
4968 } while (0)
4969
4970 /*
4971  * Extract a network address from the RDATA of an A or AAAA
4972  * record.
4973  *
4974  * Returns:
4975  *      ISC_R_SUCCESS
4976  *      ISC_R_NOTIMPLEMENTED    The rdata is not a known address type.
4977  */
4978 static isc_result_t
4979 rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
4980         struct in_addr ina;
4981         struct in6_addr in6a;
4982
4983         switch (rdata->type) {
4984         case dns_rdatatype_a:
4985                 INSIST(rdata->length == 4);
4986                 memmove(&ina.s_addr, rdata->data, 4);
4987                 isc_netaddr_fromin(netaddr, &ina);
4988                 return (ISC_R_SUCCESS);
4989         case dns_rdatatype_aaaa:
4990                 INSIST(rdata->length == 16);
4991                 memmove(in6a.s6_addr, rdata->data, 16);
4992                 isc_netaddr_fromin6(netaddr, &in6a);
4993                 return (ISC_R_SUCCESS);
4994         default:
4995                 return (ISC_R_NOTIMPLEMENTED);
4996         }
4997 }
4998
4999 /*
5000  * Find the sort order of 'rdata' in the topology-like
5001  * ACL forming the second element in a 2-element top-level
5002  * sortlist statement.
5003  */
5004 static int
5005 query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) {
5006         isc_netaddr_t netaddr;
5007
5008         if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
5009                 return (INT_MAX);
5010         return (ns_sortlist_addrorder2(&netaddr, arg));
5011 }
5012
5013 /*
5014  * Find the sort order of 'rdata' in the matching element
5015  * of a 1-element top-level sortlist statement.
5016  */
5017 static int
5018 query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) {
5019         isc_netaddr_t netaddr;
5020
5021         if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
5022                 return (INT_MAX);
5023         return (ns_sortlist_addrorder1(&netaddr, arg));
5024 }
5025
5026 /*
5027  * Find the sortlist statement that applies to 'client' and set up
5028  * the sortlist info in in client->message appropriately.
5029  */
5030 static void
5031 setup_query_sortlist(ns_client_t *client) {
5032         isc_netaddr_t netaddr;
5033         dns_rdatasetorderfunc_t order = NULL;
5034         const void *order_arg = NULL;
5035
5036         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
5037         switch (ns_sortlist_setup(client->view->sortlist,
5038                                &netaddr, &order_arg)) {
5039         case NS_SORTLISTTYPE_1ELEMENT:
5040                 order = query_sortlist_order_1element;
5041                 break;
5042         case NS_SORTLISTTYPE_2ELEMENT:
5043                 order = query_sortlist_order_2element;
5044                 break;
5045         case NS_SORTLISTTYPE_NONE:
5046                 order = NULL;
5047                 break;
5048         default:
5049                 INSIST(0);
5050                 break;
5051         }
5052         dns_message_setsortorder(client->message, order, order_arg);
5053 }
5054
5055 static void
5056 query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
5057         isc_buffer_t *dbuf, b;
5058         dns_name_t *fname;
5059         dns_rdataset_t *neg, *negsig;
5060         isc_result_t result = ISC_R_NOMEMORY;
5061
5062         CTRACE("query_addnoqnameproof");
5063
5064         fname = NULL;
5065         neg = NULL;
5066         negsig = NULL;
5067
5068         dbuf = query_getnamebuf(client);
5069         if (dbuf == NULL)
5070                 goto cleanup;
5071         fname = query_newname(client, dbuf, &b);
5072         neg = query_newrdataset(client);
5073         negsig = query_newrdataset(client);
5074         if (fname == NULL || neg == NULL || negsig == NULL)
5075                 goto cleanup;
5076
5077         result = dns_rdataset_getnoqname(rdataset, fname, neg, negsig);
5078         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5079
5080         query_addrrset(client, &fname, &neg, &negsig, dbuf,
5081                        DNS_SECTION_AUTHORITY);
5082
5083         if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) == 0)
5084                 goto cleanup;
5085
5086         if (fname == NULL) {
5087                 dbuf = query_getnamebuf(client);
5088                 if (dbuf == NULL)
5089                         goto cleanup;
5090                 fname = query_newname(client, dbuf, &b);
5091         }
5092         if (neg == NULL)
5093                 neg = query_newrdataset(client);
5094         else if (dns_rdataset_isassociated(neg))
5095                 dns_rdataset_disassociate(neg);
5096         if (negsig == NULL)
5097                 negsig = query_newrdataset(client);
5098         else if (dns_rdataset_isassociated(negsig))
5099                 dns_rdataset_disassociate(negsig);
5100         if (fname == NULL || neg == NULL || negsig == NULL)
5101                 goto cleanup;
5102         result = dns_rdataset_getclosest(rdataset, fname, neg, negsig);
5103         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5104
5105         query_addrrset(client, &fname, &neg, &negsig, dbuf,
5106                        DNS_SECTION_AUTHORITY);
5107
5108  cleanup:
5109         if (neg != NULL)
5110                 query_putrdataset(client, &neg);
5111         if (negsig != NULL)
5112                 query_putrdataset(client, &negsig);
5113         if (fname != NULL)
5114                 query_releasename(client, &fname);
5115 }
5116
5117 static inline void
5118 answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
5119         dns_name_t *name;
5120         dns_message_t *msg;
5121         dns_section_t section = DNS_SECTION_ADDITIONAL;
5122         dns_rdataset_t *rdataset = NULL;
5123
5124         msg = client->message;
5125         for (name = ISC_LIST_HEAD(msg->sections[section]);
5126              name != NULL;
5127              name = ISC_LIST_NEXT(name, link))
5128                 if (dns_name_equal(name, client->query.qname)) {
5129                         for (rdataset = ISC_LIST_HEAD(name->list);
5130                              rdataset != NULL;
5131                              rdataset = ISC_LIST_NEXT(rdataset, link))
5132                                 if (rdataset->type == qtype)
5133                                         break;
5134                         break;
5135                 }
5136         if (rdataset != NULL) {
5137                 ISC_LIST_UNLINK(msg->sections[section], name, link);
5138                 ISC_LIST_PREPEND(msg->sections[section], name, link);
5139                 ISC_LIST_UNLINK(name->list, rdataset, link);
5140                 ISC_LIST_PREPEND(name->list, rdataset, link);
5141                 rdataset->attributes |= DNS_RDATASETATTR_REQUIREDGLUE;
5142         }
5143 }
5144
5145 #define NS_NAME_INIT(A,B) \
5146          { \
5147                 DNS_NAME_MAGIC, \
5148                 A, sizeof(A), sizeof(B), \
5149                 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
5150                 B, NULL, { (void *)-1, (void *)-1}, \
5151                 {NULL, NULL} \
5152         }
5153
5154 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
5155 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
5156 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
5157
5158 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
5159
5160 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
5161 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
5162 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
5163 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
5164 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
5165 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
5166 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
5167 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
5168 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
5169 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
5170 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
5171 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
5172 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
5173 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
5174 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
5175 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
5176
5177 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
5178
5179 static dns_name_t rfc1918names[] = {
5180         NS_NAME_INIT(inaddr10, inaddr10_offsets),
5181         NS_NAME_INIT(inaddr16172, inaddr172_offsets),
5182         NS_NAME_INIT(inaddr17172, inaddr172_offsets),
5183         NS_NAME_INIT(inaddr18172, inaddr172_offsets),
5184         NS_NAME_INIT(inaddr19172, inaddr172_offsets),
5185         NS_NAME_INIT(inaddr20172, inaddr172_offsets),
5186         NS_NAME_INIT(inaddr21172, inaddr172_offsets),
5187         NS_NAME_INIT(inaddr22172, inaddr172_offsets),
5188         NS_NAME_INIT(inaddr23172, inaddr172_offsets),
5189         NS_NAME_INIT(inaddr24172, inaddr172_offsets),
5190         NS_NAME_INIT(inaddr25172, inaddr172_offsets),
5191         NS_NAME_INIT(inaddr26172, inaddr172_offsets),
5192         NS_NAME_INIT(inaddr27172, inaddr172_offsets),
5193         NS_NAME_INIT(inaddr28172, inaddr172_offsets),
5194         NS_NAME_INIT(inaddr29172, inaddr172_offsets),
5195         NS_NAME_INIT(inaddr30172, inaddr172_offsets),
5196         NS_NAME_INIT(inaddr31172, inaddr172_offsets),
5197         NS_NAME_INIT(inaddr168192, inaddr192_offsets)
5198 };
5199
5200
5201 static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
5202 static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org";
5203
5204 static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
5205 static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
5206
5207 static dns_name_t prisoner = NS_NAME_INIT(prisoner_data, prisoner_offsets);
5208 static dns_name_t hostmaster = NS_NAME_INIT(hostmaster_data, hostmaster_offsets);
5209
5210 static void
5211 warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
5212         unsigned int i;
5213         dns_rdata_t rdata = DNS_RDATA_INIT;
5214         dns_rdata_soa_t soa;
5215         dns_rdataset_t found;
5216         isc_result_t result;
5217
5218         for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) {
5219                 if (dns_name_issubdomain(fname, &rfc1918names[i])) {
5220                         dns_rdataset_init(&found);
5221                         result = dns_ncache_getrdataset(rdataset,
5222                                                         &rfc1918names[i],
5223                                                         dns_rdatatype_soa,
5224                                                         &found);
5225                         if (result != ISC_R_SUCCESS)
5226                                 return;
5227
5228                         result = dns_rdataset_first(&found);
5229                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5230                         dns_rdataset_current(&found, &rdata);
5231                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
5232                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5233                         if (dns_name_equal(&soa.origin, &prisoner) &&
5234                             dns_name_equal(&soa.contact, &hostmaster)) {
5235                                 char buf[DNS_NAME_FORMATSIZE];
5236                                 dns_name_format(fname, buf, sizeof(buf));
5237                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
5238                                               NS_LOGMODULE_QUERY,
5239                                               ISC_LOG_WARNING,
5240                                               "RFC 1918 response from "
5241                                               "Internet for %s", buf);
5242                         }
5243                         dns_rdataset_disassociate(&found);
5244                         return;
5245                 }
5246         }
5247 }
5248
5249 static void
5250 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
5251                        dns_dbversion_t *version, ns_client_t *client,
5252                        dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
5253                        dns_name_t *fname, isc_boolean_t exact,
5254                        dns_name_t *found)
5255 {
5256         unsigned char salt[256];
5257         size_t salt_length;
5258         isc_uint16_t iterations;
5259         isc_result_t result;
5260         unsigned int dboptions;
5261         dns_fixedname_t fixed;
5262         dns_hash_t hash;
5263         dns_name_t name;
5264         unsigned int skip = 0, labels;
5265         dns_rdata_nsec3_t nsec3;
5266         dns_rdata_t rdata = DNS_RDATA_INIT;
5267         isc_boolean_t optout;
5268         dns_clientinfomethods_t cm;
5269         dns_clientinfo_t ci;
5270
5271         salt_length = sizeof(salt);
5272         result = dns_db_getnsec3parameters(db, version, &hash, NULL,
5273                                            &iterations, salt, &salt_length);
5274         if (result != ISC_R_SUCCESS)
5275                 return;
5276
5277         dns_name_init(&name, NULL);
5278         dns_name_clone(qname, &name);
5279         labels = dns_name_countlabels(&name);
5280         dns_clientinfomethods_init(&cm, ns_client_sourceip);
5281         dns_clientinfo_init(&ci, client);
5282
5283         /*
5284          * Map unknown algorithm to known value.
5285          */
5286         if (hash == DNS_NSEC3_UNKNOWNALG)
5287                 hash = 1;
5288
5289  again:
5290         dns_fixedname_init(&fixed);
5291         result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
5292                                     dns_db_origin(db), hash,
5293                                     iterations, salt, salt_length);
5294         if (result != ISC_R_SUCCESS)
5295                 return;
5296
5297         dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
5298         result = dns_db_findext(db, dns_fixedname_name(&fixed), version,
5299                                 dns_rdatatype_nsec3, dboptions, client->now,
5300                                 NULL, fname, &cm, &ci, rdataset, sigrdataset);
5301
5302         if (result == DNS_R_NXDOMAIN) {
5303                 if (!dns_rdataset_isassociated(rdataset)) {
5304                         return;
5305                 }
5306                 result = dns_rdataset_first(rdataset);
5307                 INSIST(result == ISC_R_SUCCESS);
5308                 dns_rdataset_current(rdataset, &rdata);
5309                 dns_rdata_tostruct(&rdata, &nsec3, NULL);
5310                 dns_rdata_reset(&rdata);
5311                 optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
5312                 if (found != NULL && optout &&
5313                     dns_name_issubdomain(&name, dns_db_origin(db)))
5314                 {
5315                         dns_rdataset_disassociate(rdataset);
5316                         if (dns_rdataset_isassociated(sigrdataset))
5317                                 dns_rdataset_disassociate(sigrdataset);
5318                         skip++;
5319                         dns_name_getlabelsequence(qname, skip, labels - skip,
5320                                                   &name);
5321                         ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
5322                                       NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3),
5323                                       "looking for closest provable encloser");
5324                         goto again;
5325                 }
5326                 if (exact)
5327                         ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
5328                                       NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
5329                                       "expected a exact match NSEC3, got "
5330                                       "a covering record");
5331
5332         } else if (result != ISC_R_SUCCESS) {
5333                 return;
5334         } else if (!exact)
5335                 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
5336                               NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
5337                               "expected covering NSEC3, got an exact match");
5338         if (found == qname) {
5339                 if (skip != 0U)
5340                         dns_name_getlabelsequence(qname, skip, labels - skip,
5341                                                   found);
5342         } else if (found != NULL)
5343                 dns_name_copy(&name, found, NULL);
5344         return;
5345 }
5346
5347 #ifdef ALLOW_FILTER_AAAA_ON_V4
5348 static isc_boolean_t
5349 is_v4_client(ns_client_t *client) {
5350         if (isc_sockaddr_pf(&client->peeraddr) == AF_INET)
5351                 return (ISC_TRUE);
5352         if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
5353             IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
5354                 return (ISC_TRUE);
5355         return (ISC_FALSE);
5356 }
5357 #endif
5358
5359 static isc_uint32_t
5360 dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
5361         dns_dbnode_t *node = NULL;
5362         dns_rdata_soa_t soa;
5363         dns_rdata_t rdata = DNS_RDATA_INIT;
5364         dns_rdataset_t rdataset;
5365         isc_result_t result;
5366         isc_uint32_t ttl = ISC_UINT32_MAX;
5367
5368         dns_rdataset_init(&rdataset);
5369
5370         result = dns_db_getoriginnode(db, &node);
5371         if (result != ISC_R_SUCCESS)
5372                 goto cleanup;
5373
5374         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5375                                      0, 0, &rdataset, NULL);
5376         if (result != ISC_R_SUCCESS)
5377                 goto cleanup;
5378         result = dns_rdataset_first(&rdataset);
5379         if (result != ISC_R_SUCCESS)
5380                 goto cleanup;
5381
5382         dns_rdataset_current(&rdataset, &rdata);
5383         result = dns_rdata_tostruct(&rdata, &soa, NULL);
5384         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5385         ttl = ISC_MIN(rdataset.ttl, soa.minimum);
5386
5387 cleanup:
5388         if (dns_rdataset_isassociated(&rdataset))
5389                 dns_rdataset_disassociate(&rdataset);
5390         if (node != NULL)
5391                 dns_db_detachnode(db, &node);
5392         return (ttl);
5393 }
5394
5395 static isc_boolean_t
5396 dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
5397              dns_rdataset_t *sigrdataset)
5398 {
5399         isc_netaddr_t netaddr;
5400         dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
5401         unsigned int flags = 0;
5402         unsigned int i, count;
5403         isc_boolean_t *aaaaok;
5404
5405         INSIST(client->query.dns64_aaaaok == NULL);
5406         INSIST(client->query.dns64_aaaaoklen == 0);
5407         INSIST(client->query.dns64_aaaa == NULL);
5408         INSIST(client->query.dns64_sigaaaa == NULL);
5409
5410         if (dns64 == NULL)
5411                 return (ISC_TRUE);
5412
5413         if (RECURSIONOK(client))
5414                 flags |= DNS_DNS64_RECURSIVE;
5415
5416         if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
5417                 flags |= DNS_DNS64_DNSSEC;
5418
5419         count = dns_rdataset_count(rdataset);
5420         aaaaok = isc_mem_get(client->mctx, sizeof(isc_boolean_t) * count);
5421
5422         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
5423         if (dns_dns64_aaaaok(dns64, &netaddr, client->signer,
5424                              &ns_g_server->aclenv, flags, rdataset,
5425                              aaaaok, count)) {
5426                 for (i = 0; i < count; i++) {
5427                         if (aaaaok != NULL && !aaaaok[i]) {
5428                                 client->query.dns64_aaaaok = aaaaok;
5429                                 client->query.dns64_aaaaoklen = count;
5430                                 break;
5431                         }
5432                 }
5433                 if (i == count && aaaaok != NULL)
5434                         isc_mem_put(client->mctx, aaaaok,
5435                                     sizeof(isc_boolean_t) * count);
5436                 return (ISC_TRUE);
5437         }
5438         if (aaaaok != NULL)
5439                 isc_mem_put(client->mctx, aaaaok,
5440                             sizeof(isc_boolean_t) * count);
5441         return (ISC_FALSE);
5442 }
5443
5444 /*
5445  * Look for the name and type in the redirection zone.  If found update
5446  * the arguments as appropriate.  Return ISC_TRUE if a update was
5447  * performed.
5448  *
5449  * Only perform the update if the client is in the allow query acl and
5450  * returning the update would not cause a DNSSEC validation failure.
5451  */
5452 static isc_boolean_t
5453 redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
5454          dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
5455          dns_rdatatype_t qtype)
5456 {
5457         dns_db_t *db = NULL;
5458         dns_dbnode_t *node = NULL;
5459         dns_fixedname_t fixed;
5460         dns_name_t *found;
5461         dns_rdataset_t trdataset;
5462         isc_result_t result;
5463         dns_rdatatype_t type;
5464         dns_clientinfomethods_t cm;
5465         dns_clientinfo_t ci;
5466         ns_dbversion_t *dbversion;
5467
5468         CTRACE("redirect");
5469
5470         if (client->view->redirect == NULL)
5471                 return (ISC_FALSE);
5472
5473         dns_fixedname_init(&fixed);
5474         found = dns_fixedname_name(&fixed);
5475         dns_rdataset_init(&trdataset);
5476
5477         dns_clientinfomethods_init(&cm, ns_client_sourceip);
5478         dns_clientinfo_init(&ci, client);
5479
5480         if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
5481                 return (ISC_FALSE);
5482
5483         if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
5484                 if (rdataset->trust == dns_trust_secure)
5485                         return (ISC_FALSE);
5486                 if (rdataset->trust == dns_trust_ultimate &&
5487                     (rdataset->type == dns_rdatatype_nsec ||
5488                      rdataset->type == dns_rdatatype_nsec3))
5489                         return (ISC_FALSE);
5490                 if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
5491                         for (result = dns_rdataset_first(rdataset);
5492                              result == ISC_R_SUCCESS;
5493                              result = dns_rdataset_next(rdataset)) {
5494                                 dns_ncache_current(rdataset, found, &trdataset);
5495                                 type = trdataset.type;
5496                                 dns_rdataset_disassociate(&trdataset);
5497                                 if (type == dns_rdatatype_nsec ||
5498                                     type == dns_rdatatype_nsec3 ||
5499                                     type == dns_rdatatype_rrsig)
5500                                         return (ISC_FALSE);
5501                         }
5502                 }
5503         }
5504
5505         result = ns_client_checkaclsilent(client, NULL,
5506                                  dns_zone_getqueryacl(client->view->redirect),
5507                                           ISC_TRUE);
5508         if (result != ISC_R_SUCCESS)
5509                 return (ISC_FALSE);
5510
5511         result = dns_zone_getdb(client->view->redirect, &db);
5512         if (result != ISC_R_SUCCESS)
5513                 return (ISC_FALSE);
5514
5515         dbversion = query_findversion(client, db);
5516         if (dbversion == NULL) {
5517                 dns_db_detach(&db);
5518                 return (ISC_FALSE);
5519         }
5520
5521         /*
5522          * Lookup the requested data in the redirect zone.
5523          */
5524         result = dns_db_findext(db, client->query.qname, dbversion->version,
5525                                 qtype, 0, client->now, &node, found, &cm, &ci,
5526                                 &trdataset, NULL);
5527         if (result != ISC_R_SUCCESS) {
5528                 if (dns_rdataset_isassociated(&trdataset))
5529                         dns_rdataset_disassociate(&trdataset);
5530                 if (node != NULL)
5531                         dns_db_detachnode(db, &node);
5532                 dns_db_detach(&db);
5533                 return (ISC_FALSE);
5534         }
5535         CTRACE("redirect: found data: done");
5536
5537         dns_name_copy(found, name, NULL);
5538         if (dns_rdataset_isassociated(rdataset))
5539                 dns_rdataset_disassociate(rdataset);
5540         if (dns_rdataset_isassociated(&trdataset)) {
5541                 dns_rdataset_clone(&trdataset, rdataset);
5542                 dns_rdataset_disassociate(&trdataset);
5543         }
5544         if (*nodep != NULL)
5545                 dns_db_detachnode(*dbp, nodep);
5546         dns_db_detach(dbp);
5547         dns_db_attachnode(db, node, nodep);
5548         dns_db_attach(db, dbp);
5549         dns_db_detachnode(db, &node);
5550         dns_db_detach(&db);
5551         *versionp = dbversion->version;
5552
5553         client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
5554                                      NS_QUERYATTR_NOADDITIONAL);
5555
5556         return (ISC_TRUE);
5557 }
5558
5559 /*
5560  * Do the bulk of query processing for the current query of 'client'.
5561  * If 'event' is non-NULL, we are returning from recursion and 'qtype'
5562  * is ignored.  Otherwise, 'qtype' is the query type.
5563  */
5564 static isc_result_t
5565 query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
5566 {
5567         dns_db_t *db, *zdb;
5568         dns_dbnode_t *node;
5569         dns_rdatatype_t type;
5570         dns_name_t *fname, *zfname, *tname, *prefix;
5571         dns_rdataset_t *rdataset, *trdataset;
5572         dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset;
5573         dns_rdataset_t **sigrdatasetp;
5574         dns_rdata_t rdata = DNS_RDATA_INIT;
5575         dns_rdatasetiter_t *rdsiter;
5576         isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof;
5577         isc_boolean_t is_staticstub_zone;
5578         unsigned int n, nlabels;
5579         dns_namereln_t namereln;
5580         int order;
5581         isc_buffer_t *dbuf;
5582         isc_buffer_t b;
5583         isc_result_t result, eresult;
5584         dns_fixedname_t fixed;
5585         dns_fixedname_t wildcardname;
5586         dns_dbversion_t *version, *zversion;
5587         dns_zone_t *zone;
5588         dns_rdata_cname_t cname;
5589         dns_rdata_dname_t dname;
5590         unsigned int options;
5591         isc_boolean_t empty_wild;
5592         dns_rdataset_t *noqname;
5593         dns_rpz_st_t *rpz_st;
5594         isc_boolean_t resuming;
5595         int line = -1;
5596         isc_boolean_t dns64_exclude, dns64;
5597         dns_clientinfomethods_t cm;
5598         dns_clientinfo_t ci;
5599
5600         CTRACE("query_find");
5601
5602         /*
5603          * One-time initialization.
5604          *
5605          * It's especially important to initialize anything that the cleanup
5606          * code might cleanup.
5607          */
5608
5609         eresult = ISC_R_SUCCESS;
5610         fname = NULL;
5611         zfname = NULL;
5612         rdataset = NULL;
5613         zrdataset = NULL;
5614         sigrdataset = NULL;
5615         zsigrdataset = NULL;
5616         zversion = NULL;
5617         node = NULL;
5618         db = NULL;
5619         zdb = NULL;
5620         version = NULL;
5621         zone = NULL;
5622         need_wildcardproof = ISC_FALSE;
5623         empty_wild = ISC_FALSE;
5624         dns64_exclude = dns64 = ISC_FALSE;
5625         options = 0;
5626         resuming = ISC_FALSE;
5627         is_zone = ISC_FALSE;
5628         is_staticstub_zone = ISC_FALSE;
5629
5630         dns_clientinfomethods_init(&cm, ns_client_sourceip);
5631         dns_clientinfo_init(&ci, client);
5632
5633         if (event != NULL) {
5634                 /*
5635                  * We're returning from recursion.  Restore the query context
5636                  * and resume.
5637                  */
5638                 want_restart = ISC_FALSE;
5639
5640                 rpz_st = client->query.rpz_st;
5641                 if (rpz_st != NULL &&
5642                     (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
5643                         is_zone = rpz_st->q.is_zone;
5644                         authoritative = rpz_st->q.authoritative;
5645                         zone = rpz_st->q.zone;
5646                         rpz_st->q.zone = NULL;
5647                         node = rpz_st->q.node;
5648                         rpz_st->q.node = NULL;
5649                         db = rpz_st->q.db;
5650                         rpz_st->q.db = NULL;
5651                         rdataset = rpz_st->q.rdataset;
5652                         rpz_st->q.rdataset = NULL;
5653                         sigrdataset = rpz_st->q.sigrdataset;
5654                         rpz_st->q.sigrdataset = NULL;
5655                         qtype = rpz_st->q.qtype;
5656
5657                         rpz_st->r.db = event->db;
5658                         if (event->node != NULL)
5659                                 dns_db_detachnode(event->db, &event->node);
5660                         rpz_st->r.r_type = event->qtype;
5661                         rpz_st->r.r_rdataset = event->rdataset;
5662                         query_putrdataset(client, &event->sigrdataset);
5663                 } else {
5664                         authoritative = ISC_FALSE;
5665
5666                         qtype = event->qtype;
5667                         db = event->db;
5668                         node = event->node;
5669                         rdataset = event->rdataset;
5670                         sigrdataset = event->sigrdataset;
5671                 }
5672
5673                 if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
5674                         type = dns_rdatatype_any;
5675                 else
5676                         type = qtype;
5677
5678                 if (DNS64(client)) {
5679                         client->query.attributes &= ~NS_QUERYATTR_DNS64;
5680                         dns64 = ISC_TRUE;
5681                 }
5682                 if (DNS64EXCLUDE(client)) {
5683                         client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE;
5684                         dns64_exclude = ISC_TRUE;
5685                 }
5686
5687                 /*
5688                  * We'll need some resources...
5689                  */
5690                 dbuf = query_getnamebuf(client);
5691                 if (dbuf == NULL) {
5692                         QUERY_ERROR(DNS_R_SERVFAIL);
5693                         goto cleanup;
5694                 }
5695                 fname = query_newname(client, dbuf, &b);
5696                 if (fname == NULL) {
5697                         QUERY_ERROR(DNS_R_SERVFAIL);
5698                         goto cleanup;
5699                 }
5700                 if (rpz_st != NULL &&
5701                     (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
5702                         tname = rpz_st->fname;
5703                 } else {
5704                         tname = dns_fixedname_name(&event->foundname);
5705                 }
5706                 result = dns_name_copy(tname, fname, NULL);
5707                 if (result != ISC_R_SUCCESS) {
5708                         QUERY_ERROR(DNS_R_SERVFAIL);
5709                         goto cleanup;
5710                 }
5711                 if (rpz_st != NULL &&
5712                     (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
5713                         rpz_st->r.r_result = event->result;
5714                         result = rpz_st->q.result;
5715                         isc_event_free(ISC_EVENT_PTR(&event));
5716                 } else {
5717                         result = event->result;
5718                 }
5719                 resuming = ISC_TRUE;
5720                 goto resume;
5721         }
5722
5723         /*
5724          * Not returning from recursion.
5725          */
5726
5727         /*
5728          * If it's a SIG query, we'll iterate the node.
5729          */
5730         if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
5731                 type = dns_rdatatype_any;
5732         else
5733                 type = qtype;
5734
5735  restart:
5736         CTRACE("query_find: restart");
5737         want_restart = ISC_FALSE;
5738         authoritative = ISC_FALSE;
5739         version = NULL;
5740         need_wildcardproof = ISC_FALSE;
5741
5742         if (client->view->checknames &&
5743             !dns_rdata_checkowner(client->query.qname,
5744                                   client->message->rdclass,
5745                                   qtype, ISC_FALSE)) {
5746                 char namebuf[DNS_NAME_FORMATSIZE];
5747                 char typename[DNS_RDATATYPE_FORMATSIZE];
5748                 char classname[DNS_RDATACLASS_FORMATSIZE];
5749
5750                 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
5751                 dns_rdatatype_format(qtype, typename, sizeof(typename));
5752                 dns_rdataclass_format(client->message->rdclass, classname,
5753                                       sizeof(classname));
5754                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
5755                               NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
5756                               "check-names failure %s/%s/%s", namebuf,
5757                               typename, classname);
5758                 QUERY_ERROR(DNS_R_REFUSED);
5759                 goto cleanup;
5760         }
5761
5762         /*
5763          * First we must find the right database.
5764          */
5765         options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */
5766         if (dns_rdatatype_atparent(qtype) &&
5767             !dns_name_equal(client->query.qname, dns_rootname))
5768                 options |= DNS_GETDB_NOEXACT;
5769         result = query_getdb(client, client->query.qname, qtype, options,
5770                              &zone, &db, &version, &is_zone);
5771         if ((result != ISC_R_SUCCESS || !is_zone) && !RECURSIONOK(client) &&
5772             (options & DNS_GETDB_NOEXACT) != 0 && qtype == dns_rdatatype_ds) {
5773                 /*
5774                  * Look to see if we are authoritative for the
5775                  * child zone if the query type is DS.
5776                  */
5777                 dns_db_t *tdb = NULL;
5778                 dns_zone_t *tzone = NULL;
5779                 dns_dbversion_t *tversion = NULL;
5780                 isc_result_t tresult;
5781
5782                 tresult = query_getzonedb(client, client->query.qname, qtype,
5783                                          DNS_GETDB_PARTIAL, &tzone, &tdb,
5784                                          &tversion);
5785                 if (tresult == ISC_R_SUCCESS) {
5786                         options &= ~DNS_GETDB_NOEXACT;
5787                         query_putrdataset(client, &rdataset);
5788                         if (db != NULL)
5789                                 dns_db_detach(&db);
5790                         if (zone != NULL)
5791                                 dns_zone_detach(&zone);
5792                         version = tversion;
5793                         db = tdb;
5794                         zone = tzone;
5795                         is_zone = ISC_TRUE;
5796                         result = ISC_R_SUCCESS;
5797                 } else {
5798                         if (tdb != NULL)
5799                                 dns_db_detach(&tdb);
5800                         if (tzone != NULL)
5801                                 dns_zone_detach(&tzone);
5802                 }
5803         }
5804         if (result != ISC_R_SUCCESS) {
5805                 if (result == DNS_R_REFUSED) {
5806                         if (WANTRECURSION(client)) {
5807                                 inc_stats(client,
5808                                           dns_nsstatscounter_recurserej);
5809                         } else
5810                                 inc_stats(client, dns_nsstatscounter_authrej);
5811                         if (!PARTIALANSWER(client))
5812                                 QUERY_ERROR(DNS_R_REFUSED);
5813                 } else
5814                         QUERY_ERROR(DNS_R_SERVFAIL);
5815                 goto cleanup;
5816         }
5817
5818         is_staticstub_zone = ISC_FALSE;
5819         if (is_zone) {
5820                 authoritative = ISC_TRUE;
5821                 if (zone != NULL &&
5822                     dns_zone_gettype(zone) == dns_zone_staticstub)
5823                         is_staticstub_zone = ISC_TRUE;
5824         }
5825
5826         if (event == NULL && client->query.restarts == 0) {
5827                 if (is_zone) {
5828                         if (zone != NULL) {
5829                                 /*
5830                                  * if is_zone = true, zone = NULL then this is
5831                                  * a DLZ zone.  Don't attempt to attach zone.
5832                                  */
5833                                 dns_zone_attach(zone, &client->query.authzone);
5834                         }
5835                         dns_db_attach(db, &client->query.authdb);
5836                 }
5837                 client->query.authdbset = ISC_TRUE;
5838         }
5839
5840  db_find:
5841         CTRACE("query_find: db_find");
5842         /*
5843          * We'll need some resources...
5844          */
5845         dbuf = query_getnamebuf(client);
5846         if (dbuf == NULL) {
5847                 QUERY_ERROR(DNS_R_SERVFAIL);
5848                 goto cleanup;
5849         }
5850         fname = query_newname(client, dbuf, &b);
5851         rdataset = query_newrdataset(client);
5852         if (fname == NULL || rdataset == NULL) {
5853                 QUERY_ERROR(DNS_R_SERVFAIL);
5854                 goto cleanup;
5855         }
5856         if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) {
5857                 sigrdataset = query_newrdataset(client);
5858                 if (sigrdataset == NULL) {
5859                         QUERY_ERROR(DNS_R_SERVFAIL);
5860                         goto cleanup;
5861                 }
5862         }
5863
5864         /*
5865          * Now look for an answer in the database.
5866          */
5867         result = dns_db_findext(db, client->query.qname, version, type,
5868                                 client->query.dboptions, client->now,
5869                                 &node, fname, &cm, &ci, rdataset, sigrdataset);
5870
5871  resume:
5872         CTRACE("query_find: resume");
5873
5874 #ifdef USE_RRL
5875         /*
5876          * Rate limit these responses to this client.
5877          * Do not delay counting and handling obvious referrals,
5878          *      since those won't come here again.
5879          * Delay handling delegations for which we are certain to recurse and
5880          *      return here (DNS_R_DELEGATION, not a child of one of our
5881          *      own zones, and recursion enabled)
5882          * Don't mess with responses rewritten by RPZ
5883          * Count each response at most once.
5884          */
5885         if (client->view->rrl != NULL &&
5886             ((fname != NULL && dns_name_isabsolute(fname)) ||
5887              (result == ISC_R_NOTFOUND && !RECURSIONOK(client))) &&
5888             !(result == DNS_R_DELEGATION && !is_zone && RECURSIONOK(client)) &&
5889             (client->query.rpz_st == NULL ||
5890              (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0)&&
5891             (client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0) {
5892                 dns_rdataset_t nc_rdataset;
5893                 isc_boolean_t wouldlog;
5894                 char log_buf[DNS_RRL_LOG_BUF_LEN];
5895                 isc_result_t nc_result, resp_result;
5896                 dns_rrl_result_t rrl_result;
5897
5898                 client->query.attributes |= NS_QUERYATTR_RRL_CHECKED;
5899
5900                 wouldlog = isc_log_wouldlog(ns_g_lctx, DNS_RRL_LOG_DROP);
5901                 tname = fname;
5902                 if (result == DNS_R_NXDOMAIN) {
5903                         /*
5904                          * Use the database origin name to rate limit NXDOMAIN
5905                          */
5906                         if (db != NULL)
5907                                 tname = dns_db_origin(db);
5908                         resp_result = result;
5909                 } else if (result == DNS_R_NCACHENXDOMAIN &&
5910                            rdataset != NULL &&
5911                            dns_rdataset_isassociated(rdataset) &&
5912                            (rdataset->attributes &
5913                             DNS_RDATASETATTR_NEGATIVE) != 0) {
5914                         /*
5915                          * Try to use owner name in the negative cache SOA.
5916                          */
5917                         dns_fixedname_init(&fixed);
5918                         dns_rdataset_init(&nc_rdataset);
5919                         for (nc_result = dns_rdataset_first(rdataset);
5920                              nc_result == ISC_R_SUCCESS;
5921                              nc_result = dns_rdataset_next(rdataset)) {
5922                                 dns_ncache_current(rdataset,
5923                                                    dns_fixedname_name(&fixed),
5924                                                    &nc_rdataset);
5925                                 if (nc_rdataset.type == dns_rdatatype_soa) {
5926                                         dns_rdataset_disassociate(&nc_rdataset);
5927                                         tname = dns_fixedname_name(&fixed);
5928                                         break;
5929                                 }
5930                                 dns_rdataset_disassociate(&nc_rdataset);
5931                         }
5932                         resp_result = DNS_R_NXDOMAIN;
5933                 } else if (result == DNS_R_NXRRSET ||
5934                            result == DNS_R_EMPTYNAME) {
5935                         resp_result = DNS_R_NXRRSET;
5936                 } else if (result == DNS_R_DELEGATION) {
5937                         resp_result = result;
5938                 } else if (result == ISC_R_NOTFOUND) {
5939                         /*
5940                          * Handle referral to ".", including when recursion
5941                          * is off or not requested and the hints have not
5942                          * been loaded or we have "additional-from-cache no".
5943                          */
5944                         tname = dns_rootname;
5945                         resp_result = DNS_R_DELEGATION;
5946                 } else {
5947                         resp_result = ISC_R_SUCCESS;
5948                 }
5949                 rrl_result = dns_rrl(client->view, &client->peeraddr,
5950                                      ISC_TF((client->attributes
5951                                              & NS_CLIENTATTR_TCP) != 0),
5952                                      client->message->rdclass, qtype, tname,
5953                                      resp_result, client->now,
5954                                      wouldlog, log_buf, sizeof(log_buf));
5955                 if (rrl_result != DNS_RRL_RESULT_OK) {
5956                         /*
5957                          * Log dropped or slipped responses in the query
5958                          * category so that requests are not silently lost.
5959                          * Starts of rate-limited bursts are logged in
5960                          * DNS_LOGCATEGORY_RRL.
5961                          *
5962                          * Dropped responses are counted with dropped queries
5963                          * in QryDropped while slipped responses are counted
5964                          * with other truncated responses in RespTruncated.
5965                          */
5966                         if (wouldlog) {
5967                                 ns_client_log(client,
5968                                               NS_LOGCATEGORY_QUERY_EERRORS,
5969                                               NS_LOGMODULE_QUERY,
5970                                               DNS_RRL_LOG_DROP,
5971                                               "%s", log_buf);
5972                         }
5973                         if (!client->view->rrl->log_only) {
5974                                 if (rrl_result == DNS_RRL_RESULT_DROP) {
5975                                         /*
5976                                          * These will also be counted in
5977                                          * dns_nsstatscounter_dropped
5978                                          */
5979                                         inc_stats(client,
5980                                                 dns_nsstatscounter_ratedropped);
5981                                         QUERY_ERROR(DNS_R_DROP);
5982                                 } else {
5983                                         /*
5984                                          * These will also be counted in
5985                                          * dns_nsstatscounter_truncatedresp
5986                                          */
5987                                         inc_stats(client,
5988                                                 dns_nsstatscounter_rateslipped);
5989                                         client->message->flags |=
5990                                                 DNS_MESSAGEFLAG_TC;
5991                                         if (resp_result == DNS_R_NXDOMAIN)
5992                                                 client->message->rcode =
5993                                                         dns_rcode_nxdomain;
5994                                 }
5995                                 goto cleanup;
5996                         }
5997                 }
5998         }
5999 #endif /* USE_RRL */
6000
6001         if (!ISC_LIST_EMPTY(client->view->rpz_zones) &&
6002             (RECURSIONOK(client) || !client->view->rpz_recursive_only) &&
6003             rpz_ck_dnssec(client, result, rdataset, sigrdataset) &&
6004             !RECURSING(client) &&
6005             (client->query.rpz_st == NULL ||
6006              (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) &&
6007             !dns_name_equal(client->query.qname, dns_rootname)) {
6008                 isc_result_t rresult;
6009
6010                 rresult = rpz_rewrite(client, qtype, result, resuming);
6011                 rpz_st = client->query.rpz_st;
6012                 switch (rresult) {
6013                 case ISC_R_SUCCESS:
6014                         break;
6015                 case DNS_R_DELEGATION:
6016                         /*
6017                          * recursing for NS names or addresses,
6018                          * so save the main query state
6019                          */
6020                         rpz_st->q.qtype = qtype;
6021                         rpz_st->q.is_zone = is_zone;
6022                         rpz_st->q.authoritative = authoritative;
6023                         rpz_st->q.zone = zone;
6024                         zone = NULL;
6025                         rpz_st->q.db = db;
6026                         db = NULL;
6027                         rpz_st->q.node = node;
6028                         node = NULL;
6029                         rpz_st->q.rdataset = rdataset;
6030                         rdataset = NULL;
6031                         rpz_st->q.sigrdataset = sigrdataset;
6032                         sigrdataset = NULL;
6033                         dns_name_copy(fname, rpz_st->fname, NULL);
6034                         rpz_st->q.result = result;
6035                         client->query.attributes |= NS_QUERYATTR_RECURSING;
6036                         goto cleanup;
6037                 default:
6038                         RECURSE_ERROR(rresult);
6039                         goto cleanup;
6040                 }
6041                 if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS)
6042                         rpz_st->state |= DNS_RPZ_REWRITTEN;
6043                 if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS &&
6044                     rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU &&
6045                     rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
6046                         if (rpz_st->m.type == DNS_RPZ_TYPE_QNAME) {
6047                                 result = dns_name_copy(client->query.qname,
6048                                                        fname, NULL);
6049                                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6050                         }
6051                         rpz_clean(&zone, &db, &node, NULL);
6052                         if (rpz_st->m.rdataset != NULL) {
6053                                 query_putrdataset(client, &rdataset);
6054                                 rdataset = rpz_st->m.rdataset;
6055                                 rpz_st->m.rdataset = NULL;
6056                         } else if (rdataset != NULL &&
6057                                    dns_rdataset_isassociated(rdataset)) {
6058                                 dns_rdataset_disassociate(rdataset);
6059                         }
6060                         node = rpz_st->m.node;
6061                         rpz_st->m.node = NULL;
6062                         db = rpz_st->m.db;
6063                         rpz_st->m.db = NULL;
6064                         version = rpz_st->m.version;
6065                         rpz_st->m.version = NULL;
6066                         zone = rpz_st->m.zone;
6067                         rpz_st->m.zone = NULL;
6068
6069                         switch (rpz_st->m.policy) {
6070                         case DNS_RPZ_POLICY_NXDOMAIN:
6071                                 result = DNS_R_NXDOMAIN;
6072                                 break;
6073                         case DNS_RPZ_POLICY_NODATA:
6074                                 result = DNS_R_NXRRSET;
6075                                 break;
6076                         case DNS_RPZ_POLICY_RECORD:
6077                                 result = rpz_st->m.result;
6078                                 if (qtype == dns_rdatatype_any &&
6079                                     result != DNS_R_CNAME) {
6080                                         /*
6081                                          * We will add all of the rdatasets of
6082                                          * the node by iterating, setting the
6083                                          * TTL then.
6084                                          */
6085                                         if (dns_rdataset_isassociated(rdataset))
6086                                             dns_rdataset_disassociate(rdataset);
6087                                 } else {
6088                                         /*
6089                                          * We will add this rdataset.
6090                                          */
6091                                         rdataset->ttl = ISC_MIN(rdataset->ttl,
6092                                                             rpz_st->m.ttl);
6093                                 }
6094                                 break;
6095                         case DNS_RPZ_POLICY_WILDCNAME:
6096                                 result = dns_rdataset_first(rdataset);
6097                                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6098                                 dns_rdataset_current(rdataset, &rdata);
6099                                 result = dns_rdata_tostruct(&rdata, &cname,
6100                                                             NULL);
6101                                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6102                                 dns_rdata_reset(&rdata);
6103                                 result = rpz_add_cname(client, rpz_st,
6104                                                        &cname.cname,
6105                                                        fname, dbuf);
6106                                 if (result != ISC_R_SUCCESS)
6107                                         goto cleanup;
6108                                 fname = NULL;
6109                                 want_restart = ISC_TRUE;
6110                                 goto cleanup;
6111                         case DNS_RPZ_POLICY_CNAME:
6112                                 /*
6113                                  * Add overridding CNAME from a named.conf
6114                                  * response-policy statement
6115                                  */
6116                                 result = rpz_add_cname(client, rpz_st,
6117                                                        &rpz_st->m.rpz->cname,
6118                                                        fname, dbuf);
6119                                 if (result != ISC_R_SUCCESS)
6120                                         goto cleanup;
6121                                 fname = NULL;
6122                                 want_restart = ISC_TRUE;
6123                                 goto cleanup;
6124                         default:
6125                                 INSIST(0);
6126                         }
6127
6128                         /*
6129                          * Turn off DNSSEC because the results of a
6130                          * response policy zone cannot verify.
6131                          */
6132                         client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
6133                                                 DNS_MESSAGEFLAG_AD);
6134                         query_putrdataset(client, &sigrdataset);
6135                         rpz_st->q.is_zone = is_zone;
6136                         is_zone = ISC_TRUE;
6137                         rpz_log_rewrite(client, ISC_FALSE, rpz_st->m.policy,
6138                                         rpz_st->m.type, zone, rpz_st->qname);
6139                 }
6140         }
6141
6142         switch (result) {
6143         case ISC_R_SUCCESS:
6144                 /*
6145                  * This case is handled in the main line below.
6146                  */
6147                 break;
6148         case DNS_R_GLUE:
6149         case DNS_R_ZONECUT:
6150                 /*
6151                  * These cases are handled in the main line below.
6152                  */
6153                 INSIST(is_zone);
6154                 authoritative = ISC_FALSE;
6155                 break;
6156         case ISC_R_NOTFOUND:
6157                 /*
6158                  * The cache doesn't even have the root NS.  Get them from
6159                  * the hints DB.
6160                  */
6161                 INSIST(!is_zone);
6162                 if (db != NULL)
6163                         dns_db_detach(&db);
6164
6165                 if (client->view->hints == NULL) {
6166                         /* We have no hints. */
6167                         result = ISC_R_FAILURE;
6168                 } else {
6169                         dns_db_attach(client->view->hints, &db);
6170                         result = dns_db_findext(db, dns_rootname,
6171                                                 NULL, dns_rdatatype_ns,
6172                                                 0, client->now, &node,
6173                                                 fname, &cm, &ci,
6174                                                 rdataset, sigrdataset);
6175                 }
6176                 if (result != ISC_R_SUCCESS) {
6177                         /*
6178                          * Nonsensical root hints may require cleanup.
6179                          */
6180                         if (dns_rdataset_isassociated(rdataset))
6181                                 dns_rdataset_disassociate(rdataset);
6182                         if (sigrdataset != NULL &&
6183                             dns_rdataset_isassociated(sigrdataset))
6184                                 dns_rdataset_disassociate(sigrdataset);
6185                         if (node != NULL)
6186                                 dns_db_detachnode(db, &node);
6187
6188                         /*
6189                          * We don't have any root server hints, but
6190                          * we may have working forwarders, so try to
6191                          * recurse anyway.
6192                          */
6193                         if (RECURSIONOK(client)) {
6194                                 result = query_recurse(client, qtype,
6195                                                        client->query.qname,
6196                                                        NULL, NULL, resuming);
6197                                 if (result == ISC_R_SUCCESS) {
6198                                         client->query.attributes |=
6199                                                 NS_QUERYATTR_RECURSING;
6200                                         if (dns64)
6201                                                 client->query.attributes |=
6202                                                         NS_QUERYATTR_DNS64;
6203                                         if (dns64_exclude)
6204                                                 client->query.attributes |=
6205                                                       NS_QUERYATTR_DNS64EXCLUDE;
6206                                 } else
6207                                         RECURSE_ERROR(result);
6208                                 goto cleanup;
6209                         } else {
6210                                 /* Unable to give root server referral. */
6211                                 QUERY_ERROR(DNS_R_SERVFAIL);
6212                                 goto cleanup;
6213                         }
6214                 }
6215                 /*
6216                  * XXXRTH  We should trigger root server priming here.
6217                  */
6218                 /* FALLTHROUGH */
6219         case DNS_R_DELEGATION:
6220                 authoritative = ISC_FALSE;
6221                 if (is_zone) {
6222                         /*
6223                          * Look to see if we are authoritative for the
6224                          * child zone if the query type is DS.
6225                          */
6226                         if (!RECURSIONOK(client) &&
6227                             (options & DNS_GETDB_NOEXACT) != 0 &&
6228                             qtype == dns_rdatatype_ds) {
6229                                 dns_db_t *tdb = NULL;
6230                                 dns_zone_t *tzone = NULL;
6231                                 dns_dbversion_t *tversion = NULL;
6232                                 result = query_getzonedb(client,
6233                                                          client->query.qname,
6234                                                          qtype,
6235                                                          DNS_GETDB_PARTIAL,
6236                                                          &tzone, &tdb,
6237                                                          &tversion);
6238                                 if (result == ISC_R_SUCCESS) {
6239                                         options &= ~DNS_GETDB_NOEXACT;
6240                                         query_putrdataset(client, &rdataset);
6241                                         if (sigrdataset != NULL)
6242                                                 query_putrdataset(client,
6243                                                                   &sigrdataset);
6244                                         if (fname != NULL)
6245                                                 query_releasename(client,
6246                                                                   &fname);
6247                                         if (node != NULL)
6248                                                 dns_db_detachnode(db, &node);
6249                                         if (db != NULL)
6250                                                 dns_db_detach(&db);
6251                                         if (zone != NULL)
6252                                                 dns_zone_detach(&zone);
6253                                         version = tversion;
6254                                         db = tdb;
6255                                         zone = tzone;
6256                                         authoritative = ISC_TRUE;
6257                                         goto db_find;
6258                                 }
6259                                 if (tdb != NULL)
6260                                         dns_db_detach(&tdb);
6261                                 if (tzone != NULL)
6262                                         dns_zone_detach(&tzone);
6263                         }
6264                         /*
6265                          * We're authoritative for an ancestor of QNAME.
6266                          */
6267                         if (!USECACHE(client) || !RECURSIONOK(client)) {
6268                                 dns_fixedname_t fixed;
6269
6270                                 dns_fixedname_init(&fixed);
6271                                 dns_name_copy(fname,
6272                                               dns_fixedname_name(&fixed), NULL);
6273
6274                                 /*
6275                                  * If we don't have a cache, this is the best
6276                                  * answer.
6277                                  *
6278                                  * If the client is making a nonrecursive
6279                                  * query we always give out the authoritative
6280                                  * delegation.  This way even if we get
6281                                  * junk in our cache, we won't fail in our
6282                                  * role as the delegating authority if another
6283                                  * nameserver asks us about a delegated
6284                                  * subzone.
6285                                  *
6286                                  * We enable the retrieval of glue for this
6287                                  * database by setting client->query.gluedb.
6288                                  */
6289                                 client->query.gluedb = db;
6290                                 client->query.isreferral = ISC_TRUE;
6291                                 /*
6292                                  * We must ensure NOADDITIONAL is off,
6293                                  * because the generation of
6294                                  * additional data is required in
6295                                  * delegations.
6296                                  */
6297                                 client->query.attributes &=
6298                                         ~NS_QUERYATTR_NOADDITIONAL;
6299                                 if (sigrdataset != NULL)
6300                                         sigrdatasetp = &sigrdataset;
6301                                 else
6302                                         sigrdatasetp = NULL;
6303                                 query_addrrset(client, &fname,
6304                                                &rdataset, sigrdatasetp,
6305                                                dbuf, DNS_SECTION_AUTHORITY);
6306                                 client->query.gluedb = NULL;
6307                                 if (WANTDNSSEC(client))
6308                                         query_addds(client, db, node, version,
6309                                                    dns_fixedname_name(&fixed));
6310                         } else {
6311                                 /*
6312                                  * We might have a better answer or delegation
6313                                  * in the cache.  We'll remember the current
6314                                  * values of fname, rdataset, and sigrdataset.
6315                                  * We'll then go looking for QNAME in the
6316                                  * cache.  If we find something better, we'll
6317                                  * use it instead.
6318                                  */
6319                                 query_keepname(client, fname, dbuf);
6320                                 zdb = db;
6321                                 zfname = fname;
6322                                 fname = NULL;
6323                                 zrdataset = rdataset;
6324                                 rdataset = NULL;
6325                                 zsigrdataset = sigrdataset;
6326                                 sigrdataset = NULL;
6327                                 dns_db_detachnode(db, &node);
6328                                 zversion = version;
6329                                 version = NULL;
6330                                 db = NULL;
6331                                 dns_db_attach(client->view->cachedb, &db);
6332                                 is_zone = ISC_FALSE;
6333                                 goto db_find;
6334                         }
6335                 } else {
6336                         if (zfname != NULL &&
6337                             (!dns_name_issubdomain(fname, zfname) ||
6338                              (is_staticstub_zone &&
6339                               dns_name_equal(fname, zfname)))) {
6340                                 /*
6341                                  * In the following cases use "authoritative"
6342                                  * data instead of the cache delegation:
6343                                  * 1. We've already got a delegation from
6344                                  *    authoritative data, and it is better
6345                                  *    than what we found in the cache.
6346                                  * 2. The query name matches the origin name
6347                                  *    of a static-stub zone.  This needs to be
6348                                  *    considered for the case where the NS of
6349                                  *    the static-stub zone and the cached NS
6350                                  *    are different.  We still need to contact
6351                                  *    the nameservers configured in the
6352                                  *    static-stub zone.
6353                                  */
6354                                 query_releasename(client, &fname);
6355                                 fname = zfname;
6356                                 zfname = NULL;
6357                                 /*
6358                                  * We've already done query_keepname() on
6359                                  * zfname, so we must set dbuf to NULL to
6360                                  * prevent query_addrrset() from trying to
6361                                  * call query_keepname() again.
6362                                  */
6363                                 dbuf = NULL;
6364                                 query_putrdataset(client, &rdataset);
6365                                 if (sigrdataset != NULL)
6366                                         query_putrdataset(client,
6367                                                           &sigrdataset);
6368                                 rdataset = zrdataset;
6369                                 zrdataset = NULL;
6370                                 sigrdataset = zsigrdataset;
6371                                 zsigrdataset = NULL;
6372                                 version = zversion;
6373                                 zversion = NULL;
6374                                 /*
6375                                  * We don't clean up zdb here because we
6376                                  * may still need it.  It will get cleaned
6377                                  * up by the main cleanup code.
6378                                  */
6379                         }
6380
6381                         if (RECURSIONOK(client)) {
6382                                 /*
6383                                  * Recurse!
6384                                  */
6385                                 if (dns_rdatatype_atparent(type))
6386                                         result = query_recurse(client, qtype,
6387                                                          client->query.qname,
6388                                                          NULL, NULL, resuming);
6389                                 else if (dns64)
6390                                         result = query_recurse(client,
6391                                                          dns_rdatatype_a,
6392                                                          client->query.qname,
6393                                                          NULL, NULL, resuming);
6394                                 else
6395                                         result = query_recurse(client, qtype,
6396                                                          client->query.qname,
6397                                                          fname, rdataset,
6398                                                          resuming);
6399
6400                                 if (result == ISC_R_SUCCESS) {
6401                                         client->query.attributes |=
6402                                                 NS_QUERYATTR_RECURSING;
6403                                         if (dns64)
6404                                                 client->query.attributes |=
6405                                                         NS_QUERYATTR_DNS64;
6406                                         if (dns64_exclude)
6407                                                 client->query.attributes |=
6408                                                       NS_QUERYATTR_DNS64EXCLUDE;
6409                                 } else if (result == DNS_R_DUPLICATE ||
6410                                          result == DNS_R_DROP)
6411                                         QUERY_ERROR(result);
6412                                 else
6413                                         RECURSE_ERROR(result);
6414                         } else {
6415                                 dns_fixedname_t fixed;
6416
6417                                 dns_fixedname_init(&fixed);
6418                                 dns_name_copy(fname,
6419                                               dns_fixedname_name(&fixed), NULL);
6420                                 /*
6421                                  * This is the best answer.
6422                                  */
6423                                 client->query.attributes |=
6424                                         NS_QUERYATTR_CACHEGLUEOK;
6425                                 client->query.gluedb = zdb;
6426                                 client->query.isreferral = ISC_TRUE;
6427                                 /*
6428                                  * We must ensure NOADDITIONAL is off,
6429                                  * because the generation of
6430                                  * additional data is required in
6431                                  * delegations.
6432                                  */
6433                                 client->query.attributes &=
6434                                         ~NS_QUERYATTR_NOADDITIONAL;
6435                                 if (sigrdataset != NULL)
6436                                         sigrdatasetp = &sigrdataset;
6437                                 else
6438                                         sigrdatasetp = NULL;
6439                                 query_addrrset(client, &fname,
6440                                                &rdataset, sigrdatasetp,
6441                                                dbuf, DNS_SECTION_AUTHORITY);
6442                                 client->query.gluedb = NULL;
6443                                 client->query.attributes &=
6444                                         ~NS_QUERYATTR_CACHEGLUEOK;
6445                                 if (WANTDNSSEC(client))
6446                                         query_addds(client, db, node, version,
6447                                                    dns_fixedname_name(&fixed));
6448                         }
6449                 }
6450                 goto cleanup;
6451
6452         case DNS_R_EMPTYNAME:
6453         case DNS_R_NXRRSET:
6454         iszone_nxrrset:
6455                 INSIST(is_zone);
6456
6457 #ifdef dns64_bis_return_excluded_addresses
6458                 if (dns64)
6459 #else
6460                 if (dns64 && !dns64_exclude)
6461 #endif
6462                 {
6463                         /*
6464                          * Restore the answers from the previous AAAA lookup.
6465                          */
6466                         if (rdataset != NULL)
6467                                 query_putrdataset(client, &rdataset);
6468                         if (sigrdataset != NULL)
6469                                 query_putrdataset(client, &sigrdataset);
6470                         rdataset = client->query.dns64_aaaa;
6471                         sigrdataset = client->query.dns64_sigaaaa;
6472                         client->query.dns64_aaaa = NULL;
6473                         client->query.dns64_sigaaaa = NULL;
6474                         if (fname == NULL) {
6475                                 dbuf = query_getnamebuf(client);
6476                                 if (dbuf == NULL) {
6477                                         QUERY_ERROR(DNS_R_SERVFAIL);
6478                                         goto cleanup;
6479                                 }
6480                                 fname = query_newname(client, dbuf, &b);
6481                                 if (fname == NULL) {
6482                                         QUERY_ERROR(DNS_R_SERVFAIL);
6483                                         goto cleanup;
6484                                 }
6485                         }
6486                         dns_name_copy(client->query.qname, fname, NULL);
6487                         dns64 = ISC_FALSE;
6488 #ifdef dns64_bis_return_excluded_addresses
6489                         /*
6490                          * Resume the diverted processing of the AAAA response?
6491                          */
6492                         if (dns64_excluded)
6493                                 break;
6494 #endif
6495                 } else if (result == DNS_R_NXRRSET &&
6496                            !ISC_LIST_EMPTY(client->view->dns64) &&
6497                            client->message->rdclass == dns_rdataclass_in &&
6498                            qtype == dns_rdatatype_aaaa)
6499                 {
6500                         /*
6501                          * Look to see if there are A records for this
6502                          * name.
6503                          */
6504                         INSIST(client->query.dns64_aaaa == NULL);
6505                         INSIST(client->query.dns64_sigaaaa == NULL);
6506                         client->query.dns64_aaaa = rdataset;
6507                         client->query.dns64_sigaaaa = sigrdataset;
6508                         client->query.dns64_ttl = dns64_ttl(db, version);
6509                         query_releasename(client, &fname);
6510                         dns_db_detachnode(db, &node);
6511                         rdataset = NULL;
6512                         sigrdataset = NULL;
6513                         type = qtype = dns_rdatatype_a;
6514                         rpz_st = client->query.rpz_st;
6515                         if (rpz_st != NULL) {
6516                                 /*
6517                                  * Arrange for RPZ rewriting of any A records.
6518                                  */
6519                                 if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0)
6520                                         is_zone = rpz_st->q.is_zone;
6521                                 rpz_st_clear(client);
6522                         }
6523                         dns64 = ISC_TRUE;
6524                         goto db_find;
6525                 }
6526
6527                 /*
6528                  * Look for a NSEC3 record if we don't have a NSEC record.
6529                  */
6530  nxrrset_rrsig:
6531                 if (!dns_rdataset_isassociated(rdataset) &&
6532                      WANTDNSSEC(client)) {
6533                         if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
6534                                 dns_name_t *found;
6535                                 dns_name_t *qname;
6536
6537                                 dns_fixedname_init(&fixed);
6538                                 found = dns_fixedname_name(&fixed);
6539                                 qname = client->query.qname;
6540
6541                                 query_findclosestnsec3(qname, db, version,
6542                                                        client, rdataset,
6543                                                        sigrdataset, fname,
6544                                                        ISC_TRUE, found);
6545                                 /*
6546                                  * Did we find the closest provable encloser
6547                                  * instead? If so add the nearest to the
6548                                  * closest provable encloser.
6549                                  */
6550                                 if (dns_rdataset_isassociated(rdataset) &&
6551                                     !dns_name_equal(qname, found) &&
6552                                     !(ns_g_nonearest &&
6553                                       qtype != dns_rdatatype_ds))
6554                                 {
6555                                         unsigned int count;
6556                                         unsigned int skip;
6557
6558                                         /*
6559                                          * Add the closest provable encloser.
6560                                          */
6561                                         query_addrrset(client, &fname,
6562                                                        &rdataset, &sigrdataset,
6563                                                        dbuf,
6564                                                        DNS_SECTION_AUTHORITY);
6565
6566                                         count = dns_name_countlabels(found)
6567                                                          + 1;
6568                                         skip = dns_name_countlabels(qname) -
6569                                                          count;
6570                                         dns_name_getlabelsequence(qname, skip,
6571                                                                   count,
6572                                                                   found);
6573
6574                                         fixfname(client, &fname, &dbuf, &b);
6575                                         fixrdataset(client, &rdataset);
6576                                         fixrdataset(client, &sigrdataset);
6577                                         if (fname == NULL ||
6578                                             rdataset == NULL ||
6579                                             sigrdataset == NULL) {
6580                                                 QUERY_ERROR(DNS_R_SERVFAIL);
6581                                                 goto cleanup;
6582                                         }
6583                                         /*
6584                                          * 'nearest' doesn't exist so
6585                                          * 'exist' is set to ISC_FALSE.
6586                                          */
6587                                         query_findclosestnsec3(found, db,
6588                                                                version,
6589                                                                client,
6590                                                                rdataset,
6591                                                                sigrdataset,
6592                                                                fname,
6593                                                                ISC_FALSE,
6594                                                                NULL);
6595                                 }
6596                         } else {
6597                                 query_releasename(client, &fname);
6598                                 query_addwildcardproof(client, db, version,
6599                                                        client->query.qname,
6600                                                        ISC_FALSE, ISC_TRUE);
6601                         }
6602                 }
6603                 if (dns_rdataset_isassociated(rdataset)) {
6604                         /*
6605                          * If we've got a NSEC record, we need to save the
6606                          * name now because we're going call query_addsoa()
6607                          * below, and it needs to use the name buffer.
6608                          */
6609                         query_keepname(client, fname, dbuf);
6610                 } else if (fname != NULL) {
6611                         /*
6612                          * We're not going to use fname, and need to release
6613                          * our hold on the name buffer so query_addsoa()
6614                          * may use it.
6615                          */
6616                         query_releasename(client, &fname);
6617                 }
6618                 /*
6619                  * Add SOA.
6620                  */
6621                 result = query_addsoa(client, db, version, ISC_UINT32_MAX,
6622                                       dns_rdataset_isassociated(rdataset));
6623                 if (result != ISC_R_SUCCESS) {
6624                         QUERY_ERROR(result);
6625                         goto cleanup;
6626                 }
6627                 /*
6628                  * Add NSEC record if we found one.
6629                  */
6630                 if (WANTDNSSEC(client)) {
6631                         if (dns_rdataset_isassociated(rdataset))
6632                                 query_addnxrrsetnsec(client, db, version,
6633                                                      &fname, &rdataset,
6634                                                      &sigrdataset);
6635                 }
6636                 goto cleanup;
6637
6638         case DNS_R_EMPTYWILD:
6639                 empty_wild = ISC_TRUE;
6640                 /* FALLTHROUGH */
6641
6642         case DNS_R_NXDOMAIN:
6643                 INSIST(is_zone);
6644                 if (!empty_wild &&
6645                     redirect(client, fname, rdataset, &node, &db, &version,
6646                              type))
6647                         break;
6648                 if (dns_rdataset_isassociated(rdataset)) {
6649                         /*
6650                          * If we've got a NSEC record, we need to save the
6651                          * name now because we're going call query_addsoa()
6652                          * below, and it needs to use the name buffer.
6653                          */
6654                         query_keepname(client, fname, dbuf);
6655                 } else if (fname != NULL) {
6656                         /*
6657                          * We're not going to use fname, and need to release
6658                          * our hold on the name buffer so query_addsoa()
6659                          * may use it.
6660                          */
6661                         query_releasename(client, &fname);
6662                 }
6663
6664                 /*
6665                  * Add SOA.  If the query was for a SOA record force the
6666                  * ttl to zero so that it is possible for clients to find
6667                  * the containing zone of an arbitrary name with a stub
6668                  * resolver and not have it cached.
6669                  */
6670                 if (qtype == dns_rdatatype_soa &&
6671                     zone != NULL &&
6672                     dns_zone_getzeronosoattl(zone))
6673                         result = query_addsoa(client, db, version, 0,
6674                                           dns_rdataset_isassociated(rdataset));
6675                 else
6676                         result = query_addsoa(client, db, version,
6677                                               ISC_UINT32_MAX,
6678                                           dns_rdataset_isassociated(rdataset));
6679                 if (result != ISC_R_SUCCESS) {
6680                         QUERY_ERROR(result);
6681                         goto cleanup;
6682                 }
6683
6684                 if (WANTDNSSEC(client)) {
6685                         /*
6686                          * Add NSEC record if we found one.
6687                          */
6688                         if (dns_rdataset_isassociated(rdataset))
6689                                 query_addrrset(client, &fname, &rdataset,
6690                                                &sigrdataset,
6691                                                NULL, DNS_SECTION_AUTHORITY);
6692                         query_addwildcardproof(client, db, version,
6693                                                client->query.qname, ISC_FALSE,
6694                                                ISC_FALSE);
6695                 }
6696
6697                 /*
6698                  * Set message rcode.
6699                  */
6700                 if (empty_wild)
6701                         client->message->rcode = dns_rcode_noerror;
6702                 else
6703                         client->message->rcode = dns_rcode_nxdomain;
6704                 goto cleanup;
6705
6706         case DNS_R_NCACHENXDOMAIN:
6707                 if (redirect(client, fname, rdataset, &node, &db, &version,
6708                              type))
6709                         break;
6710         case DNS_R_NCACHENXRRSET:
6711         ncache_nxrrset:
6712                 INSIST(!is_zone);
6713                 authoritative = ISC_FALSE;
6714                 /*
6715                  * Set message rcode, if required.
6716                  */
6717                 if (result == DNS_R_NCACHENXDOMAIN)
6718                         client->message->rcode = dns_rcode_nxdomain;
6719                 /*
6720                  * Look for RFC 1918 leakage from Internet.
6721                  */
6722                 if (result == DNS_R_NCACHENXDOMAIN &&
6723                     qtype == dns_rdatatype_ptr &&
6724                     client->message->rdclass == dns_rdataclass_in &&
6725                     dns_name_countlabels(fname) == 7)
6726                         warn_rfc1918(client, fname, rdataset);
6727
6728 #ifdef dns64_bis_return_excluded_addresses
6729                 if (dns64)
6730 #else
6731                 if (dns64 && !dns64_exclude)
6732 #endif
6733                 {
6734                         /*
6735                          * Restore the answers from the previous AAAA lookup.
6736                          */
6737                         if (rdataset != NULL)
6738                                 query_putrdataset(client, &rdataset);
6739                         if (sigrdataset != NULL)
6740                                 query_putrdataset(client, &sigrdataset);
6741                         rdataset = client->query.dns64_aaaa;
6742                         sigrdataset = client->query.dns64_sigaaaa;
6743                         client->query.dns64_aaaa = NULL;
6744                         client->query.dns64_sigaaaa = NULL;
6745                         if (fname == NULL) {
6746                                 dbuf = query_getnamebuf(client);
6747                                 if (dbuf == NULL) {
6748                                         QUERY_ERROR(DNS_R_SERVFAIL);
6749                                         goto cleanup;
6750                                 }
6751                                 fname = query_newname(client, dbuf, &b);
6752                                 if (fname == NULL) {
6753                                         QUERY_ERROR(DNS_R_SERVFAIL);
6754                                         goto cleanup;
6755                                 }
6756                         }
6757                         dns_name_copy(client->query.qname, fname, NULL);
6758                         dns64 = ISC_FALSE;
6759 #ifdef dns64_bis_return_excluded_addresses
6760                         if (dns64_excluded)
6761                                 break;
6762 #endif
6763                 } else if (result == DNS_R_NCACHENXRRSET &&
6764                            !ISC_LIST_EMPTY(client->view->dns64) &&
6765                            client->message->rdclass == dns_rdataclass_in &&
6766                            qtype == dns_rdatatype_aaaa)
6767                 {
6768                         /*
6769                          * Look to see if there are A records for this
6770                          * name.
6771                          */
6772                         INSIST(client->query.dns64_aaaa == NULL);
6773                         INSIST(client->query.dns64_sigaaaa == NULL);
6774                         client->query.dns64_aaaa = rdataset;
6775                         client->query.dns64_sigaaaa = sigrdataset;
6776                         /*
6777                          * If the ttl is zero we need to workout if we have just
6778                          * decremented to zero or if there was no negative cache
6779                          * ttl in the answer.
6780                          */
6781                         if (rdataset->ttl != 0)
6782                                 client->query.dns64_ttl = rdataset->ttl;
6783                         else if (dns_rdataset_first(rdataset) == ISC_R_SUCCESS)
6784                                 client->query.dns64_ttl = 0;
6785                         query_releasename(client, &fname);
6786                         dns_db_detachnode(db, &node);
6787                         rdataset = NULL;
6788                         sigrdataset = NULL;
6789                         fname = NULL;
6790                         type = qtype = dns_rdatatype_a;
6791                         rpz_st = client->query.rpz_st;
6792                         if (rpz_st != NULL) {
6793                                 /*
6794                                  * Arrange for RPZ rewriting of any A records.
6795                                  */
6796                                 if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0)
6797                                         is_zone = rpz_st->q.is_zone;
6798                                 rpz_st_clear(client);
6799                         }
6800                         dns64 = ISC_TRUE;
6801                         goto db_find;
6802                 }
6803
6804                 /*
6805                  * We don't call query_addrrset() because we don't need any
6806                  * of its extra features (and things would probably break!).
6807                  */
6808                 query_keepname(client, fname, dbuf);
6809                 dns_message_addname(client->message, fname,
6810                                     DNS_SECTION_AUTHORITY);
6811                 ISC_LIST_APPEND(fname->list, rdataset, link);
6812                 fname = NULL;
6813                 rdataset = NULL;
6814                 goto cleanup;
6815
6816         case DNS_R_CNAME:
6817                 /*
6818                  * Keep a copy of the rdataset.  We have to do this because
6819                  * query_addrrset may clear 'rdataset' (to prevent the
6820                  * cleanup code from cleaning it up).
6821                  */
6822                 trdataset = rdataset;
6823                 /*
6824                  * Add the CNAME to the answer section.
6825                  */
6826                 if (sigrdataset != NULL)
6827                         sigrdatasetp = &sigrdataset;
6828                 else
6829                         sigrdatasetp = NULL;
6830                 if (WANTDNSSEC(client) &&
6831                     (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
6832                 {
6833                         dns_fixedname_init(&wildcardname);
6834                         dns_name_copy(fname, dns_fixedname_name(&wildcardname),
6835                                       NULL);
6836                         need_wildcardproof = ISC_TRUE;
6837                 }
6838                 if (NOQNAME(rdataset) && WANTDNSSEC(client))
6839                         noqname = rdataset;
6840                 else
6841                         noqname = NULL;
6842                 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
6843                                DNS_SECTION_ANSWER);
6844                 if (noqname != NULL)
6845                         query_addnoqnameproof(client, noqname);
6846                 /*
6847                  * We set the PARTIALANSWER attribute so that if anything goes
6848                  * wrong later on, we'll return what we've got so far.
6849                  */
6850                 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
6851                 /*
6852                  * Reset qname to be the target name of the CNAME and restart
6853                  * the query.
6854                  */
6855                 tname = NULL;
6856                 result = dns_message_gettempname(client->message, &tname);
6857                 if (result != ISC_R_SUCCESS)
6858                         goto cleanup;
6859                 result = dns_rdataset_first(trdataset);
6860                 if (result != ISC_R_SUCCESS) {
6861                         dns_message_puttempname(client->message, &tname);
6862                         goto cleanup;
6863                 }
6864                 dns_rdataset_current(trdataset, &rdata);
6865                 result = dns_rdata_tostruct(&rdata, &cname, NULL);
6866                 dns_rdata_reset(&rdata);
6867                 if (result != ISC_R_SUCCESS) {
6868                         dns_message_puttempname(client->message, &tname);
6869                         goto cleanup;
6870                 }
6871                 dns_name_init(tname, NULL);
6872                 result = dns_name_dup(&cname.cname, client->mctx, tname);
6873                 if (result != ISC_R_SUCCESS) {
6874                         dns_message_puttempname(client->message, &tname);
6875                         dns_rdata_freestruct(&cname);
6876                         goto cleanup;
6877                 }
6878                 dns_rdata_freestruct(&cname);
6879                 ns_client_qnamereplace(client, tname);
6880                 want_restart = ISC_TRUE;
6881                 if (!WANTRECURSION(client))
6882                         options |= DNS_GETDB_NOLOG;
6883                 goto addauth;
6884         case DNS_R_DNAME:
6885                 /*
6886                  * Compare the current qname to the found name.  We need
6887                  * to know how many labels and bits are in common because
6888                  * we're going to have to split qname later on.
6889                  */
6890                 namereln = dns_name_fullcompare(client->query.qname, fname,
6891                                                 &order, &nlabels);
6892                 INSIST(namereln == dns_namereln_subdomain);
6893                 /*
6894                  * Keep a copy of the rdataset.  We have to do this because
6895                  * query_addrrset may clear 'rdataset' (to prevent the
6896                  * cleanup code from cleaning it up).
6897                  */
6898                 trdataset = rdataset;
6899                 /*
6900                  * Add the DNAME to the answer section.
6901                  */
6902                 if (sigrdataset != NULL)
6903                         sigrdatasetp = &sigrdataset;
6904                 else
6905                         sigrdatasetp = NULL;
6906                 if (WANTDNSSEC(client) &&
6907                     (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
6908                 {
6909                         dns_fixedname_init(&wildcardname);
6910                         dns_name_copy(fname, dns_fixedname_name(&wildcardname),
6911                                       NULL);
6912                         need_wildcardproof = ISC_TRUE;
6913                 }
6914                 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
6915                                DNS_SECTION_ANSWER);
6916                 /*
6917                  * We set the PARTIALANSWER attribute so that if anything goes
6918                  * wrong later on, we'll return what we've got so far.
6919                  */
6920                 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
6921                 /*
6922                  * Get the target name of the DNAME.
6923                  */
6924                 tname = NULL;
6925                 result = dns_message_gettempname(client->message, &tname);
6926                 if (result != ISC_R_SUCCESS)
6927                         goto cleanup;
6928                 result = dns_rdataset_first(trdataset);
6929                 if (result != ISC_R_SUCCESS) {
6930                         dns_message_puttempname(client->message, &tname);
6931                         goto cleanup;
6932                 }
6933                 dns_rdataset_current(trdataset, &rdata);
6934                 result = dns_rdata_tostruct(&rdata, &dname, NULL);
6935                 dns_rdata_reset(&rdata);
6936                 if (result != ISC_R_SUCCESS) {
6937                         dns_message_puttempname(client->message, &tname);
6938                         goto cleanup;
6939                 }
6940                 dns_name_clone(&dname.dname, tname);
6941                 dns_rdata_freestruct(&dname);
6942                 /*
6943                  * Construct the new qname consisting of
6944                  * <found name prefix>.<dname target>
6945                  */
6946                 dns_fixedname_init(&fixed);
6947                 prefix = dns_fixedname_name(&fixed);
6948                 dns_name_split(client->query.qname, nlabels, prefix, NULL);
6949                 INSIST(fname == NULL);
6950                 dbuf = query_getnamebuf(client);
6951                 if (dbuf == NULL) {
6952                         dns_message_puttempname(client->message, &tname);
6953                         goto cleanup;
6954                 }
6955                 fname = query_newname(client, dbuf, &b);
6956                 if (fname == NULL) {
6957                         dns_message_puttempname(client->message, &tname);
6958                         goto cleanup;
6959                 }
6960                 result = dns_name_concatenate(prefix, tname, fname, NULL);
6961                 dns_message_puttempname(client->message, &tname);
6962
6963                 /*
6964                  * RFC2672, section 4.1, subsection 3c says
6965                  * we should return YXDOMAIN if the constructed
6966                  * name would be too long.
6967                  */
6968                 if (result == DNS_R_NAMETOOLONG)
6969                         client->message->rcode = dns_rcode_yxdomain;
6970                 if (result != ISC_R_SUCCESS)
6971                         goto cleanup;
6972
6973                 query_keepname(client, fname, dbuf);
6974                 /*
6975                  * Synthesize a CNAME consisting of
6976                  *   <old qname> <dname ttl> CNAME <new qname>
6977                  *          with <dname trust value>
6978                  *
6979                  * Synthesize a CNAME so old old clients that don't understand
6980                  * DNAME can chain.
6981                  *
6982                  * We do not try to synthesize a signature because we hope
6983                  * that security aware servers will understand DNAME.  Also,
6984                  * even if we had an online key, making a signature
6985                  * on-the-fly is costly, and not really legitimate anyway
6986                  * since the synthesized CNAME is NOT in the zone.
6987                  */
6988                 result = query_add_cname(client, client->query.qname, fname,
6989                                          trdataset->trust, trdataset->ttl);
6990                 if (result != ISC_R_SUCCESS)
6991                         goto cleanup;
6992                 /*
6993                  * Switch to the new qname and restart.
6994                  */
6995                 ns_client_qnamereplace(client, fname);
6996                 fname = NULL;
6997                 want_restart = ISC_TRUE;
6998                 if (!WANTRECURSION(client))
6999                         options |= DNS_GETDB_NOLOG;
7000                 goto addauth;
7001         default:
7002                 /*
7003                  * Something has gone wrong.
7004                  */
7005                 QUERY_ERROR(DNS_R_SERVFAIL);
7006                 goto cleanup;
7007         }
7008
7009         if (WANTDNSSEC(client) &&
7010             (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
7011         {
7012                 dns_fixedname_init(&wildcardname);
7013                 dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL);
7014                 need_wildcardproof = ISC_TRUE;
7015         }
7016
7017 #ifdef ALLOW_FILTER_AAAA_ON_V4
7018         if (client->view->v4_aaaa != dns_v4_aaaa_ok &&
7019             is_v4_client(client) &&
7020             ns_client_checkaclsilent(client, NULL,
7021                                      client->view->v4_aaaa_acl,
7022                                      ISC_TRUE) == ISC_R_SUCCESS)
7023                 client->filter_aaaa = client->view->v4_aaaa;
7024         else
7025                 client->filter_aaaa = dns_v4_aaaa_ok;
7026
7027 #endif
7028
7029         if (type == dns_rdatatype_any) {
7030 #ifdef ALLOW_FILTER_AAAA_ON_V4
7031                 isc_boolean_t have_aaaa, have_a, have_sig;
7032
7033                 /*
7034                  * The filter-aaaa-on-v4 option should
7035                  * suppress AAAAs for IPv4 clients if there is an A.
7036                  * If we are not authoritative, assume there is a A
7037                  * even in if it is not in our cache.  This assumption could
7038                  * be wrong but it is a good bet.
7039                  */
7040                 have_aaaa = ISC_FALSE;
7041                 have_a = !authoritative;
7042                 have_sig = ISC_FALSE;
7043 #endif
7044                 /*
7045                  * XXXRTH  Need to handle zonecuts with special case
7046                  * code.
7047                  */
7048                 n = 0;
7049                 rdsiter = NULL;
7050                 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
7051                 if (result != ISC_R_SUCCESS) {
7052                         QUERY_ERROR(DNS_R_SERVFAIL);
7053                         goto cleanup;
7054                 }
7055
7056                 /*
7057                  * Calling query_addrrset() with a non-NULL dbuf is going
7058                  * to either keep or release the name.  We don't want it to
7059                  * release fname, since we may have to call query_addrrset()
7060                  * more than once.  That means we have to call query_keepname()
7061                  * now, and pass a NULL dbuf to query_addrrset().
7062                  *
7063                  * If we do a query_addrrset() below, we must set fname to
7064                  * NULL before leaving this block, otherwise we might try to
7065                  * cleanup fname even though we're using it!
7066                  */
7067                 query_keepname(client, fname, dbuf);
7068                 tname = fname;
7069                 result = dns_rdatasetiter_first(rdsiter);
7070                 while (result == ISC_R_SUCCESS) {
7071                         dns_rdatasetiter_current(rdsiter, rdataset);
7072 #ifdef ALLOW_FILTER_AAAA_ON_V4
7073                         /*
7074                          * Notice the presence of A and AAAAs so
7075                          * that AAAAs can be hidden from IPv4 clients.
7076                          */
7077                         if (client->filter_aaaa != dns_v4_aaaa_ok) {
7078                                 if (rdataset->type == dns_rdatatype_aaaa)
7079                                         have_aaaa = ISC_TRUE;
7080                                 else if (rdataset->type == dns_rdatatype_a)
7081                                         have_a = ISC_TRUE;
7082                         }
7083 #endif
7084                         if (is_zone && qtype == dns_rdatatype_any &&
7085                             !dns_db_issecure(db) &&
7086                             dns_rdatatype_isdnssec(rdataset->type)) {
7087                                 /*
7088                                  * The zone is transitioning from insecure
7089                                  * to secure. Hide the dnssec records from
7090                                  * ANY queries.
7091                                  */
7092                                 dns_rdataset_disassociate(rdataset);
7093                         } else if ((qtype == dns_rdatatype_any ||
7094                              rdataset->type == qtype) && rdataset->type != 0) {
7095 #ifdef ALLOW_FILTER_AAAA_ON_V4
7096                                 if (dns_rdatatype_isdnssec(rdataset->type))
7097                                         have_sig = ISC_TRUE;
7098 #endif
7099                                 if (NOQNAME(rdataset) && WANTDNSSEC(client))
7100                                         noqname = rdataset;
7101                                 else
7102                                         noqname = NULL;
7103                                 rpz_st = client->query.rpz_st;
7104                                 if (rpz_st != NULL)
7105                                         rdataset->ttl = ISC_MIN(rdataset->ttl,
7106                                                             rpz_st->m.ttl);
7107                                 query_addrrset(client,
7108                                                fname != NULL ? &fname : &tname,
7109                                                &rdataset, NULL,
7110                                                NULL, DNS_SECTION_ANSWER);
7111                                 if (noqname != NULL)
7112                                         query_addnoqnameproof(client, noqname);
7113                                 n++;
7114                                 INSIST(tname != NULL);
7115                                 /*
7116                                  * rdataset is non-NULL only in certain
7117                                  * pathological cases involving DNAMEs.
7118                                  */
7119                                 if (rdataset != NULL)
7120                                         query_putrdataset(client, &rdataset);
7121                                 rdataset = query_newrdataset(client);
7122                                 if (rdataset == NULL)
7123                                         break;
7124                         } else {
7125                                 /*
7126                                  * We're not interested in this rdataset.
7127                                  */
7128                                 dns_rdataset_disassociate(rdataset);
7129                         }
7130                         result = dns_rdatasetiter_next(rdsiter);
7131                 }
7132
7133 #ifdef ALLOW_FILTER_AAAA_ON_V4
7134                 /*
7135                  * Filter AAAAs if there is an A and there is no signature
7136                  * or we are supposed to break DNSSEC.
7137                  */
7138                 if (client->filter_aaaa == dns_v4_aaaa_break_dnssec)
7139                         client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
7140                 else if (client->filter_aaaa != dns_v4_aaaa_ok &&
7141                          have_aaaa && have_a &&
7142                          (!have_sig || !WANTDNSSEC(client)))
7143                           client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
7144 #endif
7145                 if (fname != NULL)
7146                         dns_message_puttempname(client->message, &fname);
7147
7148                 if (n == 0) {
7149                         /*
7150                          * No matching rdatasets found in cache. If we were
7151                          * searching for RRSIG/SIG, that's probably okay;
7152                          * otherwise this is an error condition.
7153                          */
7154                         if ((qtype == dns_rdatatype_rrsig ||
7155                              qtype == dns_rdatatype_sig) &&
7156                             result == ISC_R_NOMORE) {
7157                                 if (!is_zone) {
7158                                         authoritative = ISC_FALSE;
7159                                         dns_rdatasetiter_destroy(&rdsiter);
7160                                         client->attributes &= ~NS_CLIENTATTR_RA;
7161                                         goto addauth;
7162                                 }
7163
7164                                 if (qtype == dns_rdatatype_rrsig &&
7165                                     dns_db_issecure(db)) {
7166                                         char namebuf[DNS_NAME_FORMATSIZE];
7167                                         dns_name_format(client->query.qname,
7168                                                         namebuf,
7169                                                         sizeof(namebuf));
7170                                         ns_client_log(client,
7171                                                       DNS_LOGCATEGORY_DNSSEC,
7172                                                       NS_LOGMODULE_QUERY,
7173                                                       ISC_LOG_WARNING,
7174                                                       "missing signature "
7175                                                       "for %s", namebuf);
7176                                 }
7177
7178                                 dns_rdatasetiter_destroy(&rdsiter);
7179                                 fname = query_newname(client, dbuf, &b);
7180                                 goto nxrrset_rrsig;
7181                         } else
7182                                 result = DNS_R_SERVFAIL;
7183                 }
7184
7185                 dns_rdatasetiter_destroy(&rdsiter);
7186                 if (result != ISC_R_NOMORE) {
7187                         QUERY_ERROR(DNS_R_SERVFAIL);
7188                         goto cleanup;
7189                 }
7190         } else {
7191                 /*
7192                  * This is the "normal" case -- an ordinary question to which
7193                  * we know the answer.
7194                  */
7195
7196 #ifdef ALLOW_FILTER_AAAA_ON_V4
7197                 /*
7198                  * Optionally hide AAAAs from IPv4 clients if there is an A.
7199                  * We add the AAAAs now, but might refuse to render them later
7200                  * after DNSSEC is figured out.
7201                  * This could be more efficient, but the whole idea is
7202                  * so fundamentally wrong, unavoidably inaccurate, and
7203                  * unneeded that it is best to keep it as short as possible.
7204                  */
7205                 if (client->filter_aaaa == dns_v4_aaaa_break_dnssec ||
7206                     (client->filter_aaaa == dns_v4_aaaa_filter &&
7207                      (!WANTDNSSEC(client) || sigrdataset == NULL ||
7208                      !dns_rdataset_isassociated(sigrdataset))))
7209                 {
7210                         if (qtype == dns_rdatatype_aaaa) {
7211                                 trdataset = query_newrdataset(client);
7212                                 result = dns_db_findrdataset(db, node, version,
7213                                                              dns_rdatatype_a, 0,
7214                                                              client->now,
7215                                                              trdataset, NULL);
7216                                 if (dns_rdataset_isassociated(trdataset))
7217                                         dns_rdataset_disassociate(trdataset);
7218                                 query_putrdataset(client, &trdataset);
7219
7220                                 /*
7221                                  * We have an AAAA but the A is not in our cache.
7222                                  * Assume any result other than DNS_R_DELEGATION
7223                                  * or ISC_R_NOTFOUND means there is no A and
7224                                  * so AAAAs are ok.
7225                                  * Assume there is no A if we can't recurse
7226                                  * for this client, although that could be
7227                                  * the wrong answer. What else can we do?
7228                                  * Besides, that we have the AAAA and are using
7229                                  * this mechanism suggests that we care more
7230                                  * about As than AAAAs and would have cached
7231                                  * the A if it existed.
7232                                  */
7233                                 if (result == ISC_R_SUCCESS) {
7234                                         client->attributes |=
7235                                                     NS_CLIENTATTR_FILTER_AAAA;
7236
7237                                 } else if (authoritative ||
7238                                            !RECURSIONOK(client) ||
7239                                            (result != DNS_R_DELEGATION &&
7240                                             result != ISC_R_NOTFOUND)) {
7241                                         client->attributes &=
7242                                                     ~NS_CLIENTATTR_FILTER_AAAA;
7243                                 } else {
7244                                         /*
7245                                          * This is an ugly kludge to recurse
7246                                          * for the A and discard the result.
7247                                          *
7248                                          * Continue to add the AAAA now.
7249                                          * We'll make a note to not render it
7250                                          * if the recursion for the A succeeds.
7251                                          */
7252                                         result = query_recurse(client,
7253                                                         dns_rdatatype_a,
7254                                                         client->query.qname,
7255                                                         NULL, NULL, resuming);
7256                                         if (result == ISC_R_SUCCESS) {
7257                                             client->attributes |=
7258                                                     NS_CLIENTATTR_FILTER_AAAA_RC;
7259                                             client->query.attributes |=
7260                                                         NS_QUERYATTR_RECURSING;
7261                                         }
7262                                 }
7263
7264                         } else if (qtype == dns_rdatatype_a &&
7265                                    (client->attributes &
7266                                             NS_CLIENTATTR_FILTER_AAAA_RC) != 0) {
7267                                 client->attributes &=
7268                                             ~NS_CLIENTATTR_FILTER_AAAA_RC;
7269                                 client->attributes |=
7270                                             NS_CLIENTATTR_FILTER_AAAA;
7271                                 dns_rdataset_disassociate(rdataset);
7272                                 if (sigrdataset != NULL &&
7273                                     dns_rdataset_isassociated(sigrdataset))
7274                                         dns_rdataset_disassociate(sigrdataset);
7275                                 goto cleanup;
7276                         }
7277                 }
7278 #endif
7279                 /*
7280                  * Check to see if the AAAA RRset has non-excluded addresses
7281                  * in it.  If not look for a A RRset.
7282                  */
7283                 INSIST(client->query.dns64_aaaaok == NULL);
7284
7285                 if (qtype == dns_rdatatype_aaaa && !dns64_exclude &&
7286                     !ISC_LIST_EMPTY(client->view->dns64) &&
7287                     client->message->rdclass == dns_rdataclass_in &&
7288                     !dns64_aaaaok(client, rdataset, sigrdataset)) {
7289                         /*
7290                          * Look to see if there are A records for this
7291                          * name.
7292                          */
7293                         client->query.dns64_aaaa = rdataset;
7294                         client->query.dns64_sigaaaa = sigrdataset;
7295                         client->query.dns64_ttl = rdataset->ttl;
7296                         query_releasename(client, &fname);
7297                         dns_db_detachnode(db, &node);
7298                         rdataset = NULL;
7299                         sigrdataset = NULL;
7300                         type = qtype = dns_rdatatype_a;
7301                         rpz_st = client->query.rpz_st;
7302                         if (rpz_st != NULL) {
7303                                 /*
7304                                  * Arrange for RPZ rewriting of any A records.
7305                                  */
7306                                 if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0)
7307                                         is_zone = rpz_st->q.is_zone;
7308                                 rpz_st_clear(client);
7309                         }
7310                         dns64_exclude = dns64 = ISC_TRUE;
7311                         goto db_find;
7312                 }
7313
7314                 if (sigrdataset != NULL)
7315                         sigrdatasetp = &sigrdataset;
7316                 else
7317                         sigrdatasetp = NULL;
7318                 if (NOQNAME(rdataset) && WANTDNSSEC(client))
7319                         noqname = rdataset;
7320                 else
7321                         noqname = NULL;
7322                 /*
7323                  * BIND 8 priming queries need the additional section.
7324                  */
7325                 if (is_zone && qtype == dns_rdatatype_ns &&
7326                     dns_name_equal(client->query.qname, dns_rootname))
7327                         client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL;
7328
7329                 if (dns64) {
7330                         qtype = type = dns_rdatatype_aaaa;
7331                         result = query_dns64(client, &fname, rdataset,
7332                                              sigrdataset, dbuf,
7333                                              DNS_SECTION_ANSWER);
7334                         dns_rdataset_disassociate(rdataset);
7335                         dns_message_puttemprdataset(client->message, &rdataset);
7336                         if (result == ISC_R_NOMORE) {
7337 #ifndef dns64_bis_return_excluded_addresses
7338                                 if (dns64_exclude) {
7339                                         if (!is_zone)
7340                                                 goto cleanup;
7341                                         /*
7342                                          * Add a fake SOA record.
7343                                          */
7344                                         (void)query_addsoa(client, db, version,
7345                                                            600, ISC_FALSE);
7346                                         goto cleanup;
7347                                 }
7348 #endif
7349                                 if (is_zone)
7350                                         goto iszone_nxrrset;
7351                                 else
7352                                         goto ncache_nxrrset;
7353                         } else if (result != ISC_R_SUCCESS) {
7354                                 eresult = result;
7355                                 goto cleanup;
7356                         }
7357                 } else if (client->query.dns64_aaaaok != NULL) {
7358                         query_filter64(client, &fname, rdataset, dbuf,
7359                                        DNS_SECTION_ANSWER);
7360                         query_putrdataset(client, &rdataset);
7361                 } else
7362                         query_addrrset(client, &fname, &rdataset,
7363                                        sigrdatasetp, dbuf, DNS_SECTION_ANSWER);
7364
7365                 if (noqname != NULL)
7366                         query_addnoqnameproof(client, noqname);
7367                 /*
7368                  * We shouldn't ever fail to add 'rdataset'
7369                  * because it's already in the answer.
7370                  */
7371                 INSIST(rdataset == NULL);
7372         }
7373
7374  addauth:
7375         CTRACE("query_find: addauth");
7376         /*
7377          * Add NS records to the authority section (if we haven't already
7378          * added them to the answer section).
7379          */
7380         if (!want_restart && !NOAUTHORITY(client)) {
7381                 if (is_zone) {
7382                         if (!((qtype == dns_rdatatype_ns ||
7383                                qtype == dns_rdatatype_any) &&
7384                               dns_name_equal(client->query.qname,
7385                                              dns_db_origin(db))))
7386                                 (void)query_addns(client, db, version);
7387                 } else if (qtype != dns_rdatatype_ns) {
7388                         if (fname != NULL)
7389                                 query_releasename(client, &fname);
7390                         query_addbestns(client);
7391                 }
7392         }
7393
7394         /*
7395          * Add NSEC records to the authority section if they're needed for
7396          * DNSSEC wildcard proofs.
7397          */
7398         if (need_wildcardproof && dns_db_issecure(db))
7399                 query_addwildcardproof(client, db, version,
7400                                        dns_fixedname_name(&wildcardname),
7401                                        ISC_TRUE, ISC_FALSE);
7402  cleanup:
7403         CTRACE("query_find: cleanup");
7404         /*
7405          * General cleanup.
7406          */
7407         rpz_st = client->query.rpz_st;
7408         if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) {
7409                 rpz_match_clear(rpz_st);
7410                 rpz_st->state &= ~DNS_RPZ_DONE_QNAME;
7411         }
7412         if (rdataset != NULL)
7413                 query_putrdataset(client, &rdataset);
7414         if (sigrdataset != NULL)
7415                 query_putrdataset(client, &sigrdataset);
7416         if (fname != NULL)
7417                 query_releasename(client, &fname);
7418         if (node != NULL)
7419                 dns_db_detachnode(db, &node);
7420         if (db != NULL)
7421                 dns_db_detach(&db);
7422         if (zone != NULL)
7423                 dns_zone_detach(&zone);
7424         if (zdb != NULL) {
7425                 query_putrdataset(client, &zrdataset);
7426                 if (zsigrdataset != NULL)
7427                         query_putrdataset(client, &zsigrdataset);
7428                 if (zfname != NULL)
7429                         query_releasename(client, &zfname);
7430                 dns_db_detach(&zdb);
7431         }
7432         if (event != NULL)
7433                 isc_event_free(ISC_EVENT_PTR(&event));
7434
7435         /*
7436          * AA bit.
7437          */
7438         if (client->query.restarts == 0 && !authoritative) {
7439                 /*
7440                  * We're not authoritative, so we must ensure the AA bit
7441                  * isn't set.
7442                  */
7443                 client->message->flags &= ~DNS_MESSAGEFLAG_AA;
7444         }
7445
7446         /*
7447          * Restart the query?
7448          */
7449         if (want_restart && client->query.restarts < MAX_RESTARTS) {
7450                 client->query.restarts++;
7451                 goto restart;
7452         }
7453
7454 #ifdef USE_RRL
7455         if (eresult != ISC_R_SUCCESS &&
7456             (!PARTIALANSWER(client) || WANTRECURSION(client)
7457              || eresult == DNS_R_DROP))
7458 #else /* USE_RRL */
7459         if (eresult != ISC_R_SUCCESS &&
7460             (!PARTIALANSWER(client) || WANTRECURSION(client)))
7461 #endif /* USE_RRL */
7462         {
7463                 if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) {
7464                         /*
7465                          * This was a duplicate query that we are
7466                          * recursing on or the result of rate limiting.
7467                          * Don't send a response now for a duplicate query,
7468                          * because the original will still cause a response.
7469                          */
7470                         query_next(client, eresult);
7471                 } else {
7472                         /*
7473                          * If we don't have any answer to give the client,
7474                          * or if the client requested recursion and thus wanted
7475                          * the complete answer, send an error response.
7476                          */
7477                         INSIST(line >= 0);
7478                         query_error(client, eresult, line);
7479                 }
7480                 ns_client_detach(&client);
7481         } else if (!RECURSING(client)) {
7482                 /*
7483                  * We are done.  Set up sortlist data for the message
7484                  * rendering code, make a final tweak to the AA bit if the
7485                  * auth-nxdomain config option says so, then render and
7486                  * send the response.
7487                  */
7488                 setup_query_sortlist(client);
7489
7490                 /*
7491                  * If this is a referral and the answer to the question
7492                  * is in the glue sort it to the start of the additional
7493                  * section.
7494                  */
7495                 if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) &&
7496                     client->message->rcode == dns_rcode_noerror &&
7497                     (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa))
7498                         answer_in_glue(client, qtype);
7499
7500                 if (client->message->rcode == dns_rcode_nxdomain &&
7501                     client->view->auth_nxdomain == ISC_TRUE)
7502                         client->message->flags |= DNS_MESSAGEFLAG_AA;
7503
7504                 /*
7505                  * If the response is somehow unexpected for the client and this
7506                  * is a result of recursion, return an error to the caller
7507                  * to indicate it may need to be logged.
7508                  */
7509                 if (resuming &&
7510                     (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) ||
7511                      client->message->rcode != dns_rcode_noerror))
7512                         eresult = ISC_R_FAILURE;
7513
7514                 query_send(client);
7515                 ns_client_detach(&client);
7516         }
7517         CTRACE("query_find: done");
7518
7519         return (eresult);
7520 }
7521
7522 static inline void
7523 log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
7524         char namebuf[DNS_NAME_FORMATSIZE];
7525         char typename[DNS_RDATATYPE_FORMATSIZE];
7526         char classname[DNS_RDATACLASS_FORMATSIZE];
7527         char onbuf[ISC_NETADDR_FORMATSIZE];
7528         dns_rdataset_t *rdataset;
7529         int level = ISC_LOG_INFO;
7530
7531         if (! isc_log_wouldlog(ns_g_lctx, level))
7532                 return;
7533
7534         rdataset = ISC_LIST_HEAD(client->query.qname->list);
7535         INSIST(rdataset != NULL);
7536         dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
7537         dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname));
7538         dns_rdatatype_format(rdataset->type, typename, sizeof(typename));
7539         isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf));
7540
7541         ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
7542                       level, "query: %s %s %s %s%s%s%s%s%s (%s)", namebuf,
7543                       classname, typename, WANTRECURSION(client) ? "+" : "-",
7544                       (client->signer != NULL) ? "S": "",
7545                       (client->opt != NULL) ? "E" : "",
7546                       ((client->attributes & NS_CLIENTATTR_TCP) != 0) ?
7547                                  "T" : "",
7548                       ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
7549                       ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "",
7550                       onbuf);
7551 }
7552
7553 static inline void
7554 log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) {
7555         char namebuf[DNS_NAME_FORMATSIZE];
7556         char typename[DNS_RDATATYPE_FORMATSIZE];
7557         char classname[DNS_RDATACLASS_FORMATSIZE];
7558         const char *namep, *typep, *classp, *sep1, *sep2;
7559         dns_rdataset_t *rdataset;
7560
7561         if (!isc_log_wouldlog(ns_g_lctx, level))
7562                 return;
7563
7564         namep = typep = classp = sep1 = sep2 = "";
7565
7566         /*
7567          * Query errors can happen for various reasons.  In some cases we cannot
7568          * even assume the query contains a valid question section, so we should
7569          * expect exceptional cases.
7570          */
7571         if (client->query.origqname != NULL) {
7572                 dns_name_format(client->query.origqname, namebuf,
7573                                 sizeof(namebuf));
7574                 namep = namebuf;
7575                 sep1 = " for ";
7576
7577                 rdataset = ISC_LIST_HEAD(client->query.origqname->list);
7578                 if (rdataset != NULL) {
7579                         dns_rdataclass_format(rdataset->rdclass, classname,
7580                                               sizeof(classname));
7581                         classp = classname;
7582                         dns_rdatatype_format(rdataset->type, typename,
7583                                              sizeof(typename));
7584                         typep = typename;
7585                         sep2 = "/";
7586                 }
7587         }
7588
7589         ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, NS_LOGMODULE_QUERY,
7590                       level, "query failed (%s)%s%s%s%s%s%s at %s:%d",
7591                       isc_result_totext(result), sep1, namep, sep2,
7592                       classp, sep2, typep, __FILE__, line);
7593 }
7594
7595 void
7596 ns_query_start(ns_client_t *client) {
7597         isc_result_t result;
7598         dns_message_t *message = client->message;
7599         dns_rdataset_t *rdataset;
7600         ns_client_t *qclient;
7601         dns_rdatatype_t qtype;
7602         unsigned int saved_extflags = client->extflags;
7603         unsigned int saved_flags = client->message->flags;
7604
7605         CTRACE("ns_query_start");
7606
7607         /*
7608          * Test only.
7609          */
7610         if (ns_g_clienttest && (client->attributes & NS_CLIENTATTR_TCP) == 0)
7611                 RUNTIME_CHECK(ns_client_replace(client) == ISC_R_SUCCESS);
7612
7613         /*
7614          * Ensure that appropriate cleanups occur.
7615          */
7616         client->next = query_next_callback;
7617
7618         /*
7619          * Behave as if we don't support DNSSEC if not enabled.
7620          */
7621         if (!client->view->enablednssec) {
7622                 message->flags &= ~DNS_MESSAGEFLAG_CD;
7623                 client->extflags &= ~DNS_MESSAGEEXTFLAG_DO;
7624                 if (client->opt != NULL)
7625                         client->opt->ttl &= ~DNS_MESSAGEEXTFLAG_DO;
7626         }
7627
7628         if ((message->flags & DNS_MESSAGEFLAG_RD) != 0)
7629                 client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
7630
7631         if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0)
7632                 client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
7633
7634         if (client->view->minimalresponses)
7635                 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
7636                                              NS_QUERYATTR_NOADDITIONAL);
7637
7638         if ((client->view->cachedb == NULL)
7639             || (!client->view->additionalfromcache)) {
7640                 /*
7641                  * We don't have a cache.  Turn off cache support and
7642                  * recursion.
7643                  */
7644                 client->query.attributes &=
7645                         ~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK);
7646         } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
7647                    (message->flags & DNS_MESSAGEFLAG_RD) == 0) {
7648                 /*
7649                  * If the client isn't allowed to recurse (due to
7650                  * "recursion no", the allow-recursion ACL, or the
7651                  * lack of a resolver in this view), or if it
7652                  * doesn't want recursion, turn recursion off.
7653                  */
7654                 client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
7655         }
7656
7657         /*
7658          * Get the question name.
7659          */
7660         result = dns_message_firstname(message, DNS_SECTION_QUESTION);
7661         if (result != ISC_R_SUCCESS) {
7662                 query_error(client, result, __LINE__);
7663                 return;
7664         }
7665         dns_message_currentname(message, DNS_SECTION_QUESTION,
7666                                 &client->query.qname);
7667         client->query.origqname = client->query.qname;
7668         result = dns_message_nextname(message, DNS_SECTION_QUESTION);
7669         if (result != ISC_R_NOMORE) {
7670                 if (result == ISC_R_SUCCESS) {
7671                         /*
7672                          * There's more than one QNAME in the question
7673                          * section.
7674                          */
7675                         query_error(client, DNS_R_FORMERR, __LINE__);
7676                 } else
7677                         query_error(client, result, __LINE__);
7678                 return;
7679         }
7680
7681         if (ns_g_server->log_queries)
7682                 log_query(client, saved_flags, saved_extflags);
7683
7684         /*
7685          * Check for multiple question queries, since edns1 is dead.
7686          */
7687         if (message->counts[DNS_SECTION_QUESTION] > 1) {
7688                 query_error(client, DNS_R_FORMERR, __LINE__);
7689                 return;
7690         }
7691
7692         /*
7693          * Check for meta-queries like IXFR and AXFR.
7694          */
7695         rdataset = ISC_LIST_HEAD(client->query.qname->list);
7696         INSIST(rdataset != NULL);
7697         qtype = rdataset->type;
7698         dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype);
7699
7700         if (dns_rdatatype_ismeta(qtype)) {
7701                 switch (qtype) {
7702                 case dns_rdatatype_any:
7703                         break; /* Let query_find handle it. */
7704                 case dns_rdatatype_ixfr:
7705                 case dns_rdatatype_axfr:
7706                         ns_xfr_start(client, rdataset->type);
7707                         return;
7708                 case dns_rdatatype_maila:
7709                 case dns_rdatatype_mailb:
7710                         query_error(client, DNS_R_NOTIMP, __LINE__);
7711                         return;
7712                 case dns_rdatatype_tkey:
7713                         result = dns_tkey_processquery(client->message,
7714                                                 ns_g_server->tkeyctx,
7715                                                 client->view->dynamickeys);
7716                         if (result == ISC_R_SUCCESS)
7717                                 query_send(client);
7718                         else
7719                                 query_error(client, result, __LINE__);
7720                         return;
7721                 default: /* TSIG, etc. */
7722                         query_error(client, DNS_R_FORMERR, __LINE__);
7723                         return;
7724                 }
7725         }
7726
7727         /*
7728          * Turn on minimal response for DNSKEY and DS queries.
7729          */
7730         if (qtype == dns_rdatatype_dnskey || qtype == dns_rdatatype_ds)
7731                 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
7732                                              NS_QUERYATTR_NOADDITIONAL);
7733
7734         /*
7735          * Turn on minimal responses for EDNS/UDP bufsize 512 queries.
7736          */
7737         if (client->opt != NULL && client->udpsize <= 512U &&
7738             (client->attributes & NS_CLIENTATTR_TCP) == 0)
7739                 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
7740                                              NS_QUERYATTR_NOADDITIONAL);
7741
7742         /*
7743          * If the client has requested that DNSSEC checking be disabled,
7744          * allow lookups to return pending data and instruct the resolver
7745          * to return data before validation has completed.
7746          *
7747          * We don't need to set DNS_DBFIND_PENDINGOK when validation is
7748          * disabled as there will be no pending data.
7749          */
7750         if (message->flags & DNS_MESSAGEFLAG_CD ||
7751             qtype == dns_rdatatype_rrsig)
7752         {
7753                 client->query.dboptions |= DNS_DBFIND_PENDINGOK;
7754                 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
7755         } else if (!client->view->enablevalidation)
7756                 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
7757
7758         /*
7759          * Allow glue NS records to be added to the authority section
7760          * if the answer is secure.
7761          */
7762         if (message->flags & DNS_MESSAGEFLAG_CD)
7763                 client->query.attributes &= ~NS_QUERYATTR_SECURE;
7764
7765         /*
7766          * Set NS_CLIENTATTR_WANTDNSSEC if the client has set AD in the query.
7767          * This allows AD to be returned on queries without DO set.
7768          */
7769         if ((message->flags & DNS_MESSAGEFLAG_AD) != 0)
7770                 client->attributes |= NS_CLIENTATTR_WANTAD;
7771
7772         /*
7773          * This is an ordinary query.
7774          */
7775         result = dns_message_reply(message, ISC_TRUE);
7776         if (result != ISC_R_SUCCESS) {
7777                 query_next(client, result);
7778                 return;
7779         }
7780
7781         /*
7782          * Assume authoritative response until it is known to be
7783          * otherwise.
7784          *
7785          * If "-T noaa" has been set on the command line don't set
7786          * AA on authoritative answers.
7787          */
7788         if (!ns_g_noaa)
7789                 message->flags |= DNS_MESSAGEFLAG_AA;
7790
7791         /*
7792          * Set AD.  We must clear it if we add non-validated data to a
7793          * response.
7794          */
7795         if (WANTDNSSEC(client) || WANTAD(client))
7796                 message->flags |= DNS_MESSAGEFLAG_AD;
7797
7798         qclient = NULL;
7799         ns_client_attach(client, &qclient);
7800         (void)query_find(qclient, NULL, qtype);
7801 }