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