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