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