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