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