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