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