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