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