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