]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind9/bin/named/query.c
Merge sendmail 8.14.4 to HEAD
[FreeBSD/FreeBSD.git] / contrib / bind9 / bin / named / query.c
1 /*
2  * Copyright (C) 2004-2009  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.313.20.7.12.4 2009/12/31 22:53:03 each 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 #ifdef DLZ
35 #include <dns/dlz.h>
36 #endif
37 #include <dns/dnssec.h>
38 #include <dns/events.h>
39 #include <dns/message.h>
40 #include <dns/ncache.h>
41 #include <dns/nsec3.h>
42 #include <dns/order.h>
43 #include <dns/rdata.h>
44 #include <dns/rdataclass.h>
45 #include <dns/rdatalist.h>
46 #include <dns/rdataset.h>
47 #include <dns/rdatasetiter.h>
48 #include <dns/rdatastruct.h>
49 #include <dns/rdatatype.h>
50 #include <dns/resolver.h>
51 #include <dns/result.h>
52 #include <dns/stats.h>
53 #include <dns/tkey.h>
54 #include <dns/view.h>
55 #include <dns/zone.h>
56 #include <dns/zt.h>
57
58 #include <named/client.h>
59 #include <named/log.h>
60 #include <named/server.h>
61 #include <named/sortlist.h>
62 #include <named/xfrout.h>
63
64 /*% Partial answer? */
65 #define PARTIALANSWER(c)        (((c)->query.attributes & \
66                                   NS_QUERYATTR_PARTIALANSWER) != 0)
67 /*% Use Cache? */
68 #define USECACHE(c)             (((c)->query.attributes & \
69                                   NS_QUERYATTR_CACHEOK) != 0)
70 /*% Recursion OK? */
71 #define RECURSIONOK(c)          (((c)->query.attributes & \
72                                   NS_QUERYATTR_RECURSIONOK) != 0)
73 /*% Recursing? */
74 #define RECURSING(c)            (((c)->query.attributes & \
75                                   NS_QUERYATTR_RECURSING) != 0)
76 /*% Cache glue ok? */
77 #define CACHEGLUEOK(c)          (((c)->query.attributes & \
78                                   NS_QUERYATTR_CACHEGLUEOK) != 0)
79 /*% Want Recursion? */
80 #define WANTRECURSION(c)        (((c)->query.attributes & \
81                                   NS_QUERYATTR_WANTRECURSION) != 0)
82 /*% Want DNSSEC? */
83 #define WANTDNSSEC(c)           (((c)->attributes & \
84                                   NS_CLIENTATTR_WANTDNSSEC) != 0)
85 /*% No authority? */
86 #define NOAUTHORITY(c)          (((c)->query.attributes & \
87                                   NS_QUERYATTR_NOAUTHORITY) != 0)
88 /*% No additional? */
89 #define NOADDITIONAL(c)         (((c)->query.attributes & \
90                                   NS_QUERYATTR_NOADDITIONAL) != 0)
91 /*% Secure? */
92 #define SECURE(c)               (((c)->query.attributes & \
93                                   NS_QUERYATTR_SECURE) != 0)
94
95 /*% No QNAME Proof? */
96 #define NOQNAME(r)              (((r)->attributes & \
97                                   DNS_RDATASETATTR_NOQNAME) != 0)
98
99 #if 0
100 #define CTRACE(m)       isc_log_write(ns_g_lctx, \
101                                       NS_LOGCATEGORY_CLIENT, \
102                                       NS_LOGMODULE_QUERY, \
103                                       ISC_LOG_DEBUG(3), \
104                                       "client %p: %s", client, (m))
105 #define QTRACE(m)       isc_log_write(ns_g_lctx, \
106                                       NS_LOGCATEGORY_GENERAL, \
107                                       NS_LOGMODULE_QUERY, \
108                                       ISC_LOG_DEBUG(3), \
109                                       "query %p: %s", query, (m))
110 #else
111 #define CTRACE(m) ((void)m)
112 #define QTRACE(m) ((void)m)
113 #endif
114
115 #define DNS_GETDB_NOEXACT 0x01U
116 #define DNS_GETDB_NOLOG 0x02U
117 #define DNS_GETDB_PARTIAL 0x04U
118
119 #define PENDINGOK(x)    (((x) & DNS_DBFIND_PENDINGOK) != 0)
120
121 typedef struct client_additionalctx {
122         ns_client_t *client;
123         dns_rdataset_t *rdataset;
124 } client_additionalctx_t;
125
126 static isc_result_t
127 query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
128
129 static isc_boolean_t
130 validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
131          dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
132
133 static void
134 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
135                        dns_dbversion_t *version, ns_client_t *client,
136                        dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
137                        dns_name_t *fname, isc_boolean_t exact,
138                        dns_name_t *found);
139
140 static inline void
141 log_queryerror(ns_client_t *client, isc_result_t result, int line, int level);
142
143 /*%
144  * Increment query statistics counters.
145  */
146 static inline void
147 inc_stats(ns_client_t *client, isc_statscounter_t counter) {
148         dns_zone_t *zone = client->query.authzone;
149
150         isc_stats_increment(ns_g_server->nsstats, counter);
151
152         if (zone != NULL) {
153                 isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
154                 if (zonestats != NULL)
155                         isc_stats_increment(zonestats, counter);
156         }
157 }
158
159 static void
160 query_send(ns_client_t *client) {
161         isc_statscounter_t counter;
162         if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0)
163                 inc_stats(client, dns_nsstatscounter_nonauthans);
164         else
165                 inc_stats(client, dns_nsstatscounter_authans);
166         if (client->message->rcode == dns_rcode_noerror) {
167                 if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER])) {
168                         if (client->query.isreferral) {
169                                 counter = dns_nsstatscounter_referral;
170                         } else {
171                                 counter = dns_nsstatscounter_nxrrset;
172                         }
173                 } else {
174                         counter = dns_nsstatscounter_success;
175                 }
176         } else if (client->message->rcode == dns_rcode_nxdomain) {
177                 counter = dns_nsstatscounter_nxdomain;
178         } else {
179                 /* We end up here in case of YXDOMAIN, and maybe others */
180                 counter = dns_nsstatscounter_failure;
181         }
182         inc_stats(client, counter);
183         ns_client_send(client);
184 }
185
186 static void
187 query_error(ns_client_t *client, isc_result_t result, int line) {
188         int loglevel = ISC_LOG_DEBUG(3);
189
190         switch (result) {
191         case DNS_R_SERVFAIL:
192                 loglevel = ISC_LOG_DEBUG(1);
193                 inc_stats(client, dns_nsstatscounter_servfail);
194                 break;
195         case DNS_R_FORMERR:
196                 inc_stats(client, dns_nsstatscounter_formerr);
197                 break;
198         default:
199                 inc_stats(client, dns_nsstatscounter_failure);
200                 break;
201         }
202
203         log_queryerror(client, result, line, loglevel);
204
205         ns_client_error(client, result);
206 }
207
208 static void
209 query_next(ns_client_t *client, isc_result_t result) {
210         if (result == DNS_R_DUPLICATE)
211                 inc_stats(client, dns_nsstatscounter_duplicate);
212         else if (result == DNS_R_DROP)
213                 inc_stats(client, dns_nsstatscounter_dropped);
214         else
215                 inc_stats(client, dns_nsstatscounter_failure);
216         ns_client_next(client, result);
217 }
218
219 static inline void
220 query_freefreeversions(ns_client_t *client, isc_boolean_t everything) {
221         ns_dbversion_t *dbversion, *dbversion_next;
222         unsigned int i;
223
224         for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
225              dbversion != NULL;
226              dbversion = dbversion_next, i++)
227         {
228                 dbversion_next = ISC_LIST_NEXT(dbversion, link);
229                 /*
230                  * If we're not freeing everything, we keep the first three
231                  * dbversions structures around.
232                  */
233                 if (i > 3 || everything) {
234                         ISC_LIST_UNLINK(client->query.freeversions, dbversion,
235                                         link);
236                         isc_mem_put(client->mctx, dbversion,
237                                     sizeof(*dbversion));
238                 }
239         }
240 }
241
242 void
243 ns_query_cancel(ns_client_t *client) {
244         LOCK(&client->query.fetchlock);
245         if (client->query.fetch != NULL) {
246                 dns_resolver_cancelfetch(client->query.fetch);
247
248                 client->query.fetch = NULL;
249         }
250         UNLOCK(&client->query.fetchlock);
251 }
252
253 static inline void
254 query_reset(ns_client_t *client, isc_boolean_t everything) {
255         isc_buffer_t *dbuf, *dbuf_next;
256         ns_dbversion_t *dbversion, *dbversion_next;
257
258         /*%
259          * Reset the query state of a client to its default state.
260          */
261
262         /*
263          * Cancel the fetch if it's running.
264          */
265         ns_query_cancel(client);
266
267         /*
268          * Cleanup any active versions.
269          */
270         for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
271              dbversion != NULL;
272              dbversion = dbversion_next) {
273                 dbversion_next = ISC_LIST_NEXT(dbversion, link);
274                 dns_db_closeversion(dbversion->db, &dbversion->version,
275                                     ISC_FALSE);
276                 dns_db_detach(&dbversion->db);
277                 ISC_LIST_INITANDAPPEND(client->query.freeversions,
278                                       dbversion, link);
279         }
280         ISC_LIST_INIT(client->query.activeversions);
281
282         if (client->query.authdb != NULL)
283                 dns_db_detach(&client->query.authdb);
284         if (client->query.authzone != NULL)
285                 dns_zone_detach(&client->query.authzone);
286
287         query_freefreeversions(client, everything);
288
289         for (dbuf = ISC_LIST_HEAD(client->query.namebufs);
290              dbuf != NULL;
291              dbuf = dbuf_next) {
292                 dbuf_next = ISC_LIST_NEXT(dbuf, link);
293                 if (dbuf_next != NULL || everything) {
294                         ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
295                         isc_buffer_free(&dbuf);
296                 }
297         }
298
299         if (client->query.restarts > 0) {
300                 /*
301                  * client->query.qname was dynamically allocated.
302                  */
303                 dns_message_puttempname(client->message,
304                                         &client->query.qname);
305         }
306         client->query.qname = NULL;
307         client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
308                                     NS_QUERYATTR_CACHEOK |
309                                     NS_QUERYATTR_SECURE);
310         client->query.restarts = 0;
311         client->query.timerset = ISC_FALSE;
312         client->query.origqname = NULL;
313         client->query.qname = NULL;
314         client->query.dboptions = 0;
315         client->query.fetchoptions = 0;
316         client->query.gluedb = NULL;
317         client->query.authdbset = ISC_FALSE;
318         client->query.isreferral = ISC_FALSE;
319 }
320
321 static void
322 query_next_callback(ns_client_t *client) {
323         query_reset(client, ISC_FALSE);
324 }
325
326 void
327 ns_query_free(ns_client_t *client) {
328         query_reset(client, ISC_TRUE);
329 }
330
331 static inline isc_result_t
332 query_newnamebuf(ns_client_t *client) {
333         isc_buffer_t *dbuf;
334         isc_result_t result;
335
336         CTRACE("query_newnamebuf");
337         /*%
338          * Allocate a name buffer.
339          */
340
341         dbuf = NULL;
342         result = isc_buffer_allocate(client->mctx, &dbuf, 1024);
343         if (result != ISC_R_SUCCESS) {
344                 CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
345                 return (result);
346         }
347         ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
348
349         CTRACE("query_newnamebuf: done");
350         return (ISC_R_SUCCESS);
351 }
352
353 static inline isc_buffer_t *
354 query_getnamebuf(ns_client_t *client) {
355         isc_buffer_t *dbuf;
356         isc_result_t result;
357         isc_region_t r;
358
359         CTRACE("query_getnamebuf");
360         /*%
361          * Return a name buffer with space for a maximal name, allocating
362          * a new one if necessary.
363          */
364
365         if (ISC_LIST_EMPTY(client->query.namebufs)) {
366                 result = query_newnamebuf(client);
367                 if (result != ISC_R_SUCCESS) {
368                     CTRACE("query_getnamebuf: query_newnamebuf failed: done");
369                         return (NULL);
370                 }
371         }
372
373         dbuf = ISC_LIST_TAIL(client->query.namebufs);
374         INSIST(dbuf != NULL);
375         isc_buffer_availableregion(dbuf, &r);
376         if (r.length < 255) {
377                 result = query_newnamebuf(client);
378                 if (result != ISC_R_SUCCESS) {
379                     CTRACE("query_getnamebuf: query_newnamebuf failed: done");
380                         return (NULL);
381
382                 }
383                 dbuf = ISC_LIST_TAIL(client->query.namebufs);
384                 isc_buffer_availableregion(dbuf, &r);
385                 INSIST(r.length >= 255);
386         }
387         CTRACE("query_getnamebuf: done");
388         return (dbuf);
389 }
390
391 static inline void
392 query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
393         isc_region_t r;
394
395         CTRACE("query_keepname");
396         /*%
397          * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
398          * adjusted to take account of that.  We do the adjustment.
399          */
400
401         REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
402
403         dns_name_toregion(name, &r);
404         isc_buffer_add(dbuf, r.length);
405         dns_name_setbuffer(name, NULL);
406         client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
407 }
408
409 static inline void
410 query_releasename(ns_client_t *client, dns_name_t **namep) {
411         dns_name_t *name = *namep;
412
413         /*%
414          * 'name' is no longer needed.  Return it to our pool of temporary
415          * names.  If it is using a name buffer, relinquish its exclusive
416          * rights on the buffer.
417          */
418
419         CTRACE("query_releasename");
420         if (dns_name_hasbuffer(name)) {
421                 INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
422                        != 0);
423                 client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
424         }
425         dns_message_puttempname(client->message, namep);
426         CTRACE("query_releasename: done");
427 }
428
429 static inline dns_name_t *
430 query_newname(ns_client_t *client, isc_buffer_t *dbuf,
431               isc_buffer_t *nbuf)
432 {
433         dns_name_t *name;
434         isc_region_t r;
435         isc_result_t result;
436
437         REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
438
439         CTRACE("query_newname");
440         name = NULL;
441         result = dns_message_gettempname(client->message, &name);
442         if (result != ISC_R_SUCCESS) {
443                 CTRACE("query_newname: dns_message_gettempname failed: done");
444                 return (NULL);
445         }
446         isc_buffer_availableregion(dbuf, &r);
447         isc_buffer_init(nbuf, r.base, r.length);
448         dns_name_init(name, NULL);
449         dns_name_setbuffer(name, nbuf);
450         client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
451
452         CTRACE("query_newname: done");
453         return (name);
454 }
455
456 static inline dns_rdataset_t *
457 query_newrdataset(ns_client_t *client) {
458         dns_rdataset_t *rdataset;
459         isc_result_t result;
460
461         CTRACE("query_newrdataset");
462         rdataset = NULL;
463         result = dns_message_gettemprdataset(client->message, &rdataset);
464         if (result != ISC_R_SUCCESS) {
465           CTRACE("query_newrdataset: "
466                  "dns_message_gettemprdataset failed: done");
467                 return (NULL);
468         }
469         dns_rdataset_init(rdataset);
470
471         CTRACE("query_newrdataset: done");
472         return (rdataset);
473 }
474
475 static inline void
476 query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
477         dns_rdataset_t *rdataset = *rdatasetp;
478
479         CTRACE("query_putrdataset");
480         if (rdataset != NULL) {
481                 if (dns_rdataset_isassociated(rdataset))
482                         dns_rdataset_disassociate(rdataset);
483                 dns_message_puttemprdataset(client->message, rdatasetp);
484         }
485         CTRACE("query_putrdataset: done");
486 }
487
488
489 static inline isc_result_t
490 query_newdbversion(ns_client_t *client, unsigned int n) {
491         unsigned int i;
492         ns_dbversion_t *dbversion;
493
494         for (i = 0; i < n; i++) {
495                 dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
496                 if (dbversion != NULL) {
497                         dbversion->db = NULL;
498                         dbversion->version = NULL;
499                         ISC_LIST_INITANDAPPEND(client->query.freeversions,
500                                               dbversion, link);
501                 } else {
502                         /*
503                          * We only return ISC_R_NOMEMORY if we couldn't
504                          * allocate anything.
505                          */
506                         if (i == 0)
507                                 return (ISC_R_NOMEMORY);
508                         else
509                                 return (ISC_R_SUCCESS);
510                 }
511         }
512
513         return (ISC_R_SUCCESS);
514 }
515
516 static inline ns_dbversion_t *
517 query_getdbversion(ns_client_t *client) {
518         isc_result_t result;
519         ns_dbversion_t *dbversion;
520
521         if (ISC_LIST_EMPTY(client->query.freeversions)) {
522                 result = query_newdbversion(client, 1);
523                 if (result != ISC_R_SUCCESS)
524                         return (NULL);
525         }
526         dbversion = ISC_LIST_HEAD(client->query.freeversions);
527         INSIST(dbversion != NULL);
528         ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
529
530         return (dbversion);
531 }
532
533 isc_result_t
534 ns_query_init(ns_client_t *client) {
535         isc_result_t result;
536
537         ISC_LIST_INIT(client->query.namebufs);
538         ISC_LIST_INIT(client->query.activeversions);
539         ISC_LIST_INIT(client->query.freeversions);
540         client->query.restarts = 0;
541         client->query.timerset = ISC_FALSE;
542         client->query.qname = NULL;
543         result = isc_mutex_init(&client->query.fetchlock);
544         if (result != ISC_R_SUCCESS)
545                 return (result);
546         client->query.fetch = NULL;
547         client->query.authdb = NULL;
548         client->query.authzone = NULL;
549         client->query.authdbset = ISC_FALSE;
550         client->query.isreferral = ISC_FALSE;
551         query_reset(client, ISC_FALSE);
552         result = query_newdbversion(client, 3);
553         if (result != ISC_R_SUCCESS) {
554                 DESTROYLOCK(&client->query.fetchlock);
555                 return (result);
556         }
557         result = query_newnamebuf(client);
558         if (result != ISC_R_SUCCESS)
559                 query_freefreeversions(client, ISC_TRUE);
560
561         return (result);
562 }
563
564 static inline ns_dbversion_t *
565 query_findversion(ns_client_t *client, dns_db_t *db,
566                   isc_boolean_t *newzonep)
567 {
568         ns_dbversion_t *dbversion;
569
570         /*%
571          * We may already have done a query related to this
572          * database.  If so, we must be sure to make subsequent
573          * queries from the same version.
574          */
575         for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
576              dbversion != NULL;
577              dbversion = ISC_LIST_NEXT(dbversion, link)) {
578                 if (dbversion->db == db)
579                         break;
580         }
581
582         if (dbversion == NULL) {
583                 /*
584                  * This is a new zone for this query.  Add it to
585                  * the active list.
586                  */
587                 dbversion = query_getdbversion(client);
588                 if (dbversion == NULL)
589                         return (NULL);
590                 dns_db_attach(db, &dbversion->db);
591                 dns_db_currentversion(db, &dbversion->version);
592                 dbversion->queryok = ISC_FALSE;
593                 ISC_LIST_APPEND(client->query.activeversions,
594                                 dbversion, link);
595                 *newzonep = ISC_TRUE;
596         } else
597                 *newzonep = ISC_FALSE;
598
599         return (dbversion);
600 }
601
602 static inline isc_result_t
603 query_validatezonedb(ns_client_t *client, dns_name_t *name,
604                      dns_rdatatype_t qtype, unsigned int options,
605                      dns_zone_t *zone, dns_db_t *db,
606                      dns_dbversion_t **versionp)
607 {
608         isc_result_t result;
609         isc_boolean_t check_acl, new_zone;
610         dns_acl_t *queryacl;
611         ns_dbversion_t *dbversion;
612
613         REQUIRE(zone != NULL);
614         REQUIRE(db != NULL);
615
616         /*
617          * This limits our searching to the zone where the first name
618          * (the query target) was looked for.  This prevents following
619          * CNAMES or DNAMES into other zones and prevents returning
620          * additional data from other zones.
621          */
622         if (!client->view->additionalfromauth &&
623             client->query.authdbset &&
624             db != client->query.authdb)
625                 goto refuse;
626
627         /*
628          * If the zone has an ACL, we'll check it, otherwise
629          * we use the view's "allow-query" ACL.  Each ACL is only checked
630          * once per query.
631          *
632          * Also, get the database version to use.
633          */
634
635         check_acl = ISC_TRUE;   /* Keep compiler happy. */
636         queryacl = NULL;
637
638         /*
639          * Get the current version of this database.
640          */
641         dbversion = query_findversion(client, db, &new_zone);
642         if (dbversion == NULL) {
643                 result = DNS_R_SERVFAIL;
644                 goto fail;
645         }
646         if (new_zone) {
647                 check_acl = ISC_TRUE;
648         } else if (!dbversion->queryok) {
649                 goto refuse;
650         } else {
651                 check_acl = ISC_FALSE;
652         }
653
654         queryacl = dns_zone_getqueryacl(zone);
655         if (queryacl == NULL) {
656                 queryacl = client->view->queryacl;
657                 if ((client->query.attributes &
658                      NS_QUERYATTR_QUERYOKVALID) != 0) {
659                         /*
660                          * We've evaluated the view's queryacl already.  If
661                          * NS_QUERYATTR_QUERYOK is set, then the client is
662                          * allowed to make queries, otherwise the query should
663                          * be refused.
664                          */
665                         check_acl = ISC_FALSE;
666                         if ((client->query.attributes &
667                              NS_QUERYATTR_QUERYOK) == 0)
668                                 goto refuse;
669                 } else {
670                         /*
671                          * We haven't evaluated the view's queryacl yet.
672                          */
673                         check_acl = ISC_TRUE;
674                 }
675         }
676
677         if (check_acl) {
678                 isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);
679
680                 result = ns_client_checkaclsilent(client, NULL, queryacl,
681                                                   ISC_TRUE);
682                 if (log) {
683                         char msg[NS_CLIENT_ACLMSGSIZE("query")];
684                         if (result == ISC_R_SUCCESS) {
685                                 if (isc_log_wouldlog(ns_g_lctx,
686                                                      ISC_LOG_DEBUG(3)))
687                                 {
688                                         ns_client_aclmsg("query", name, qtype,
689                                                          client->view->rdclass,
690                                                          msg, sizeof(msg));
691                                         ns_client_log(client,
692                                                       DNS_LOGCATEGORY_SECURITY,
693                                                       NS_LOGMODULE_QUERY,
694                                                       ISC_LOG_DEBUG(3),
695                                                       "%s approved", msg);
696                                 }
697                         } else {
698                                 ns_client_aclmsg("query", name, qtype,
699                                                  client->view->rdclass,
700                                                  msg, sizeof(msg));
701                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
702                                               NS_LOGMODULE_QUERY, ISC_LOG_INFO,
703                                               "%s denied", msg);
704                         }
705                 }
706
707                 if (queryacl == client->view->queryacl) {
708                         if (result == ISC_R_SUCCESS) {
709                                 /*
710                                  * We were allowed by the default
711                                  * "allow-query" ACL.  Remember this so we
712                                  * don't have to check again.
713                                  */
714                                 client->query.attributes |=
715                                         NS_QUERYATTR_QUERYOK;
716                         }
717                         /*
718                          * We've now evaluated the view's query ACL, and
719                          * the NS_QUERYATTR_QUERYOK attribute is now valid.
720                          */
721                         client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
722                 }
723
724                 if (result != ISC_R_SUCCESS)
725                         goto refuse;
726         }
727
728         /* Approved. */
729
730         /*
731          * Remember the result of the ACL check so we
732          * don't have to check again.
733          */
734         dbversion->queryok = ISC_TRUE;
735
736         /* Transfer ownership, if necessary. */
737         if (versionp != NULL)
738                 *versionp = dbversion->version;
739
740         return (ISC_R_SUCCESS);
741
742  refuse:
743         return (DNS_R_REFUSED);
744
745  fail:
746         return (result);
747 }
748
749 static inline isc_result_t
750 query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
751                 unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
752                 dns_dbversion_t **versionp)
753 {
754         isc_result_t result;
755         unsigned int ztoptions;
756         dns_zone_t *zone = NULL;
757         dns_db_t *db = NULL;
758         isc_boolean_t partial = ISC_FALSE;
759
760         REQUIRE(zonep != NULL && *zonep == NULL);
761         REQUIRE(dbp != NULL && *dbp == NULL);
762
763         /*%
764          * Find a zone database to answer the query.
765          */
766         ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?
767                 DNS_ZTFIND_NOEXACT : 0;
768
769         result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
770                              &zone);
771         if (result == DNS_R_PARTIALMATCH)
772                 partial = ISC_TRUE;
773         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
774                 result = dns_zone_getdb(zone, &db);
775
776         if (result != ISC_R_SUCCESS)
777                 goto fail;
778
779         result = query_validatezonedb(client, name, qtype, options, zone, db,
780                                       versionp);
781
782         if (result != ISC_R_SUCCESS)
783                 goto fail;
784
785         /* Transfer ownership. */
786         *zonep = zone;
787         *dbp = db;
788
789         if (partial && (options & DNS_GETDB_PARTIAL) != 0)
790                 return (DNS_R_PARTIALMATCH);
791         return (ISC_R_SUCCESS);
792
793  fail:
794         if (zone != NULL)
795                 dns_zone_detach(&zone);
796         if (db != NULL)
797                 dns_db_detach(&db);
798
799         return (result);
800 }
801
802 static inline isc_result_t
803 query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
804                  dns_db_t **dbp, unsigned int options)
805 {
806         isc_result_t result;
807         isc_boolean_t check_acl;
808         dns_db_t *db = NULL;
809
810         REQUIRE(dbp != NULL && *dbp == NULL);
811
812         /*%
813          * Find a cache database to answer the query.
814          * This may fail with DNS_R_REFUSED if the client
815          * is not allowed to use the cache.
816          */
817
818         if (!USECACHE(client))
819                 return (DNS_R_REFUSED);
820         dns_db_attach(client->view->cachedb, &db);
821
822         if ((client->query.attributes &
823              NS_QUERYATTR_QUERYOKVALID) != 0) {
824                 /*
825                  * We've evaluated the view's queryacl already.  If
826                  * NS_QUERYATTR_QUERYOK is set, then the client is
827                  * allowed to make queries, otherwise the query should
828                  * be refused.
829                  */
830                 check_acl = ISC_FALSE;
831                 if ((client->query.attributes &
832                      NS_QUERYATTR_QUERYOK) == 0)
833                         goto refuse;
834         } else {
835                 /*
836                  * We haven't evaluated the view's queryacl yet.
837                  */
838                 check_acl = ISC_TRUE;
839         }
840
841         if (check_acl) {
842                 isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);
843                 char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
844
845                 result = ns_client_checkaclsilent(client, NULL,
846                                                   client->view->queryacl,
847                                                   ISC_TRUE);
848                 if (result == ISC_R_SUCCESS) {
849                         /*
850                          * We were allowed by the default
851                          * "allow-query" ACL.  Remember this so we
852                          * don't have to check again.
853                          */
854                         client->query.attributes |=
855                                 NS_QUERYATTR_QUERYOK;
856                         if (log && isc_log_wouldlog(ns_g_lctx,
857                                                      ISC_LOG_DEBUG(3)))
858                         {
859                                 ns_client_aclmsg("query (cache)", name, qtype,
860                                                  client->view->rdclass,
861                                                  msg, sizeof(msg));
862                                 ns_client_log(client,
863                                               DNS_LOGCATEGORY_SECURITY,
864                                               NS_LOGMODULE_QUERY,
865                                               ISC_LOG_DEBUG(3),
866                                               "%s approved", msg);
867                         }
868                 } else if (log) {
869                         ns_client_aclmsg("query (cache)", name, qtype,
870                                          client->view->rdclass, msg,
871                                          sizeof(msg));
872                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
873                                       NS_LOGMODULE_QUERY, ISC_LOG_INFO,
874                                       "%s denied", msg);
875                 }
876                 /*
877                  * We've now evaluated the view's query ACL, and
878                  * the NS_QUERYATTR_QUERYOK attribute is now valid.
879                  */
880                 client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
881
882                 if (result != ISC_R_SUCCESS)
883                         goto refuse;
884         }
885
886         /* Approved. */
887
888         /* Transfer ownership. */
889         *dbp = db;
890
891         return (ISC_R_SUCCESS);
892
893  refuse:
894         result = DNS_R_REFUSED;
895
896         if (db != NULL)
897                 dns_db_detach(&db);
898
899         return (result);
900 }
901
902
903 static inline isc_result_t
904 query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
905             unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
906             dns_dbversion_t **versionp, isc_boolean_t *is_zonep)
907 {
908         isc_result_t result;
909
910 #ifdef DLZ
911         isc_result_t tresult;
912         unsigned int namelabels;
913         unsigned int zonelabels;
914         dns_zone_t *zone = NULL;
915         dns_db_t *tdbp;
916
917         REQUIRE(zonep != NULL && *zonep == NULL);
918
919         tdbp = NULL;
920
921         /* Calculate how many labels are in name. */
922         namelabels = dns_name_countlabels(name);
923         zonelabels = 0;
924
925         /* Try to find name in bind's standard database. */
926         result = query_getzonedb(client, name, qtype, options, &zone,
927                                  dbp, versionp);
928
929         /* See how many labels are in the zone's name.    */
930         if (result == ISC_R_SUCCESS && zone != NULL)
931                 zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));
932         /*
933          * If # zone labels < # name labels, try to find an even better match
934          * Only try if a DLZ driver is loaded for this view
935          */
936         if (zonelabels < namelabels && client->view->dlzdatabase != NULL) {
937                 tresult = dns_dlzfindzone(client->view, name,
938                                           zonelabels, &tdbp);
939                  /* If we successful, we found a better match. */
940                 if (tresult == ISC_R_SUCCESS) {
941                         /*
942                          * If the previous search returned a zone, detach it.
943                          */
944                         if (zone != NULL)
945                                 dns_zone_detach(&zone);
946
947                         /*
948                          * If the previous search returned a database,
949                          * detach it.
950                          */
951                         if (*dbp != NULL)
952                                 dns_db_detach(dbp);
953
954                         /*
955                          * If the previous search returned a version, clear it.
956                          */
957                         *versionp = NULL;
958
959                         /*
960                          * Get our database version.
961                          */
962                         dns_db_currentversion(tdbp, versionp);
963
964                         /*
965                          * Be sure to return our database.
966                          */
967                         *dbp = tdbp;
968
969                         /*
970                          * We return a null zone, No stats for DLZ zones.
971                          */
972                         zone = NULL;
973                         result = tresult;
974                 }
975         }
976 #else
977         result = query_getzonedb(client, name, qtype, options,
978                                  zonep, dbp, versionp);
979 #endif
980
981         /* If successful, Transfer ownership of zone. */
982         if (result == ISC_R_SUCCESS) {
983 #ifdef DLZ
984                 *zonep = zone;
985 #endif
986                 /*
987                  * If neither attempt above succeeded, return the cache instead
988                  */
989                 *is_zonep = ISC_TRUE;
990         } else if (result == ISC_R_NOTFOUND) {
991                 result = query_getcachedb(client, name, qtype, dbp, options);
992                 *is_zonep = ISC_FALSE;
993         }
994         return (result);
995 }
996
997 static inline isc_boolean_t
998 query_isduplicate(ns_client_t *client, dns_name_t *name,
999                   dns_rdatatype_t type, dns_name_t **mnamep)
1000 {
1001         dns_section_t section;
1002         dns_name_t *mname = NULL;
1003         isc_result_t result;
1004
1005         CTRACE("query_isduplicate");
1006
1007         for (section = DNS_SECTION_ANSWER;
1008              section <= DNS_SECTION_ADDITIONAL;
1009              section++) {
1010                 result = dns_message_findname(client->message, section,
1011                                               name, type, 0, &mname, NULL);
1012                 if (result == ISC_R_SUCCESS) {
1013                         /*
1014                          * We've already got this RRset in the response.
1015                          */
1016                         CTRACE("query_isduplicate: true: done");
1017                         return (ISC_TRUE);
1018                 } else if (result == DNS_R_NXRRSET) {
1019                         /*
1020                          * The name exists, but the rdataset does not.
1021                          */
1022                         if (section == DNS_SECTION_ADDITIONAL)
1023                                 break;
1024                 } else
1025                         RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
1026                 mname = NULL;
1027         }
1028
1029         /*
1030          * If the dns_name_t we're looking up is already in the message,
1031          * we don't want to trigger the caller's name replacement logic.
1032          */
1033         if (name == mname)
1034                 mname = NULL;
1035
1036         *mnamep = mname;
1037
1038         CTRACE("query_isduplicate: false: done");
1039         return (ISC_FALSE);
1040 }
1041
1042 static isc_result_t
1043 query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
1044         ns_client_t *client = arg;
1045         isc_result_t result, eresult;
1046         dns_dbnode_t *node;
1047         dns_db_t *db;
1048         dns_name_t *fname, *mname;
1049         dns_rdataset_t *rdataset, *sigrdataset, *trdataset;
1050         isc_buffer_t *dbuf;
1051         isc_buffer_t b;
1052         dns_dbversion_t *version;
1053         isc_boolean_t added_something, need_addname;
1054         dns_zone_t *zone;
1055         dns_rdatatype_t type;
1056
1057         REQUIRE(NS_CLIENT_VALID(client));
1058         REQUIRE(qtype != dns_rdatatype_any);
1059
1060         if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))
1061                 return (ISC_R_SUCCESS);
1062
1063         CTRACE("query_addadditional");
1064
1065         /*
1066          * Initialization.
1067          */
1068         eresult = ISC_R_SUCCESS;
1069         fname = NULL;
1070         rdataset = NULL;
1071         sigrdataset = NULL;
1072         trdataset = NULL;
1073         db = NULL;
1074         version = NULL;
1075         node = NULL;
1076         added_something = ISC_FALSE;
1077         need_addname = ISC_FALSE;
1078         zone = NULL;
1079
1080         /*
1081          * We treat type A additional section processing as if it
1082          * were "any address type" additional section processing.
1083          * To avoid multiple lookups, we do an 'any' database
1084          * lookup and iterate over the node.
1085          */
1086         if (qtype == dns_rdatatype_a)
1087                 type = dns_rdatatype_any;
1088         else
1089                 type = qtype;
1090
1091         /*
1092          * Get some resources.
1093          */
1094         dbuf = query_getnamebuf(client);
1095         if (dbuf == NULL)
1096                 goto cleanup;
1097         fname = query_newname(client, dbuf, &b);
1098         rdataset = query_newrdataset(client);
1099         if (fname == NULL || rdataset == NULL)
1100                 goto cleanup;
1101         if (WANTDNSSEC(client)) {
1102                 sigrdataset = query_newrdataset(client);
1103                 if (sigrdataset == NULL)
1104                         goto cleanup;
1105         }
1106
1107         /*
1108          * Look for a zone database that might contain authoritative
1109          * additional data.
1110          */
1111         result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
1112                                  &zone, &db, &version);
1113         if (result != ISC_R_SUCCESS)
1114                 goto try_cache;
1115
1116         CTRACE("query_addadditional: db_find");
1117
1118         /*
1119          * Since we are looking for authoritative data, we do not set
1120          * the GLUEOK flag.  Glue will be looked for later, but not
1121          * necessarily in the same database.
1122          */
1123         node = NULL;
1124         result = dns_db_find(db, name, version, type, client->query.dboptions,
1125                              client->now, &node, fname, rdataset,
1126                              sigrdataset);
1127         if (result == ISC_R_SUCCESS) {
1128                 if (sigrdataset != NULL && !dns_db_issecure(db) &&
1129                     dns_rdataset_isassociated(sigrdataset))
1130                         dns_rdataset_disassociate(sigrdataset);
1131                 goto found;
1132         }
1133
1134         if (dns_rdataset_isassociated(rdataset))
1135                 dns_rdataset_disassociate(rdataset);
1136         if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
1137                 dns_rdataset_disassociate(sigrdataset);
1138         if (node != NULL)
1139                 dns_db_detachnode(db, &node);
1140         version = NULL;
1141         dns_db_detach(&db);
1142
1143         /*
1144          * No authoritative data was found.  The cache is our next best bet.
1145          */
1146
1147  try_cache:
1148         result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
1149         if (result != ISC_R_SUCCESS)
1150                 /*
1151                  * Most likely the client isn't allowed to query the cache.
1152                  */
1153                 goto try_glue;
1154         /*
1155          * Attempt to validate glue.
1156          */
1157         if (sigrdataset == NULL) {
1158                 sigrdataset = query_newrdataset(client);
1159                 if (sigrdataset == NULL)
1160                         goto cleanup;
1161         }
1162         result = dns_db_find(db, name, version, type,
1163                              client->query.dboptions |
1164                              DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
1165                              client->now, &node, fname, rdataset,
1166                              sigrdataset);
1167         if (result == DNS_R_GLUE &&
1168             validate(client, db, fname, rdataset, sigrdataset))
1169                 result = ISC_R_SUCCESS;
1170         if (!WANTDNSSEC(client))
1171                 query_putrdataset(client, &sigrdataset);
1172         if (result == ISC_R_SUCCESS)
1173                 goto found;
1174
1175         if (dns_rdataset_isassociated(rdataset))
1176                 dns_rdataset_disassociate(rdataset);
1177         if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
1178                 dns_rdataset_disassociate(sigrdataset);
1179         if (node != NULL)
1180                 dns_db_detachnode(db, &node);
1181         dns_db_detach(&db);
1182
1183  try_glue:
1184         /*
1185          * No cached data was found.  Glue is our last chance.
1186          * RFC1035 sayeth:
1187          *
1188          *      NS records cause both the usual additional section
1189          *      processing to locate a type A record, and, when used
1190          *      in a referral, a special search of the zone in which
1191          *      they reside for glue information.
1192          *
1193          * This is the "special search".  Note that we must search
1194          * the zone where the NS record resides, not the zone it
1195          * points to, and that we only do the search in the delegation
1196          * case (identified by client->query.gluedb being set).
1197          */
1198
1199         if (client->query.gluedb == NULL)
1200                 goto cleanup;
1201
1202         /*
1203          * Don't poison caches using the bailiwick protection model.
1204          */
1205         if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
1206                 goto cleanup;
1207
1208         dns_db_attach(client->query.gluedb, &db);
1209         result = dns_db_find(db, name, version, type,
1210                              client->query.dboptions | DNS_DBFIND_GLUEOK,
1211                              client->now, &node, fname, rdataset,
1212                              sigrdataset);
1213         if (!(result == ISC_R_SUCCESS ||
1214               result == DNS_R_ZONECUT ||
1215               result == DNS_R_GLUE))
1216                 goto cleanup;
1217
1218  found:
1219         /*
1220          * We have found a potential additional data rdataset, or
1221          * at least a node to iterate over.
1222          */
1223         query_keepname(client, fname, dbuf);
1224
1225         /*
1226          * If we have an rdataset, add it to the additional data
1227          * section.
1228          */
1229         mname = NULL;
1230         if (dns_rdataset_isassociated(rdataset) &&
1231             !query_isduplicate(client, fname, type, &mname)) {
1232                 if (mname != NULL) {
1233                         query_releasename(client, &fname);
1234                         fname = mname;
1235                 } else
1236                         need_addname = ISC_TRUE;
1237                 ISC_LIST_APPEND(fname->list, rdataset, link);
1238                 trdataset = rdataset;
1239                 rdataset = NULL;
1240                 added_something = ISC_TRUE;
1241                 /*
1242                  * Note: we only add SIGs if we've added the type they cover,
1243                  * so we do not need to check if the SIG rdataset is already
1244                  * in the response.
1245                  */
1246                 if (sigrdataset != NULL &&
1247                     dns_rdataset_isassociated(sigrdataset))
1248                 {
1249                         ISC_LIST_APPEND(fname->list, sigrdataset, link);
1250                         sigrdataset = NULL;
1251                 }
1252         }
1253
1254         if (qtype == dns_rdatatype_a) {
1255                 /*
1256                  * We now go looking for A and AAAA records, along with
1257                  * their signatures.
1258                  *
1259                  * XXXRTH  This code could be more efficient.
1260                  */
1261                 if (rdataset != NULL) {
1262                         if (dns_rdataset_isassociated(rdataset))
1263                                 dns_rdataset_disassociate(rdataset);
1264                 } else {
1265                         rdataset = query_newrdataset(client);
1266                         if (rdataset == NULL)
1267                                 goto addname;
1268                 }
1269                 if (sigrdataset != NULL) {
1270                         if (dns_rdataset_isassociated(sigrdataset))
1271                                 dns_rdataset_disassociate(sigrdataset);
1272                 } else if (WANTDNSSEC(client)) {
1273                         sigrdataset = query_newrdataset(client);
1274                         if (sigrdataset == NULL)
1275                                 goto addname;
1276                 }
1277                 result = dns_db_findrdataset(db, node, version,
1278                                              dns_rdatatype_a, 0,
1279                                              client->now, rdataset,
1280                                              sigrdataset);
1281                 if (result == DNS_R_NCACHENXDOMAIN)
1282                         goto addname;
1283                 if (result == DNS_R_NCACHENXRRSET) {
1284                         dns_rdataset_disassociate(rdataset);
1285                         /*
1286                          * Negative cache entries don't have sigrdatasets.
1287                          */
1288                         INSIST(sigrdataset == NULL ||
1289                                ! dns_rdataset_isassociated(sigrdataset));
1290                 }
1291                 if (result == ISC_R_SUCCESS) {
1292                         mname = NULL;
1293                         if (!query_isduplicate(client, fname,
1294                                                dns_rdatatype_a, &mname)) {
1295                                 if (mname != NULL) {
1296                                         query_releasename(client, &fname);
1297                                         fname = mname;
1298                                 } else
1299                                         need_addname = ISC_TRUE;
1300                                 ISC_LIST_APPEND(fname->list, rdataset, link);
1301                                 added_something = ISC_TRUE;
1302                                 if (sigrdataset != NULL &&
1303                                     dns_rdataset_isassociated(sigrdataset))
1304                                 {
1305                                         ISC_LIST_APPEND(fname->list,
1306                                                         sigrdataset, link);
1307                                         sigrdataset =
1308                                                 query_newrdataset(client);
1309                                 }
1310                                 rdataset = query_newrdataset(client);
1311                                 if (rdataset == NULL)
1312                                         goto addname;
1313                                 if (WANTDNSSEC(client) && sigrdataset == NULL)
1314                                         goto addname;
1315                         } else {
1316                                 dns_rdataset_disassociate(rdataset);
1317                                 if (sigrdataset != NULL &&
1318                                     dns_rdataset_isassociated(sigrdataset))
1319                                         dns_rdataset_disassociate(sigrdataset);
1320                         }
1321                 }
1322                 result = dns_db_findrdataset(db, node, version,
1323                                              dns_rdatatype_aaaa, 0,
1324                                              client->now, rdataset,
1325                                              sigrdataset);
1326                 if (result == DNS_R_NCACHENXDOMAIN)
1327                         goto addname;
1328                 if (result == DNS_R_NCACHENXRRSET) {
1329                         dns_rdataset_disassociate(rdataset);
1330                         INSIST(sigrdataset == NULL ||
1331                                ! dns_rdataset_isassociated(sigrdataset));
1332                 }
1333                 if (result == ISC_R_SUCCESS) {
1334                         mname = NULL;
1335                         if (!query_isduplicate(client, fname,
1336                                                dns_rdatatype_aaaa, &mname)) {
1337                                 if (mname != NULL) {
1338                                         query_releasename(client, &fname);
1339                                         fname = mname;
1340                                 } else
1341                                         need_addname = ISC_TRUE;
1342                                 ISC_LIST_APPEND(fname->list, rdataset, link);
1343                                 added_something = ISC_TRUE;
1344                                 if (sigrdataset != NULL &&
1345                                     dns_rdataset_isassociated(sigrdataset))
1346                                 {
1347                                         ISC_LIST_APPEND(fname->list,
1348                                                         sigrdataset, link);
1349                                         sigrdataset = NULL;
1350                                 }
1351                                 rdataset = NULL;
1352                         }
1353                 }
1354         }
1355
1356  addname:
1357         CTRACE("query_addadditional: addname");
1358         /*
1359          * If we haven't added anything, then we're done.
1360          */
1361         if (!added_something)
1362                 goto cleanup;
1363
1364         /*
1365          * We may have added our rdatasets to an existing name, if so, then
1366          * need_addname will be ISC_FALSE.  Whether we used an existing name
1367          * or a new one, we must set fname to NULL to prevent cleanup.
1368          */
1369         if (need_addname)
1370                 dns_message_addname(client->message, fname,
1371                                     DNS_SECTION_ADDITIONAL);
1372         fname = NULL;
1373
1374         /*
1375          * In a few cases, we want to add additional data for additional
1376          * data.  It's simpler to just deal with special cases here than
1377          * to try to create a general purpose mechanism and allow the
1378          * rdata implementations to do it themselves.
1379          *
1380          * This involves recursion, but the depth is limited.  The
1381          * most complex case is adding a SRV rdataset, which involves
1382          * recursing to add address records, which in turn can cause
1383          * recursion to add KEYs.
1384          */
1385         if (type == dns_rdatatype_srv && trdataset != NULL) {
1386                 /*
1387                  * If we're adding SRV records to the additional data
1388                  * section, it's helpful if we add the SRV additional data
1389                  * as well.
1390                  */
1391                 eresult = dns_rdataset_additionaldata(trdataset,
1392                                                       query_addadditional,
1393                                                       client);
1394         }
1395
1396  cleanup:
1397         CTRACE("query_addadditional: cleanup");
1398         query_putrdataset(client, &rdataset);
1399         if (sigrdataset != NULL)
1400                 query_putrdataset(client, &sigrdataset);
1401         if (fname != NULL)
1402                 query_releasename(client, &fname);
1403         if (node != NULL)
1404                 dns_db_detachnode(db, &node);
1405         if (db != NULL)
1406                 dns_db_detach(&db);
1407         if (zone != NULL)
1408                 dns_zone_detach(&zone);
1409
1410         CTRACE("query_addadditional: done");
1411         return (eresult);
1412 }
1413
1414 static inline void
1415 query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base,
1416                    dns_rdatasetadditional_t additionaltype,
1417                    dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp,
1418                    dns_dbversion_t **versionp, dns_dbnode_t **nodep,
1419                    dns_name_t *fname)
1420 {
1421         dns_rdataset_t *rdataset;
1422
1423         while  ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) {
1424                 ISC_LIST_UNLINK(fname->list, rdataset, link);
1425                 query_putrdataset(client, &rdataset);
1426         }
1427         if (*versionp != NULL)
1428                 dns_db_closeversion(*dbp, versionp, ISC_FALSE);
1429         if (*nodep != NULL)
1430                 dns_db_detachnode(*dbp, nodep);
1431         if (*dbp != NULL)
1432                 dns_db_detach(dbp);
1433         if (*zonep != NULL)
1434                 dns_zone_detach(zonep);
1435         (void)dns_rdataset_putadditional(client->view->acache, rdataset_base,
1436                                          additionaltype, type);
1437 }
1438
1439 static inline isc_result_t
1440 query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0,
1441                    dns_dbversion_t *version)
1442 {
1443         isc_result_t result = ISC_R_SUCCESS;
1444         dns_dbversion_t *version_current = NULL;
1445         dns_db_t *db_current = db0;
1446
1447         if (db_current == NULL) {
1448                 result = dns_zone_getdb(zone, &db_current);
1449                 if (result != ISC_R_SUCCESS)
1450                         return (result);
1451         }
1452         dns_db_currentversion(db_current, &version_current);
1453         if (db_current != db || version_current != version) {
1454                 result = ISC_R_FAILURE;
1455                 goto cleanup;
1456         }
1457
1458  cleanup:
1459         dns_db_closeversion(db_current, &version_current, ISC_FALSE);
1460         if (db0 == NULL && db_current != NULL)
1461                 dns_db_detach(&db_current);
1462
1463         return (result);
1464 }
1465
1466 static isc_result_t
1467 query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
1468         client_additionalctx_t *additionalctx = arg;
1469         dns_rdataset_t *rdataset_base;
1470         ns_client_t *client;
1471         isc_result_t result, eresult;
1472         dns_dbnode_t *node, *cnode;
1473         dns_db_t *db, *cdb;
1474         dns_name_t *fname, *mname0, cfname;
1475         dns_rdataset_t *rdataset, *sigrdataset;
1476         dns_rdataset_t *crdataset, *crdataset_next;
1477         isc_buffer_t *dbuf;
1478         isc_buffer_t b;
1479         dns_dbversion_t *version, *cversion;
1480         isc_boolean_t added_something, need_addname, needadditionalcache;
1481         isc_boolean_t need_sigrrset;
1482         dns_zone_t *zone;
1483         dns_rdatatype_t type;
1484         dns_rdatasetadditional_t additionaltype;
1485
1486         if (qtype != dns_rdatatype_a) {
1487                 /*
1488                  * This function is optimized for "address" types.  For other
1489                  * types, use a generic routine.
1490                  * XXX: ideally, this function should be generic enough.
1491                  */
1492                 return (query_addadditional(additionalctx->client,
1493                                             name, qtype));
1494         }
1495
1496         /*
1497          * Initialization.
1498          */
1499         rdataset_base = additionalctx->rdataset;
1500         client = additionalctx->client;
1501         REQUIRE(NS_CLIENT_VALID(client));
1502         eresult = ISC_R_SUCCESS;
1503         fname = NULL;
1504         rdataset = NULL;
1505         sigrdataset = NULL;
1506         db = NULL;
1507         cdb = NULL;
1508         version = NULL;
1509         cversion = NULL;
1510         node = NULL;
1511         cnode = NULL;
1512         added_something = ISC_FALSE;
1513         need_addname = ISC_FALSE;
1514         zone = NULL;
1515         needadditionalcache = ISC_FALSE;
1516         additionaltype = dns_rdatasetadditional_fromauth;
1517         dns_name_init(&cfname, NULL);
1518
1519         CTRACE("query_addadditional2");
1520
1521         /*
1522          * We treat type A additional section processing as if it
1523          * were "any address type" additional section processing.
1524          * To avoid multiple lookups, we do an 'any' database
1525          * lookup and iterate over the node.
1526          * XXXJT: this approach can cause a suboptimal result when the cache
1527          * DB only has partial address types and the glue DB has remaining
1528          * ones.
1529          */
1530         type = dns_rdatatype_any;
1531
1532         /*
1533          * Get some resources.
1534          */
1535         dbuf = query_getnamebuf(client);
1536         if (dbuf == NULL)
1537                 goto cleanup;
1538         fname = query_newname(client, dbuf, &b);
1539         if (fname == NULL)
1540                 goto cleanup;
1541         dns_name_setbuffer(&cfname, &b); /* share the buffer */
1542
1543         /* Check additional cache */
1544         result = dns_rdataset_getadditional(rdataset_base, additionaltype,
1545                                             type, client->view->acache, &zone,
1546                                             &cdb, &cversion, &cnode, &cfname,
1547                                             client->message, client->now);
1548         if (result != ISC_R_SUCCESS)
1549                 goto findauthdb;
1550         if (zone == NULL) {
1551                 CTRACE("query_addadditional2: auth zone not found");
1552                 goto try_cache;
1553         }
1554
1555         /* Is the cached DB up-to-date? */
1556         result = query_iscachevalid(zone, cdb, NULL, cversion);
1557         if (result != ISC_R_SUCCESS) {
1558                 CTRACE("query_addadditional2: old auth additional cache");
1559                 query_discardcache(client, rdataset_base, additionaltype,
1560                                    type, &zone, &cdb, &cversion, &cnode,
1561                                    &cfname);
1562                 goto findauthdb;
1563         }
1564
1565         if (cnode == NULL) {
1566                 /*
1567                  * We have a negative cache.  We don't have to check the zone
1568                  * ACL, since the result (not using this zone) would be same
1569                  * regardless of the result.
1570                  */
1571                 CTRACE("query_addadditional2: negative auth additional cache");
1572                 dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1573                 dns_db_detach(&cdb);
1574                 dns_zone_detach(&zone);
1575                 goto try_cache;
1576         }
1577
1578         result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG,
1579                                       zone, cdb, NULL);
1580         if (result != ISC_R_SUCCESS) {
1581                 query_discardcache(client, rdataset_base, additionaltype,
1582                                    type, &zone, &cdb, &cversion, &cnode,
1583                                    &cfname);
1584                 goto try_cache;
1585         }
1586
1587         /* We've got an active cache. */
1588         CTRACE("query_addadditional2: auth additional cache");
1589         dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1590         db = cdb;
1591         node = cnode;
1592         dns_name_clone(&cfname, fname);
1593         query_keepname(client, fname, dbuf);
1594         goto foundcache;
1595
1596         /*
1597          * Look for a zone database that might contain authoritative
1598          * additional data.
1599          */
1600  findauthdb:
1601         result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
1602                                  &zone, &db, &version);
1603         if (result != ISC_R_SUCCESS) {
1604                 /* Cache the negative result */
1605                 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1606                                                  type, client->view->acache,
1607                                                  NULL, NULL, NULL, NULL,
1608                                                  NULL);
1609                 goto try_cache;
1610         }
1611
1612         CTRACE("query_addadditional2: db_find");
1613
1614         /*
1615          * Since we are looking for authoritative data, we do not set
1616          * the GLUEOK flag.  Glue will be looked for later, but not
1617          * necessarily in the same database.
1618          */
1619         node = NULL;
1620         result = dns_db_find(db, name, version, type, client->query.dboptions,
1621                              client->now, &node, fname, NULL, NULL);
1622         if (result == ISC_R_SUCCESS)
1623                 goto found;
1624
1625         /* Cache the negative result */
1626         (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1627                                          type, client->view->acache, zone, db,
1628                                          version, NULL, fname);
1629
1630         if (node != NULL)
1631                 dns_db_detachnode(db, &node);
1632         version = NULL;
1633         dns_db_detach(&db);
1634
1635         /*
1636          * No authoritative data was found.  The cache is our next best bet.
1637          */
1638
1639  try_cache:
1640         additionaltype = dns_rdatasetadditional_fromcache;
1641         result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
1642         if (result != ISC_R_SUCCESS)
1643                 /*
1644                  * Most likely the client isn't allowed to query the cache.
1645                  */
1646                 goto try_glue;
1647
1648         result = dns_db_find(db, name, version, type,
1649                              client->query.dboptions |
1650                              DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
1651                              client->now, &node, fname, NULL, NULL);
1652         if (result == ISC_R_SUCCESS)
1653                 goto found;
1654
1655         if (node != NULL)
1656                 dns_db_detachnode(db, &node);
1657         dns_db_detach(&db);
1658
1659  try_glue:
1660         /*
1661          * No cached data was found.  Glue is our last chance.
1662          * RFC1035 sayeth:
1663          *
1664          *      NS records cause both the usual additional section
1665          *      processing to locate a type A record, and, when used
1666          *      in a referral, a special search of the zone in which
1667          *      they reside for glue information.
1668          *
1669          * This is the "special search".  Note that we must search
1670          * the zone where the NS record resides, not the zone it
1671          * points to, and that we only do the search in the delegation
1672          * case (identified by client->query.gluedb being set).
1673          */
1674         if (client->query.gluedb == NULL)
1675                 goto cleanup;
1676
1677         /*
1678          * Don't poison caches using the bailiwick protection model.
1679          */
1680         if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
1681                 goto cleanup;
1682
1683         /* Check additional cache */
1684         additionaltype = dns_rdatasetadditional_fromglue;
1685         result = dns_rdataset_getadditional(rdataset_base, additionaltype,
1686                                             type, client->view->acache, NULL,
1687                                             &cdb, &cversion, &cnode, &cfname,
1688                                             client->message, client->now);
1689         if (result != ISC_R_SUCCESS)
1690                 goto findglue;
1691
1692         result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion);
1693         if (result != ISC_R_SUCCESS) {
1694                 CTRACE("query_addadditional2: old glue additional cache");
1695                 query_discardcache(client, rdataset_base, additionaltype,
1696                                    type, &zone, &cdb, &cversion, &cnode,
1697                                    &cfname);
1698                 goto findglue;
1699         }
1700
1701         if (cnode == NULL) {
1702                 /* We have a negative cache. */
1703                 CTRACE("query_addadditional2: negative glue additional cache");
1704                 dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1705                 dns_db_detach(&cdb);
1706                 goto cleanup;
1707         }
1708
1709         /* Cache hit. */
1710         CTRACE("query_addadditional2: glue additional cache");
1711         dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1712         db = cdb;
1713         node = cnode;
1714         dns_name_clone(&cfname, fname);
1715         query_keepname(client, fname, dbuf);
1716         goto foundcache;
1717
1718  findglue:
1719         dns_db_attach(client->query.gluedb, &db);
1720         result = dns_db_find(db, name, version, type,
1721                              client->query.dboptions | DNS_DBFIND_GLUEOK,
1722                              client->now, &node, fname, NULL, NULL);
1723         if (!(result == ISC_R_SUCCESS ||
1724               result == DNS_R_ZONECUT ||
1725               result == DNS_R_GLUE)) {
1726                 /* cache the negative result */
1727                 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1728                                                  type, client->view->acache,
1729                                                  NULL, db, version, NULL,
1730                                                  fname);
1731                 goto cleanup;
1732         }
1733
1734  found:
1735         /*
1736          * We have found a DB node to iterate over from a DB.
1737          * We are going to look for address RRsets (i.e., A and AAAA) in the DB
1738          * node we've just found.  We'll then store the complete information
1739          * in the additional data cache.
1740          */
1741         dns_name_clone(fname, &cfname);
1742         query_keepname(client, fname, dbuf);
1743         needadditionalcache = ISC_TRUE;
1744
1745         rdataset = query_newrdataset(client);
1746         if (rdataset == NULL)
1747                 goto cleanup;
1748
1749         sigrdataset = query_newrdataset(client);
1750         if (sigrdataset == NULL)
1751                 goto cleanup;
1752
1753         /*
1754          * Find A RRset with sig RRset.  Even if we don't find a sig RRset
1755          * for a client using DNSSEC, we'll continue the process to make a
1756          * complete list to be cached.  However, we need to cancel the
1757          * caching when something unexpected happens, in order to avoid
1758          * caching incomplete information.
1759          */
1760         result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0,
1761                                      client->now, rdataset, sigrdataset);
1762         /*
1763          * If we can't promote glue/pending from the cache to secure
1764          * then drop it.
1765          */
1766         if (result == ISC_R_SUCCESS &&
1767             additionaltype == dns_rdatasetadditional_fromcache &&
1768             (DNS_TRUST_PENDING(rdataset->trust) ||
1769              DNS_TRUST_GLUE(rdataset->trust)) &&
1770             !validate(client, db, fname, rdataset, sigrdataset)) {
1771                 dns_rdataset_disassociate(rdataset);
1772                 if (dns_rdataset_isassociated(sigrdataset))
1773                         dns_rdataset_disassociate(sigrdataset);
1774                 result = ISC_R_NOTFOUND;
1775         }
1776         if (result == DNS_R_NCACHENXDOMAIN)
1777                 goto setcache;
1778         if (result == DNS_R_NCACHENXRRSET) {
1779                 dns_rdataset_disassociate(rdataset);
1780                 /*
1781                  * Negative cache entries don't have sigrdatasets.
1782                  */
1783                 INSIST(! dns_rdataset_isassociated(sigrdataset));
1784         }
1785         if (result == ISC_R_SUCCESS) {
1786                 /* Remember the result as a cache */
1787                 ISC_LIST_APPEND(cfname.list, rdataset, link);
1788                 if (dns_rdataset_isassociated(sigrdataset)) {
1789                         ISC_LIST_APPEND(cfname.list, sigrdataset, link);
1790                         sigrdataset = query_newrdataset(client);
1791                 }
1792                 rdataset = query_newrdataset(client);
1793                 if (sigrdataset == NULL || rdataset == NULL) {
1794                         /* do not cache incomplete information */
1795                         goto foundcache;
1796                 }
1797         }
1798
1799         /* Find AAAA RRset with sig RRset */
1800         result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa,
1801                                      0, client->now, rdataset, sigrdataset);
1802         /*
1803          * If we can't promote glue/pending from the cache to secure
1804          * then drop it.
1805          */
1806         if (result == ISC_R_SUCCESS &&
1807             additionaltype == dns_rdatasetadditional_fromcache &&
1808             (DNS_TRUST_PENDING(rdataset->trust) ||
1809              DNS_TRUST_GLUE(rdataset->trust)) &&
1810             !validate(client, db, fname, rdataset, sigrdataset)) {
1811                 dns_rdataset_disassociate(rdataset);
1812                 if (dns_rdataset_isassociated(sigrdataset))
1813                         dns_rdataset_disassociate(sigrdataset);
1814                 result = ISC_R_NOTFOUND;
1815         }
1816         if (result == ISC_R_SUCCESS) {
1817                 ISC_LIST_APPEND(cfname.list, rdataset, link);
1818                 rdataset = NULL;
1819                 if (dns_rdataset_isassociated(sigrdataset)) {
1820                         ISC_LIST_APPEND(cfname.list, sigrdataset, link);
1821                         sigrdataset = NULL;
1822                 }
1823         }
1824
1825  setcache:
1826         /*
1827          * Set the new result in the cache if required.  We do not support
1828          * caching additional data from a cache DB.
1829          */
1830         if (needadditionalcache == ISC_TRUE &&
1831             (additionaltype == dns_rdatasetadditional_fromauth ||
1832              additionaltype == dns_rdatasetadditional_fromglue)) {
1833                 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1834                                                  type, client->view->acache,
1835                                                  zone, db, version, node,
1836                                                  &cfname);
1837         }
1838
1839  foundcache:
1840         need_sigrrset = ISC_FALSE;
1841         mname0 = NULL;
1842         for (crdataset = ISC_LIST_HEAD(cfname.list);
1843              crdataset != NULL;
1844              crdataset = crdataset_next) {
1845                 dns_name_t *mname;
1846
1847                 crdataset_next = ISC_LIST_NEXT(crdataset, link);
1848
1849                 mname = NULL;
1850                 if (crdataset->type == dns_rdatatype_a ||
1851                     crdataset->type == dns_rdatatype_aaaa) {
1852                         if (!query_isduplicate(client, fname, crdataset->type,
1853                                                &mname)) {
1854                                 if (mname != NULL) {
1855                                         /*
1856                                          * A different type of this name is
1857                                          * already stored in the additional
1858                                          * section.  We'll reuse the name.
1859                                          * Note that this should happen at most
1860                                          * once.  Otherwise, fname->link could
1861                                          * leak below.
1862                                          */
1863                                         INSIST(mname0 == NULL);
1864
1865                                         query_releasename(client, &fname);
1866                                         fname = mname;
1867                                         mname0 = mname;
1868                                 } else
1869                                         need_addname = ISC_TRUE;
1870                                 ISC_LIST_UNLINK(cfname.list, crdataset, link);
1871                                 ISC_LIST_APPEND(fname->list, crdataset, link);
1872                                 added_something = ISC_TRUE;
1873                                 need_sigrrset = ISC_TRUE;
1874                         } else
1875                                 need_sigrrset = ISC_FALSE;
1876                 } else if (crdataset->type == dns_rdatatype_rrsig &&
1877                            need_sigrrset && WANTDNSSEC(client)) {
1878                         ISC_LIST_UNLINK(cfname.list, crdataset, link);
1879                         ISC_LIST_APPEND(fname->list, crdataset, link);
1880                         added_something = ISC_TRUE; /* just in case */
1881                         need_sigrrset = ISC_FALSE;
1882                 }
1883         }
1884
1885         CTRACE("query_addadditional2: addname");
1886
1887         /*
1888          * If we haven't added anything, then we're done.
1889          */
1890         if (!added_something)
1891                 goto cleanup;
1892
1893         /*
1894          * We may have added our rdatasets to an existing name, if so, then
1895          * need_addname will be ISC_FALSE.  Whether we used an existing name
1896          * or a new one, we must set fname to NULL to prevent cleanup.
1897          */
1898         if (need_addname)
1899                 dns_message_addname(client->message, fname,
1900                                     DNS_SECTION_ADDITIONAL);
1901         fname = NULL;
1902
1903  cleanup:
1904         CTRACE("query_addadditional2: cleanup");
1905
1906         if (rdataset != NULL)
1907                 query_putrdataset(client, &rdataset);
1908         if (sigrdataset != NULL)
1909                 query_putrdataset(client, &sigrdataset);
1910         while  ((crdataset = ISC_LIST_HEAD(cfname.list)) != NULL) {
1911                 ISC_LIST_UNLINK(cfname.list, crdataset, link);
1912                 query_putrdataset(client, &crdataset);
1913         }
1914         if (fname != NULL)
1915                 query_releasename(client, &fname);
1916         if (node != NULL)
1917                 dns_db_detachnode(db, &node);
1918         if (db != NULL)
1919                 dns_db_detach(&db);
1920         if (zone != NULL)
1921                 dns_zone_detach(&zone);
1922
1923         CTRACE("query_addadditional2: done");
1924         return (eresult);
1925 }
1926
1927 static inline void
1928 query_addrdataset(ns_client_t *client, dns_name_t *fname,
1929                   dns_rdataset_t *rdataset)
1930 {
1931         client_additionalctx_t additionalctx;
1932
1933         /*
1934          * Add 'rdataset' and any pertinent additional data to
1935          * 'fname', a name in the response message for 'client'.
1936          */
1937
1938         CTRACE("query_addrdataset");
1939
1940         ISC_LIST_APPEND(fname->list, rdataset, link);
1941
1942         if (client->view->order != NULL)
1943                 rdataset->attributes |= dns_order_find(client->view->order,
1944                                                        fname, rdataset->type,
1945                                                        rdataset->rdclass);
1946         rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
1947
1948         if (NOADDITIONAL(client))
1949                 return;
1950
1951         /*
1952          * Add additional data.
1953          *
1954          * We don't care if dns_rdataset_additionaldata() fails.
1955          */
1956         additionalctx.client = client;
1957         additionalctx.rdataset = rdataset;
1958         (void)dns_rdataset_additionaldata(rdataset, query_addadditional2,
1959                                           &additionalctx);
1960         CTRACE("query_addrdataset: done");
1961 }
1962
1963 static void
1964 query_addrrset(ns_client_t *client, dns_name_t **namep,
1965                dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
1966                isc_buffer_t *dbuf, dns_section_t section)
1967 {
1968         dns_name_t *name, *mname;
1969         dns_rdataset_t *rdataset, *mrdataset, *sigrdataset;
1970         isc_result_t result;
1971
1972         /*%
1973          * To the current response for 'client', add the answer RRset
1974          * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
1975          * owner name '*namep', to section 'section', unless they are
1976          * already there.  Also add any pertinent additional data.
1977          *
1978          * If 'dbuf' is not NULL, then '*namep' is the name whose data is
1979          * stored in 'dbuf'.  In this case, query_addrrset() guarantees that
1980          * when it returns the name will either have been kept or released.
1981          */
1982         CTRACE("query_addrrset");
1983         name = *namep;
1984         rdataset = *rdatasetp;
1985         if (sigrdatasetp != NULL)
1986                 sigrdataset = *sigrdatasetp;
1987         else
1988                 sigrdataset = NULL;
1989         mname = NULL;
1990         mrdataset = NULL;
1991         result = dns_message_findname(client->message, section,
1992                                       name, rdataset->type, rdataset->covers,
1993                                       &mname, &mrdataset);
1994         if (result == ISC_R_SUCCESS) {
1995                 /*
1996                  * We've already got an RRset of the given name and type.
1997                  * There's nothing else to do;
1998                  */
1999                 CTRACE("query_addrrset: dns_message_findname succeeded: done");
2000                 if (dbuf != NULL)
2001                         query_releasename(client, namep);
2002                 return;
2003         } else if (result == DNS_R_NXDOMAIN) {
2004                 /*
2005                  * The name doesn't exist.
2006                  */
2007                 if (dbuf != NULL)
2008                         query_keepname(client, name, dbuf);
2009                 dns_message_addname(client->message, name, section);
2010                 *namep = NULL;
2011                 mname = name;
2012         } else {
2013                 RUNTIME_CHECK(result == DNS_R_NXRRSET);
2014                 if (dbuf != NULL)
2015                         query_releasename(client, namep);
2016         }
2017
2018         if (rdataset->trust != dns_trust_secure &&
2019             (section == DNS_SECTION_ANSWER ||
2020              section == DNS_SECTION_AUTHORITY))
2021                 client->query.attributes &= ~NS_QUERYATTR_SECURE;
2022         /*
2023          * Note: we only add SIGs if we've added the type they cover, so
2024          * we do not need to check if the SIG rdataset is already in the
2025          * response.
2026          */
2027         query_addrdataset(client, mname, rdataset);
2028         *rdatasetp = NULL;
2029         if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
2030                 /*
2031                  * We have a signature.  Add it to the response.
2032                  */
2033                 ISC_LIST_APPEND(mname->list, sigrdataset, link);
2034                 *sigrdatasetp = NULL;
2035         }
2036         CTRACE("query_addrrset: done");
2037 }
2038
2039 static inline isc_result_t
2040 query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
2041              isc_boolean_t zero_ttl)
2042 {
2043         dns_name_t *name;
2044         dns_dbnode_t *node;
2045         isc_result_t result, eresult;
2046         dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2047         dns_rdataset_t **sigrdatasetp = NULL;
2048
2049         CTRACE("query_addsoa");
2050         /*
2051          * Initialization.
2052          */
2053         eresult = ISC_R_SUCCESS;
2054         name = NULL;
2055         rdataset = NULL;
2056         node = NULL;
2057
2058         /*
2059          * Get resources and make 'name' be the database origin.
2060          */
2061         result = dns_message_gettempname(client->message, &name);
2062         if (result != ISC_R_SUCCESS)
2063                 return (result);
2064         dns_name_init(name, NULL);
2065         dns_name_clone(dns_db_origin(db), name);
2066         rdataset = query_newrdataset(client);
2067         if (rdataset == NULL) {
2068                 eresult = DNS_R_SERVFAIL;
2069                 goto cleanup;
2070         }
2071         if (WANTDNSSEC(client) && dns_db_issecure(db)) {
2072                 sigrdataset = query_newrdataset(client);
2073                 if (sigrdataset == NULL) {
2074                         eresult = DNS_R_SERVFAIL;
2075                         goto cleanup;
2076                 }
2077         }
2078
2079         /*
2080          * Find the SOA.
2081          */
2082         result = dns_db_getoriginnode(db, &node);
2083         if (result == ISC_R_SUCCESS) {
2084                 result = dns_db_findrdataset(db, node, version,
2085                                              dns_rdatatype_soa,
2086                                              0, client->now, rdataset,
2087                                              sigrdataset);
2088         } else {
2089                 dns_fixedname_t foundname;
2090                 dns_name_t *fname;
2091
2092                 dns_fixedname_init(&foundname);
2093                 fname = dns_fixedname_name(&foundname);
2094
2095                 result = dns_db_find(db, name, version, dns_rdatatype_soa,
2096                                      client->query.dboptions, 0, &node,
2097                                      fname, rdataset, sigrdataset);
2098         }
2099         if (result != ISC_R_SUCCESS) {
2100                 /*
2101                  * This is bad.  We tried to get the SOA RR at the zone top
2102                  * and it didn't work!
2103                  */
2104                 eresult = DNS_R_SERVFAIL;
2105         } else {
2106                 /*
2107                  * Extract the SOA MINIMUM.
2108                  */
2109                 dns_rdata_soa_t soa;
2110                 dns_rdata_t rdata = DNS_RDATA_INIT;
2111                 result = dns_rdataset_first(rdataset);
2112                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2113                 dns_rdataset_current(rdataset, &rdata);
2114                 result = dns_rdata_tostruct(&rdata, &soa, NULL);
2115                 if (result != ISC_R_SUCCESS)
2116                         goto cleanup;
2117
2118                 if (zero_ttl) {
2119                         rdataset->ttl = 0;
2120                         if (sigrdataset != NULL)
2121                                 sigrdataset->ttl = 0;
2122                 }
2123
2124                 /*
2125                  * Add the SOA and its SIG to the response, with the
2126                  * TTLs adjusted per RFC2308 section 3.
2127                  */
2128                 if (rdataset->ttl > soa.minimum)
2129                         rdataset->ttl = soa.minimum;
2130                 if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum)
2131                         sigrdataset->ttl = soa.minimum;
2132
2133                 if (sigrdataset != NULL)
2134                         sigrdatasetp = &sigrdataset;
2135                 else
2136                         sigrdatasetp = NULL;
2137                 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
2138                                DNS_SECTION_AUTHORITY);
2139         }
2140
2141  cleanup:
2142         query_putrdataset(client, &rdataset);
2143         if (sigrdataset != NULL)
2144                 query_putrdataset(client, &sigrdataset);
2145         if (name != NULL)
2146                 query_releasename(client, &name);
2147         if (node != NULL)
2148                 dns_db_detachnode(db, &node);
2149
2150         return (eresult);
2151 }
2152
2153 static inline isc_result_t
2154 query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
2155         dns_name_t *name, *fname;
2156         dns_dbnode_t *node;
2157         isc_result_t result, eresult;
2158         dns_fixedname_t foundname;
2159         dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2160         dns_rdataset_t **sigrdatasetp = NULL;
2161
2162         CTRACE("query_addns");
2163         /*
2164          * Initialization.
2165          */
2166         eresult = ISC_R_SUCCESS;
2167         name = NULL;
2168         rdataset = NULL;
2169         node = NULL;
2170         dns_fixedname_init(&foundname);
2171         fname = dns_fixedname_name(&foundname);
2172
2173         /*
2174          * Get resources and make 'name' be the database origin.
2175          */
2176         result = dns_message_gettempname(client->message, &name);
2177         if (result != ISC_R_SUCCESS) {
2178                 CTRACE("query_addns: dns_message_gettempname failed: done");
2179                 return (result);
2180         }
2181         dns_name_init(name, NULL);
2182         dns_name_clone(dns_db_origin(db), name);
2183         rdataset = query_newrdataset(client);
2184         if (rdataset == NULL) {
2185                 CTRACE("query_addns: query_newrdataset failed");
2186                 eresult = DNS_R_SERVFAIL;
2187                 goto cleanup;
2188         }
2189         if (WANTDNSSEC(client) && dns_db_issecure(db)) {
2190                 sigrdataset = query_newrdataset(client);
2191                 if (sigrdataset == NULL) {
2192                         CTRACE("query_addns: query_newrdataset failed");
2193                         eresult = DNS_R_SERVFAIL;
2194                         goto cleanup;
2195                 }
2196         }
2197
2198         /*
2199          * Find the NS rdataset.
2200          */
2201         result = dns_db_getoriginnode(db, &node);
2202         if (result == ISC_R_SUCCESS) {
2203                 result = dns_db_findrdataset(db, node, version,
2204                                              dns_rdatatype_ns,
2205                                              0, client->now, rdataset,
2206                                              sigrdataset);
2207         } else {
2208                 CTRACE("query_addns: calling dns_db_find");
2209                 result = dns_db_find(db, name, NULL, dns_rdatatype_ns,
2210                                      client->query.dboptions, 0, &node,
2211                                      fname, rdataset, sigrdataset);
2212                 CTRACE("query_addns: dns_db_find complete");
2213         }
2214         if (result != ISC_R_SUCCESS) {
2215                 CTRACE("query_addns: "
2216                        "dns_db_findrdataset or dns_db_find failed");
2217                 /*
2218                  * This is bad.  We tried to get the NS rdataset at the zone
2219                  * top and it didn't work!
2220                  */
2221                 eresult = DNS_R_SERVFAIL;
2222         } else {
2223                 if (sigrdataset != NULL)
2224                         sigrdatasetp = &sigrdataset;
2225                 else
2226                         sigrdatasetp = NULL;
2227                 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
2228                                DNS_SECTION_AUTHORITY);
2229         }
2230
2231  cleanup:
2232         CTRACE("query_addns: cleanup");
2233         query_putrdataset(client, &rdataset);
2234         if (sigrdataset != NULL)
2235                 query_putrdataset(client, &sigrdataset);
2236         if (name != NULL)
2237                 query_releasename(client, &name);
2238         if (node != NULL)
2239                 dns_db_detachnode(db, &node);
2240
2241         CTRACE("query_addns: done");
2242         return (eresult);
2243 }
2244
2245 static inline isc_result_t
2246 query_addcnamelike(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
2247                    dns_trust_t trust, dns_name_t **anamep, dns_rdatatype_t type)
2248 {
2249         dns_rdataset_t *rdataset;
2250         dns_rdatalist_t *rdatalist;
2251         dns_rdata_t *rdata;
2252         isc_result_t result;
2253         isc_region_t r;
2254
2255         /*
2256          * We assume the name data referred to by tname won't go away.
2257          */
2258
2259         REQUIRE(anamep != NULL);
2260
2261         rdatalist = NULL;
2262         result = dns_message_gettemprdatalist(client->message, &rdatalist);
2263         if (result != ISC_R_SUCCESS)
2264                 return (result);
2265         rdata = NULL;
2266         result = dns_message_gettemprdata(client->message, &rdata);
2267         if (result != ISC_R_SUCCESS)
2268                 return (result);
2269         rdataset = NULL;
2270         result = dns_message_gettemprdataset(client->message, &rdataset);
2271         if (result != ISC_R_SUCCESS)
2272                 return (result);
2273         dns_rdataset_init(rdataset);
2274         result = dns_name_dup(qname, client->mctx, *anamep);
2275         if (result != ISC_R_SUCCESS) {
2276                 dns_message_puttemprdataset(client->message, &rdataset);
2277                 return (result);
2278         }
2279
2280         rdatalist->type = type;
2281         rdatalist->covers = 0;
2282         rdatalist->rdclass = client->message->rdclass;
2283         rdatalist->ttl = 0;
2284
2285         dns_name_toregion(tname, &r);
2286         rdata->data = r.base;
2287         rdata->length = r.length;
2288         rdata->rdclass = client->message->rdclass;
2289         rdata->type = type;
2290
2291         ISC_LIST_INIT(rdatalist->rdata);
2292         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2293         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
2294                       == ISC_R_SUCCESS);
2295         rdataset->trust = trust;
2296
2297         query_addrrset(client, anamep, &rdataset, NULL, NULL,
2298                        DNS_SECTION_ANSWER);
2299
2300         if (rdataset != NULL) {
2301                 if (dns_rdataset_isassociated(rdataset))
2302                         dns_rdataset_disassociate(rdataset);
2303                 dns_message_puttemprdataset(client->message, &rdataset);
2304         }
2305
2306         return (ISC_R_SUCCESS);
2307 }
2308
2309 /*
2310  * Mark the RRsets as secure.  Update the cache (db) to reflect the
2311  * change in trust level.
2312  */
2313 static void
2314 mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
2315             isc_uint32_t ttl, dns_rdataset_t *rdataset,
2316             dns_rdataset_t *sigrdataset)
2317 {
2318         isc_result_t result;
2319         dns_dbnode_t *node = NULL;
2320
2321         rdataset->trust = dns_trust_secure;
2322         sigrdataset->trust = dns_trust_secure;
2323
2324         /*
2325          * Save the updated secure state.  Ignore failures.
2326          */
2327         result = dns_db_findnode(db, name, ISC_TRUE, &node);
2328         if (result != ISC_R_SUCCESS)
2329                 return;
2330         /*
2331          * Bound the validated ttls then minimise.
2332          */
2333         if (sigrdataset->ttl > ttl)
2334                 sigrdataset->ttl = ttl;
2335         if (rdataset->ttl > ttl)
2336                 rdataset->ttl = ttl;
2337         if (rdataset->ttl > sigrdataset->ttl)
2338                 rdataset->ttl = sigrdataset->ttl;
2339         else
2340                 sigrdataset->ttl = rdataset->ttl;
2341
2342         (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset,
2343                                  0, NULL);
2344         (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset,
2345                                  0, NULL);
2346         dns_db_detachnode(db, &node);
2347 }
2348
2349 /*
2350  * Find the secure key that corresponds to rrsig.
2351  * Note: 'keyrdataset' maintains state between successive calls,
2352  * there may be multiple keys with the same keyid.
2353  * Return ISC_FALSE if we have exhausted all the possible keys.
2354  */
2355 static isc_boolean_t
2356 get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
2357         dns_rdataset_t *keyrdataset, dst_key_t **keyp)
2358 {
2359         isc_result_t result;
2360         dns_dbnode_t *node = NULL;
2361         isc_boolean_t secure = ISC_FALSE;
2362
2363         if (!dns_rdataset_isassociated(keyrdataset)) {
2364                 result = dns_db_findnode(db, &rrsig->signer, ISC_FALSE, &node);
2365                 if (result != ISC_R_SUCCESS)
2366                         return (ISC_FALSE);
2367
2368                 result = dns_db_findrdataset(db, node, NULL,
2369                                              dns_rdatatype_dnskey, 0,
2370                                              client->now, keyrdataset, NULL);
2371                 dns_db_detachnode(db, &node);
2372                 if (result != ISC_R_SUCCESS)
2373                         return (ISC_FALSE);
2374
2375                 if (keyrdataset->trust != dns_trust_secure)
2376                         return (ISC_FALSE);
2377
2378                 result = dns_rdataset_first(keyrdataset);
2379         } else
2380                 result = dns_rdataset_next(keyrdataset);
2381
2382         for ( ; result == ISC_R_SUCCESS;
2383              result = dns_rdataset_next(keyrdataset)) {
2384                 dns_rdata_t rdata = DNS_RDATA_INIT;
2385                 isc_buffer_t b;
2386
2387                 dns_rdataset_current(keyrdataset, &rdata);
2388                 isc_buffer_init(&b, rdata.data, rdata.length);
2389                 isc_buffer_add(&b, rdata.length);
2390                 result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
2391                                          client->mctx, keyp);
2392                 if (result != ISC_R_SUCCESS)
2393                         continue;
2394                 if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
2395                     rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
2396                     dst_key_iszonekey(*keyp)) {
2397                         secure = ISC_TRUE;
2398                         break;
2399                 }
2400                 dst_key_free(keyp);
2401         }
2402         return (secure);
2403 }
2404
2405 static isc_boolean_t
2406 verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,
2407        dns_rdata_t *rdata, isc_mem_t *mctx, isc_boolean_t acceptexpired)
2408 {
2409         isc_result_t result;
2410         dns_fixedname_t fixed;
2411         isc_boolean_t ignore = ISC_FALSE;
2412
2413         dns_fixedname_init(&fixed);
2414
2415 again:
2416         result = dns_dnssec_verify2(name, rdataset, key, ignore, mctx,
2417                                     rdata, NULL);
2418         if (result == DNS_R_SIGEXPIRED && acceptexpired) {
2419                 ignore = ISC_TRUE;
2420                 goto again;
2421         }
2422         if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD)
2423                 return (ISC_TRUE);
2424         return (ISC_FALSE);
2425 }
2426
2427 /*
2428  * Validate the rdataset if possible with available records.
2429  */
2430 static isc_boolean_t
2431 validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
2432          dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
2433 {
2434         isc_result_t result;
2435         dns_rdata_t rdata = DNS_RDATA_INIT;
2436         dns_rdata_rrsig_t rrsig;
2437         dst_key_t *key = NULL;
2438         dns_rdataset_t keyrdataset;
2439
2440         if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
2441                 return (ISC_FALSE);
2442
2443         for (result = dns_rdataset_first(sigrdataset);
2444              result == ISC_R_SUCCESS;
2445              result = dns_rdataset_next(sigrdataset)) {
2446
2447                 dns_rdata_reset(&rdata);
2448                 dns_rdataset_current(sigrdataset, &rdata);
2449                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
2450                 if (result != ISC_R_SUCCESS)
2451                         return (ISC_FALSE);
2452                 if (!dns_resolver_algorithm_supported(client->view->resolver,
2453                                                       name, rrsig.algorithm))
2454                         continue;
2455                 if (!dns_name_issubdomain(name, &rrsig.signer))
2456                         continue;
2457                 dns_rdataset_init(&keyrdataset);
2458                 do {
2459                         if (!get_key(client, db, &rrsig, &keyrdataset, &key))
2460                                 break;
2461                         if (verify(key, name, rdataset, &rdata, client->mctx,
2462                                    client->view->acceptexpired)) {
2463                                 dst_key_free(&key);
2464                                 dns_rdataset_disassociate(&keyrdataset);
2465                                 mark_secure(client, db, name,
2466                                             rrsig.originalttl,
2467                                             rdataset, sigrdataset);
2468                                 return (ISC_TRUE);
2469                         }
2470                         dst_key_free(&key);
2471                 } while (1);
2472                 if (dns_rdataset_isassociated(&keyrdataset))
2473                         dns_rdataset_disassociate(&keyrdataset);
2474         }
2475         return (ISC_FALSE);
2476 }
2477
2478 static void
2479 query_addbestns(ns_client_t *client) {
2480         dns_db_t *db, *zdb;
2481         dns_dbnode_t *node;
2482         dns_name_t *fname, *zfname;
2483         dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset;
2484         isc_boolean_t is_zone, use_zone;
2485         isc_buffer_t *dbuf;
2486         isc_result_t result;
2487         dns_dbversion_t *version;
2488         dns_zone_t *zone;
2489         isc_buffer_t b;
2490
2491         CTRACE("query_addbestns");
2492         fname = NULL;
2493         zfname = NULL;
2494         rdataset = NULL;
2495         zrdataset = NULL;
2496         sigrdataset = NULL;
2497         zsigrdataset = NULL;
2498         node = NULL;
2499         db = NULL;
2500         zdb = NULL;
2501         version = NULL;
2502         zone = NULL;
2503         is_zone = ISC_FALSE;
2504         use_zone = ISC_FALSE;
2505
2506         /*
2507          * Find the right database.
2508          */
2509         result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0,
2510                              &zone, &db, &version, &is_zone);
2511         if (result != ISC_R_SUCCESS)
2512                 goto cleanup;
2513
2514  db_find:
2515         /*
2516          * We'll need some resources...
2517          */
2518         dbuf = query_getnamebuf(client);
2519         if (dbuf == NULL)
2520                 goto cleanup;
2521         fname = query_newname(client, dbuf, &b);
2522         rdataset = query_newrdataset(client);
2523         if (fname == NULL || rdataset == NULL)
2524                 goto cleanup;
2525         /*
2526          * Get the RRSIGs if the client requested them or if we may
2527          * need to validate answers from the cache.
2528          */
2529         if (WANTDNSSEC(client) || !is_zone) {
2530                 sigrdataset = query_newrdataset(client);
2531                 if (sigrdataset == NULL)
2532                         goto cleanup;
2533         }
2534
2535         /*
2536          * Now look for the zonecut.
2537          */
2538         if (is_zone) {
2539                 result = dns_db_find(db, client->query.qname, version,
2540                                      dns_rdatatype_ns, client->query.dboptions,
2541                                      client->now, &node, fname,
2542                                      rdataset, sigrdataset);
2543                 if (result != DNS_R_DELEGATION)
2544                         goto cleanup;
2545                 if (USECACHE(client)) {
2546                         query_keepname(client, fname, dbuf);
2547                         zdb = db;
2548                         zfname = fname;
2549                         fname = NULL;
2550                         zrdataset = rdataset;
2551                         rdataset = NULL;
2552                         zsigrdataset = sigrdataset;
2553                         sigrdataset = NULL;
2554                         dns_db_detachnode(db, &node);
2555                         version = NULL;
2556                         db = NULL;
2557                         dns_db_attach(client->view->cachedb, &db);
2558                         is_zone = ISC_FALSE;
2559                         goto db_find;
2560                 }
2561         } else {
2562                 result = dns_db_findzonecut(db, client->query.qname,
2563                                             client->query.dboptions,
2564                                             client->now, &node, fname,
2565                                             rdataset, sigrdataset);
2566                 if (result == ISC_R_SUCCESS) {
2567                         if (zfname != NULL &&
2568                             !dns_name_issubdomain(fname, zfname)) {
2569                                 /*
2570                                  * We found a zonecut in the cache, but our
2571                                  * zone delegation is better.
2572                                  */
2573                                 use_zone = ISC_TRUE;
2574                         }
2575                 } else if (result == ISC_R_NOTFOUND && zfname != NULL) {
2576                         /*
2577                          * We didn't find anything in the cache, but we
2578                          * have a zone delegation, so use it.
2579                          */
2580                         use_zone = ISC_TRUE;
2581                 } else
2582                         goto cleanup;
2583         }
2584
2585         if (use_zone) {
2586                 query_releasename(client, &fname);
2587                 fname = zfname;
2588                 zfname = NULL;
2589                 /*
2590                  * We've already done query_keepname() on
2591                  * zfname, so we must set dbuf to NULL to
2592                  * prevent query_addrrset() from trying to
2593                  * call query_keepname() again.
2594                  */
2595                 dbuf = NULL;
2596                 query_putrdataset(client, &rdataset);
2597                 if (sigrdataset != NULL)
2598                         query_putrdataset(client, &sigrdataset);
2599                 rdataset = zrdataset;
2600                 zrdataset = NULL;
2601                 sigrdataset = zsigrdataset;
2602                 zsigrdataset = NULL;
2603         }
2604
2605         /*
2606          * Attempt to validate RRsets that are pending or that are glue.
2607          */
2608         if ((DNS_TRUST_PENDING(rdataset->trust) ||
2609              (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust)))
2610             && !validate(client, db, fname, rdataset, sigrdataset) &&
2611             !PENDINGOK(client->query.dboptions))
2612                 goto cleanup;
2613
2614         if ((DNS_TRUST_GLUE(rdataset->trust) ||
2615              (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
2616             !validate(client, db, fname, rdataset, sigrdataset) &&
2617             SECURE(client) && WANTDNSSEC(client))
2618                 goto cleanup;
2619
2620         /*
2621          * If the client doesn't want DNSSEC we can discard the sigrdataset
2622          * now.
2623          */
2624         if (!WANTDNSSEC(client))
2625                 query_putrdataset(client, &sigrdataset);
2626         query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
2627                        DNS_SECTION_AUTHORITY);
2628
2629  cleanup:
2630         if (rdataset != NULL)
2631                 query_putrdataset(client, &rdataset);
2632         if (sigrdataset != NULL)
2633                 query_putrdataset(client, &sigrdataset);
2634         if (fname != NULL)
2635                 query_releasename(client, &fname);
2636         if (node != NULL)
2637                 dns_db_detachnode(db, &node);
2638         if (db != NULL)
2639                 dns_db_detach(&db);
2640         if (zone != NULL)
2641                 dns_zone_detach(&zone);
2642         if (zdb != NULL) {
2643                 query_putrdataset(client, &zrdataset);
2644                 if (zsigrdataset != NULL)
2645                         query_putrdataset(client, &zsigrdataset);
2646                 if (zfname != NULL)
2647                         query_releasename(client, &zfname);
2648                 dns_db_detach(&zdb);
2649         }
2650 }
2651
2652 static void
2653 fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) {
2654         if (*rdataset == NULL)
2655                 *rdataset = query_newrdataset(client);
2656         else  if (dns_rdataset_isassociated(*rdataset))
2657                 dns_rdataset_disassociate(*rdataset);
2658 }
2659
2660 static void
2661 fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf,
2662          isc_buffer_t *nbuf)
2663 {
2664         if (*fname == NULL) {
2665                 *dbuf = query_getnamebuf(client);
2666                 if (*dbuf == NULL)
2667                         return;
2668                 *fname = query_newname(client, *dbuf, nbuf);
2669         }
2670 }
2671
2672 static void
2673 query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node,
2674             dns_dbversion_t *version, dns_name_t *name)
2675 {
2676         dns_fixedname_t fixed;
2677         dns_name_t *fname = NULL;
2678         dns_name_t *rname;
2679         dns_rdataset_t *rdataset, *sigrdataset;
2680         isc_buffer_t *dbuf, b;
2681         isc_result_t result;
2682         unsigned int count;
2683
2684         CTRACE("query_addds");
2685         rname = NULL;
2686         rdataset = NULL;
2687         sigrdataset = NULL;
2688
2689         /*
2690          * We'll need some resources...
2691          */
2692         rdataset = query_newrdataset(client);
2693         sigrdataset = query_newrdataset(client);
2694         if (rdataset == NULL || sigrdataset == NULL)
2695                 goto cleanup;
2696
2697         /*
2698          * Look for the DS record, which may or may not be present.
2699          */
2700         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ds, 0,
2701                                      client->now, rdataset, sigrdataset);
2702         /*
2703          * If we didn't find it, look for an NSEC.
2704          */
2705         if (result == ISC_R_NOTFOUND)
2706                 result = dns_db_findrdataset(db, node, version,
2707                                              dns_rdatatype_nsec, 0, client->now,
2708                                              rdataset, sigrdataset);
2709         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
2710                 goto addnsec3;
2711         if (!dns_rdataset_isassociated(rdataset) ||
2712             !dns_rdataset_isassociated(sigrdataset))
2713                 goto addnsec3;
2714
2715         /*
2716          * We've already added the NS record, so if the name's not there,
2717          * we have other problems.  Use this name rather than calling
2718          * query_addrrset().
2719          */
2720         result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
2721         if (result != ISC_R_SUCCESS)
2722                 goto cleanup;
2723
2724         rname = NULL;
2725         dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
2726                                 &rname);
2727         result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
2728         if (result != ISC_R_SUCCESS)
2729                 goto cleanup;
2730
2731         ISC_LIST_APPEND(rname->list, rdataset, link);
2732         ISC_LIST_APPEND(rname->list, sigrdataset, link);
2733         rdataset = NULL;
2734         sigrdataset = NULL;
2735         return;
2736
2737    addnsec3:
2738         if (dns_db_iscache(db))
2739                 goto cleanup;
2740         /*
2741          * Add the NSEC3 which proves the DS does not exist.
2742          */
2743         dbuf = query_getnamebuf(client);
2744         if (dbuf == NULL)
2745                 goto cleanup;
2746         fname = query_newname(client, dbuf, &b);
2747         dns_fixedname_init(&fixed);
2748         if (dns_rdataset_isassociated(rdataset))
2749                 dns_rdataset_disassociate(rdataset);
2750         if (dns_rdataset_isassociated(sigrdataset))
2751                 dns_rdataset_disassociate(sigrdataset);
2752         query_findclosestnsec3(name, db, version, client, rdataset,
2753                                sigrdataset, fname, ISC_TRUE,
2754                                dns_fixedname_name(&fixed));
2755         if (!dns_rdataset_isassociated(rdataset))
2756                 goto cleanup;
2757         query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
2758                        DNS_SECTION_AUTHORITY);
2759         /*
2760          * Did we find the closest provable encloser instead?
2761          * If so add the nearest to the closest provable encloser.
2762          */
2763         if (!dns_name_equal(name, dns_fixedname_name(&fixed))) {
2764                 count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1;
2765                 dns_name_getlabelsequence(name,
2766                                           dns_name_countlabels(name) - count,
2767                                           count, dns_fixedname_name(&fixed));
2768                 fixfname(client, &fname, &dbuf, &b);
2769                 fixrdataset(client, &rdataset);
2770                 fixrdataset(client, &sigrdataset);
2771                 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
2772                                 goto cleanup;
2773                 query_findclosestnsec3(dns_fixedname_name(&fixed), db, version,
2774                                        client, rdataset, sigrdataset, fname,
2775                                        ISC_FALSE, NULL);
2776                 if (!dns_rdataset_isassociated(rdataset))
2777                         goto cleanup;
2778                 query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
2779                                DNS_SECTION_AUTHORITY);
2780         }
2781
2782  cleanup:
2783         if (rdataset != NULL)
2784                 query_putrdataset(client, &rdataset);
2785         if (sigrdataset != NULL)
2786                 query_putrdataset(client, &sigrdataset);
2787         if (fname != NULL)
2788                 query_releasename(client, &fname);
2789 }
2790
2791 static void
2792 query_addwildcardproof(ns_client_t *client, dns_db_t *db,
2793                        dns_dbversion_t *version, dns_name_t *name,
2794                        isc_boolean_t ispositive)
2795 {
2796         isc_buffer_t *dbuf, b;
2797         dns_name_t *fname;
2798         dns_rdataset_t *rdataset, *sigrdataset;
2799         dns_fixedname_t wfixed;
2800         dns_name_t *wname;
2801         dns_dbnode_t *node;
2802         unsigned int options;
2803         unsigned int olabels, nlabels, labels;
2804         isc_result_t result;
2805         dns_rdata_t rdata = DNS_RDATA_INIT;
2806         dns_rdata_nsec_t nsec;
2807         isc_boolean_t have_wname;
2808         int order;
2809         dns_fixedname_t cfixed;
2810         dns_name_t *cname;
2811
2812         CTRACE("query_addwildcardproof");
2813         fname = NULL;
2814         rdataset = NULL;
2815         sigrdataset = NULL;
2816         node = NULL;
2817
2818         /*
2819          * Get the NOQNAME proof then if !ispositive
2820          * get the NOWILDCARD proof.
2821          *
2822          * DNS_DBFIND_NOWILD finds the NSEC records that covers the
2823          * name ignoring any wildcard.  From the owner and next names
2824          * of this record you can compute which wildcard (if it exists)
2825          * will match by finding the longest common suffix of the
2826          * owner name and next names with the qname and prefixing that
2827          * with the wildcard label.
2828          *
2829          * e.g.
2830          *   Given:
2831          *      example SOA
2832          *      example NSEC b.example
2833          *      b.example A
2834          *      b.example NSEC a.d.example
2835          *      a.d.example A
2836          *      a.d.example NSEC g.f.example
2837          *      g.f.example A
2838          *      g.f.example NSEC z.i.example
2839          *      z.i.example A
2840          *      z.i.example NSEC example
2841          *
2842          *   QNAME:
2843          *   a.example -> example NSEC b.example
2844          *      owner common example
2845          *      next common example
2846          *      wild *.example
2847          *   d.b.example -> b.example NSEC a.d.example
2848          *      owner common b.example
2849          *      next common example
2850          *      wild *.b.example
2851          *   a.f.example -> a.d.example NSEC g.f.example
2852          *      owner common example
2853          *      next common f.example
2854          *      wild *.f.example
2855          *  j.example -> z.i.example NSEC example
2856          *      owner common example
2857          *      next common example
2858          *      wild *.f.example
2859          */
2860         options = client->query.dboptions | DNS_DBFIND_NOWILD;
2861         dns_fixedname_init(&wfixed);
2862         wname = dns_fixedname_name(&wfixed);
2863  again:
2864         have_wname = ISC_FALSE;
2865         /*
2866          * We'll need some resources...
2867          */
2868         dbuf = query_getnamebuf(client);
2869         if (dbuf == NULL)
2870                 goto cleanup;
2871         fname = query_newname(client, dbuf, &b);
2872         rdataset = query_newrdataset(client);
2873         sigrdataset = query_newrdataset(client);
2874         if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
2875                 goto cleanup;
2876
2877         result = dns_db_find(db, name, version, dns_rdatatype_nsec, options,
2878                              0, &node, fname, rdataset, sigrdataset);
2879         if (node != NULL)
2880                 dns_db_detachnode(db, &node);
2881
2882         if (!dns_rdataset_isassociated(rdataset)) {
2883                 /*
2884                  * No NSEC proof available, return NSEC3 proofs instead.
2885                  */
2886                 dns_fixedname_init(&cfixed);
2887                 cname = dns_fixedname_name(&cfixed);
2888                 /*
2889                  * Find the closest encloser.
2890                  */
2891                 dns_name_copy(name, cname, NULL);
2892                 while (result == DNS_R_NXDOMAIN) {
2893                         labels = dns_name_countlabels(cname) - 1;
2894                         dns_name_split(cname, labels, NULL, cname);
2895                         result = dns_db_find(db, cname, version,
2896                                              dns_rdatatype_nsec,
2897                                              options, 0, NULL, fname,
2898                                              NULL, NULL);
2899                 }
2900                 /*
2901                  * Add closest (provable) encloser NSEC3.
2902                  */
2903                 query_findclosestnsec3(cname, db, NULL, client, rdataset,
2904                                        sigrdataset, fname, ISC_TRUE, cname);
2905                 if (!dns_rdataset_isassociated(rdataset))
2906                         goto cleanup;
2907                 query_addrrset(client, &fname, &rdataset, &sigrdataset,
2908                                dbuf, DNS_SECTION_AUTHORITY);
2909
2910                 /*
2911                  * Replace resources which were consumed by query_addrrset.
2912                  */
2913                 if (fname == NULL) {
2914                         dbuf = query_getnamebuf(client);
2915                         if (dbuf == NULL)
2916                                 goto cleanup;
2917                         fname = query_newname(client, dbuf, &b);
2918                 }
2919
2920                 if (rdataset == NULL)
2921                         rdataset = query_newrdataset(client);
2922                 else if (dns_rdataset_isassociated(rdataset))
2923                         dns_rdataset_disassociate(rdataset);
2924
2925                 if (sigrdataset == NULL)
2926                         sigrdataset = query_newrdataset(client);
2927                 else if (dns_rdataset_isassociated(sigrdataset))
2928                         dns_rdataset_disassociate(sigrdataset);
2929
2930                 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
2931                         goto cleanup;
2932                 /*
2933                  * Add no qname proof.
2934                  */
2935                 labels = dns_name_countlabels(cname) + 1;
2936                 if (dns_name_countlabels(name) == labels)
2937                         dns_name_copy(name, wname, NULL);
2938                 else
2939                         dns_name_split(name, labels, NULL, wname);
2940
2941                 query_findclosestnsec3(wname, db, NULL, client, rdataset,
2942                                        sigrdataset, fname, ISC_FALSE, NULL);
2943                 if (!dns_rdataset_isassociated(rdataset))
2944                         goto cleanup;
2945                 query_addrrset(client, &fname, &rdataset, &sigrdataset,
2946                                dbuf, DNS_SECTION_AUTHORITY);
2947
2948                 if (ispositive)
2949                         goto cleanup;
2950
2951                 /*
2952                  * Replace resources which were consumed by query_addrrset.
2953                  */
2954                 if (fname == NULL) {
2955                         dbuf = query_getnamebuf(client);
2956                         if (dbuf == NULL)
2957                                 goto cleanup;
2958                         fname = query_newname(client, dbuf, &b);
2959                 }
2960
2961                 if (rdataset == NULL)
2962                         rdataset = query_newrdataset(client);
2963                 else if (dns_rdataset_isassociated(rdataset))
2964                         dns_rdataset_disassociate(rdataset);
2965
2966                 if (sigrdataset == NULL)
2967                         sigrdataset = query_newrdataset(client);
2968                 else if (dns_rdataset_isassociated(sigrdataset))
2969                         dns_rdataset_disassociate(sigrdataset);
2970
2971                 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
2972                         goto cleanup;
2973                 /*
2974                  * Add the no wildcard proof.
2975                  */
2976                 result = dns_name_concatenate(dns_wildcardname,
2977                                               cname, wname, NULL);
2978                 if (result != ISC_R_SUCCESS)
2979                         goto cleanup;
2980
2981                 query_findclosestnsec3(wname, db, NULL, client, rdataset,
2982                                        sigrdataset, fname, ISC_FALSE, NULL);
2983                 if (!dns_rdataset_isassociated(rdataset))
2984                         goto cleanup;
2985                 query_addrrset(client, &fname, &rdataset, &sigrdataset,
2986                                dbuf, DNS_SECTION_AUTHORITY);
2987
2988                 goto cleanup;
2989         } else if (result == DNS_R_NXDOMAIN) {
2990                 if (!ispositive)
2991                         result = dns_rdataset_first(rdataset);
2992                 if (result == ISC_R_SUCCESS) {
2993                         dns_rdataset_current(rdataset, &rdata);
2994                         result = dns_rdata_tostruct(&rdata, &nsec, NULL);
2995                 }
2996                 if (result == ISC_R_SUCCESS) {
2997                         (void)dns_name_fullcompare(name, fname, &order,
2998                                                    &olabels);
2999                         (void)dns_name_fullcompare(name, &nsec.next, &order,
3000                                                    &nlabels);
3001                         /*
3002                          * Check for a pathological condition created when
3003                          * serving some malformed signed zones and bail out.
3004                          */
3005                         if (dns_name_countlabels(name) == nlabels)
3006                                 goto cleanup;
3007
3008                         if (olabels > nlabels)
3009                                 dns_name_split(name, olabels, NULL, wname);
3010                         else
3011                                 dns_name_split(name, nlabels, NULL, wname);
3012                         result = dns_name_concatenate(dns_wildcardname,
3013                                                       wname, wname, NULL);
3014                         if (result == ISC_R_SUCCESS)
3015                                 have_wname = ISC_TRUE;
3016                         dns_rdata_freestruct(&nsec);
3017                 }
3018                 query_addrrset(client, &fname, &rdataset, &sigrdataset,
3019                                dbuf, DNS_SECTION_AUTHORITY);
3020         }
3021         if (rdataset != NULL)
3022                 query_putrdataset(client, &rdataset);
3023         if (sigrdataset != NULL)
3024                 query_putrdataset(client, &sigrdataset);
3025         if (fname != NULL)
3026                 query_releasename(client, &fname);
3027         if (have_wname) {
3028                 ispositive = ISC_TRUE;  /* prevent loop */
3029                 if (!dns_name_equal(name, wname)) {
3030                         name = wname;
3031                         goto again;
3032                 }
3033         }
3034  cleanup:
3035         if (rdataset != NULL)
3036                 query_putrdataset(client, &rdataset);
3037         if (sigrdataset != NULL)
3038                 query_putrdataset(client, &sigrdataset);
3039         if (fname != NULL)
3040                 query_releasename(client, &fname);
3041 }
3042
3043 static void
3044 query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db,
3045                      dns_dbversion_t *version, dns_name_t **namep,
3046                      dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp)
3047 {
3048         dns_name_t *name;
3049         dns_rdataset_t *sigrdataset;
3050         dns_rdata_t sigrdata;
3051         dns_rdata_rrsig_t sig;
3052         unsigned int labels;
3053         isc_buffer_t *dbuf, b;
3054         dns_name_t *fname;
3055         isc_result_t result;
3056
3057         name = *namep;
3058         if ((name->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
3059                 query_addrrset(client, namep, rdatasetp, sigrdatasetp,
3060                                NULL, DNS_SECTION_AUTHORITY);
3061                 return;
3062         }
3063
3064         if (sigrdatasetp == NULL)
3065                 return;
3066
3067         sigrdataset = *sigrdatasetp;
3068         if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
3069                 return;
3070         result = dns_rdataset_first(sigrdataset);
3071         if (result != ISC_R_SUCCESS)
3072                 return;
3073         dns_rdata_init(&sigrdata);
3074         dns_rdataset_current(sigrdataset, &sigrdata);
3075         result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
3076         if (result != ISC_R_SUCCESS)
3077                 return;
3078
3079         labels = dns_name_countlabels(name);
3080         if ((unsigned int)sig.labels + 1 >= labels)
3081                 return;
3082
3083         /* XXX */
3084         query_addwildcardproof(client, db, version, client->query.qname,
3085                                ISC_TRUE);
3086
3087         /*
3088          * We'll need some resources...
3089          */
3090         dbuf = query_getnamebuf(client);
3091         if (dbuf == NULL)
3092                 return;
3093         fname = query_newname(client, dbuf, &b);
3094         if (fname == NULL)
3095                 return;
3096         dns_name_split(name, sig.labels + 1, NULL, fname);
3097         /* This will succeed, since we've stripped labels. */
3098         RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,
3099                                            NULL) == ISC_R_SUCCESS);
3100         query_addrrset(client, &fname, rdatasetp, sigrdatasetp,
3101                        dbuf, DNS_SECTION_AUTHORITY);
3102 }
3103
3104 static void
3105 query_resume(isc_task_t *task, isc_event_t *event) {
3106         dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
3107         dns_fetch_t *fetch;
3108         ns_client_t *client;
3109         isc_boolean_t fetch_canceled, client_shuttingdown;
3110         isc_result_t result;
3111         isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_EERRORS;
3112         int errorloglevel;
3113
3114         /*
3115          * Resume a query after recursion.
3116          */
3117
3118         UNUSED(task);
3119
3120         REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
3121         client = devent->ev_arg;
3122         REQUIRE(NS_CLIENT_VALID(client));
3123         REQUIRE(task == client->task);
3124         REQUIRE(RECURSING(client));
3125
3126         LOCK(&client->query.fetchlock);
3127         if (client->query.fetch != NULL) {
3128                 /*
3129                  * This is the fetch we've been waiting for.
3130                  */
3131                 INSIST(devent->fetch == client->query.fetch);
3132                 client->query.fetch = NULL;
3133                 fetch_canceled = ISC_FALSE;
3134                 /*
3135                  * Update client->now.
3136                  */
3137                 isc_stdtime_get(&client->now);
3138         } else {
3139                 /*
3140                  * This is a fetch completion event for a canceled fetch.
3141                  * Clean up and don't resume the find.
3142                  */
3143                 fetch_canceled = ISC_TRUE;
3144         }
3145         UNLOCK(&client->query.fetchlock);
3146         INSIST(client->query.fetch == NULL);
3147
3148         client->query.attributes &= ~NS_QUERYATTR_RECURSING;
3149         fetch = devent->fetch;
3150         devent->fetch = NULL;
3151
3152         /*
3153          * If this client is shutting down, or this transaction
3154          * has timed out, do not resume the find.
3155          */
3156         client_shuttingdown = ns_client_shuttingdown(client);
3157         if (fetch_canceled || client_shuttingdown) {
3158                 if (devent->node != NULL)
3159                         dns_db_detachnode(devent->db, &devent->node);
3160                 if (devent->db != NULL)
3161                         dns_db_detach(&devent->db);
3162                 query_putrdataset(client, &devent->rdataset);
3163                 if (devent->sigrdataset != NULL)
3164                         query_putrdataset(client, &devent->sigrdataset);
3165                 isc_event_free(&event);
3166                 if (fetch_canceled)
3167                         query_error(client, DNS_R_SERVFAIL, __LINE__);
3168                 else
3169                         query_next(client, ISC_R_CANCELED);
3170                 /*
3171                  * This may destroy the client.
3172                  */
3173                 ns_client_detach(&client);
3174         } else {
3175                 result = query_find(client, devent, 0);
3176                 if (result != ISC_R_SUCCESS) {
3177                         if (result == DNS_R_SERVFAIL)
3178                                 errorloglevel = ISC_LOG_DEBUG(2);
3179                         else
3180                                 errorloglevel = ISC_LOG_DEBUG(4);
3181                         if (isc_log_wouldlog(ns_g_lctx, errorloglevel)) {
3182                                 dns_resolver_logfetch(fetch, ns_g_lctx,
3183                                                       logcategory,
3184                                                       NS_LOGMODULE_QUERY,
3185                                                       errorloglevel, ISC_FALSE);
3186                         }
3187                 }
3188         }
3189
3190         dns_resolver_destroyfetch(&fetch);
3191 }
3192
3193 static isc_result_t
3194 query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
3195               dns_rdataset_t *nameservers, isc_boolean_t resuming)
3196 {
3197         isc_result_t result;
3198         dns_rdataset_t *rdataset, *sigrdataset;
3199         isc_sockaddr_t *peeraddr;
3200
3201         if (!resuming)
3202                 inc_stats(client, dns_nsstatscounter_recursion);
3203
3204         /*
3205          * We are about to recurse, which means that this client will
3206          * be unavailable for serving new requests for an indeterminate
3207          * amount of time.  If this client is currently responsible
3208          * for handling incoming queries, set up a new client
3209          * object to handle them while we are waiting for a
3210          * response.  There is no need to replace TCP clients
3211          * because those have already been replaced when the
3212          * connection was accepted (if allowed by the TCP quota).
3213          */
3214         if (client->recursionquota == NULL) {
3215                 result = isc_quota_attach(&ns_g_server->recursionquota,
3216                                           &client->recursionquota);
3217                 if  (result == ISC_R_SOFTQUOTA) {
3218                         static isc_stdtime_t last = 0;
3219                         isc_stdtime_t now;
3220                         isc_stdtime_get(&now);
3221                         if (now != last) {
3222                                 last = now;
3223                                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3224                                               NS_LOGMODULE_QUERY,
3225                                               ISC_LOG_WARNING,
3226                                               "recursive-clients soft limit "
3227                                               "exceeded, aborting oldest query");
3228                         }
3229                         ns_client_killoldestquery(client);
3230                         result = ISC_R_SUCCESS;
3231                 } else if (result == ISC_R_QUOTA) {
3232                         static isc_stdtime_t last = 0;
3233                         isc_stdtime_t now;
3234                         isc_stdtime_get(&now);
3235                         if (now != last) {
3236                                 last = now;
3237                                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3238                                               NS_LOGMODULE_QUERY,
3239                                               ISC_LOG_WARNING,
3240                                               "no more recursive clients: %s",
3241                                               isc_result_totext(result));
3242                         }
3243                         ns_client_killoldestquery(client);
3244                 }
3245                 if (result == ISC_R_SUCCESS && !client->mortal &&
3246                     (client->attributes & NS_CLIENTATTR_TCP) == 0) {
3247                         result = ns_client_replace(client);
3248                         if (result != ISC_R_SUCCESS) {
3249                                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3250                                               NS_LOGMODULE_QUERY,
3251                                               ISC_LOG_WARNING,
3252                                               "ns_client_replace() failed: %s",
3253                                               isc_result_totext(result));
3254                                 isc_quota_detach(&client->recursionquota);
3255                         }
3256                 }
3257                 if (result != ISC_R_SUCCESS)
3258                         return (result);
3259                 ns_client_recursing(client);
3260         }
3261
3262         /*
3263          * Invoke the resolver.
3264          */
3265         REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
3266         REQUIRE(client->query.fetch == NULL);
3267
3268         rdataset = query_newrdataset(client);
3269         if (rdataset == NULL)
3270                 return (ISC_R_NOMEMORY);
3271         if (WANTDNSSEC(client)) {
3272                 sigrdataset = query_newrdataset(client);
3273                 if (sigrdataset == NULL) {
3274                         query_putrdataset(client, &rdataset);
3275                         return (ISC_R_NOMEMORY);
3276                 }
3277         } else
3278                 sigrdataset = NULL;
3279
3280         if (client->query.timerset == ISC_FALSE)
3281                 ns_client_settimeout(client, 60);
3282         if ((client->attributes & NS_CLIENTATTR_TCP) == 0)
3283                 peeraddr = &client->peeraddr;
3284         else
3285                 peeraddr = NULL;
3286         result = dns_resolver_createfetch2(client->view->resolver,
3287                                            client->query.qname,
3288                                            qtype, qdomain, nameservers,
3289                                            NULL, peeraddr, client->message->id,
3290                                            client->query.fetchoptions,
3291                                            client->task,
3292                                            query_resume, client,
3293                                            rdataset, sigrdataset,
3294                                            &client->query.fetch);
3295
3296         if (result == ISC_R_SUCCESS) {
3297                 /*
3298                  * Record that we're waiting for an event.  A client which
3299                  * is shutting down will not be destroyed until all the
3300                  * events have been received.
3301                  */
3302         } else {
3303                 query_putrdataset(client, &rdataset);
3304                 if (sigrdataset != NULL)
3305                         query_putrdataset(client, &sigrdataset);
3306         }
3307
3308         return (result);
3309 }
3310
3311 #define MAX_RESTARTS 16
3312
3313 #define QUERY_ERROR(r) \
3314 do { \
3315         eresult = r; \
3316         want_restart = ISC_FALSE; \
3317         line = __LINE__; \
3318 } while (0)
3319
3320 /*
3321  * Extract a network address from the RDATA of an A or AAAA
3322  * record.
3323  *
3324  * Returns:
3325  *      ISC_R_SUCCESS
3326  *      ISC_R_NOTIMPLEMENTED    The rdata is not a known address type.
3327  */
3328 static isc_result_t
3329 rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
3330         struct in_addr ina;
3331         struct in6_addr in6a;
3332
3333         switch (rdata->type) {
3334         case dns_rdatatype_a:
3335                 INSIST(rdata->length == 4);
3336                 memcpy(&ina.s_addr, rdata->data, 4);
3337                 isc_netaddr_fromin(netaddr, &ina);
3338                 return (ISC_R_SUCCESS);
3339         case dns_rdatatype_aaaa:
3340                 INSIST(rdata->length == 16);
3341                 memcpy(in6a.s6_addr, rdata->data, 16);
3342                 isc_netaddr_fromin6(netaddr, &in6a);
3343                 return (ISC_R_SUCCESS);
3344         default:
3345                 return (ISC_R_NOTIMPLEMENTED);
3346         }
3347 }
3348
3349 /*
3350  * Find the sort order of 'rdata' in the topology-like
3351  * ACL forming the second element in a 2-element top-level
3352  * sortlist statement.
3353  */
3354 static int
3355 query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) {
3356         isc_netaddr_t netaddr;
3357
3358         if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
3359                 return (INT_MAX);
3360         return (ns_sortlist_addrorder2(&netaddr, arg));
3361 }
3362
3363 /*
3364  * Find the sort order of 'rdata' in the matching element
3365  * of a 1-element top-level sortlist statement.
3366  */
3367 static int
3368 query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) {
3369         isc_netaddr_t netaddr;
3370
3371         if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
3372                 return (INT_MAX);
3373         return (ns_sortlist_addrorder1(&netaddr, arg));
3374 }
3375
3376 /*
3377  * Find the sortlist statement that applies to 'client' and set up
3378  * the sortlist info in in client->message appropriately.
3379  */
3380 static void
3381 setup_query_sortlist(ns_client_t *client) {
3382         isc_netaddr_t netaddr;
3383         dns_rdatasetorderfunc_t order = NULL;
3384         const void *order_arg = NULL;
3385
3386         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
3387         switch (ns_sortlist_setup(client->view->sortlist,
3388                                &netaddr, &order_arg)) {
3389         case NS_SORTLISTTYPE_1ELEMENT:
3390                 order = query_sortlist_order_1element;
3391                 break;
3392         case NS_SORTLISTTYPE_2ELEMENT:
3393                 order = query_sortlist_order_2element;
3394                 break;
3395         case NS_SORTLISTTYPE_NONE:
3396                 order = NULL;
3397                 break;
3398         default:
3399                 INSIST(0);
3400                 break;
3401         }
3402         dns_message_setsortorder(client->message, order, order_arg);
3403 }
3404
3405 static void
3406 query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
3407         isc_buffer_t *dbuf, b;
3408         dns_name_t *fname;
3409         dns_rdataset_t *neg, *negsig;
3410         isc_result_t result = ISC_R_NOMEMORY;
3411
3412         CTRACE("query_addnoqnameproof");
3413
3414         fname = NULL;
3415         neg = NULL;
3416         negsig = NULL;
3417
3418         dbuf = query_getnamebuf(client);
3419         if (dbuf == NULL)
3420                 goto cleanup;
3421         fname = query_newname(client, dbuf, &b);
3422         neg = query_newrdataset(client);
3423         negsig = query_newrdataset(client);
3424         if (fname == NULL || neg == NULL || negsig == NULL)
3425                 goto cleanup;
3426
3427         result = dns_rdataset_getnoqname(rdataset, fname, neg, negsig);
3428         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3429
3430         query_addrrset(client, &fname, &neg, &negsig, dbuf,
3431                        DNS_SECTION_AUTHORITY);
3432
3433         if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) == 0)
3434                 goto cleanup;
3435
3436         if (fname == NULL) {
3437                 dbuf = query_getnamebuf(client);
3438                 if (dbuf == NULL)
3439                         goto cleanup;
3440                 fname = query_newname(client, dbuf, &b);
3441         }
3442         if (neg == NULL)
3443                 neg = query_newrdataset(client);
3444         else if (dns_rdataset_isassociated(neg))
3445                 dns_rdataset_disassociate(neg);
3446         if (negsig == NULL)
3447                 negsig = query_newrdataset(client);
3448         else if (dns_rdataset_isassociated(negsig))
3449                 dns_rdataset_disassociate(negsig);
3450         if (fname == NULL || neg == NULL || negsig == NULL)
3451                 goto cleanup;
3452         result = dns_rdataset_getclosest(rdataset, fname, neg, negsig);
3453         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3454
3455         query_addrrset(client, &fname, &neg, &negsig, dbuf,
3456                        DNS_SECTION_AUTHORITY);
3457
3458  cleanup:
3459         if (neg != NULL)
3460                 query_putrdataset(client, &neg);
3461         if (negsig != NULL)
3462                 query_putrdataset(client, &negsig);
3463         if (fname != NULL)
3464                 query_releasename(client, &fname);
3465 }
3466
3467 static inline void
3468 answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
3469         dns_name_t *name;
3470         dns_message_t *msg;
3471         dns_section_t section = DNS_SECTION_ADDITIONAL;
3472         dns_rdataset_t *rdataset = NULL;
3473
3474         msg = client->message;
3475         for (name = ISC_LIST_HEAD(msg->sections[section]);
3476              name != NULL;
3477              name = ISC_LIST_NEXT(name, link))
3478                 if (dns_name_equal(name, client->query.qname)) {
3479                         for (rdataset = ISC_LIST_HEAD(name->list);
3480                              rdataset != NULL;
3481                              rdataset = ISC_LIST_NEXT(rdataset, link))
3482                                 if (rdataset->type == qtype)
3483                                         break;
3484                         break;
3485                 }
3486         if (rdataset != NULL) {
3487                 ISC_LIST_UNLINK(msg->sections[section], name, link);
3488                 ISC_LIST_PREPEND(msg->sections[section], name, link);
3489                 ISC_LIST_UNLINK(name->list, rdataset, link);
3490                 ISC_LIST_PREPEND(name->list, rdataset, link);
3491                 rdataset->attributes |= DNS_RDATASETATTR_REQUIREDGLUE;
3492         }
3493 }
3494
3495 #define NS_NAME_INIT(A,B) \
3496          { \
3497                 DNS_NAME_MAGIC, \
3498                 A, sizeof(A), sizeof(B), \
3499                 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
3500                 B, NULL, { (void *)-1, (void *)-1}, \
3501                 {NULL, NULL} \
3502         }
3503
3504 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
3505 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
3506 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
3507
3508 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
3509
3510 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
3511 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
3512 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
3513 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
3514 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
3515 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
3516 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
3517 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
3518 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
3519 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
3520 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
3521 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
3522 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
3523 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
3524 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
3525 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
3526
3527 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
3528
3529 static dns_name_t rfc1918names[] = {
3530         NS_NAME_INIT(inaddr10, inaddr10_offsets),
3531         NS_NAME_INIT(inaddr16172, inaddr172_offsets),
3532         NS_NAME_INIT(inaddr17172, inaddr172_offsets),
3533         NS_NAME_INIT(inaddr18172, inaddr172_offsets),
3534         NS_NAME_INIT(inaddr19172, inaddr172_offsets),
3535         NS_NAME_INIT(inaddr20172, inaddr172_offsets),
3536         NS_NAME_INIT(inaddr21172, inaddr172_offsets),
3537         NS_NAME_INIT(inaddr22172, inaddr172_offsets),
3538         NS_NAME_INIT(inaddr23172, inaddr172_offsets),
3539         NS_NAME_INIT(inaddr24172, inaddr172_offsets),
3540         NS_NAME_INIT(inaddr25172, inaddr172_offsets),
3541         NS_NAME_INIT(inaddr26172, inaddr172_offsets),
3542         NS_NAME_INIT(inaddr27172, inaddr172_offsets),
3543         NS_NAME_INIT(inaddr28172, inaddr172_offsets),
3544         NS_NAME_INIT(inaddr29172, inaddr172_offsets),
3545         NS_NAME_INIT(inaddr30172, inaddr172_offsets),
3546         NS_NAME_INIT(inaddr31172, inaddr172_offsets),
3547         NS_NAME_INIT(inaddr168192, inaddr192_offsets)
3548 };
3549
3550
3551 static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
3552 static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org";
3553
3554 static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
3555 static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
3556
3557 static dns_name_t prisoner = NS_NAME_INIT(prisoner_data, prisoner_offsets);
3558 static dns_name_t hostmaster = NS_NAME_INIT(hostmaster_data, hostmaster_offsets);
3559
3560 static void
3561 warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
3562         unsigned int i;
3563         dns_rdata_t rdata = DNS_RDATA_INIT;
3564         dns_rdata_soa_t soa;
3565         dns_rdataset_t found;
3566         isc_result_t result;
3567
3568         for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) {
3569                 if (dns_name_issubdomain(fname, &rfc1918names[i])) {
3570                         dns_rdataset_init(&found);
3571                         result = dns_ncache_getrdataset(rdataset,
3572                                                         &rfc1918names[i],
3573                                                         dns_rdatatype_soa,
3574                                                         &found);
3575                         if (result != ISC_R_SUCCESS)
3576                                 return;
3577
3578                         result = dns_rdataset_first(&found);
3579                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3580                         dns_rdataset_current(&found, &rdata);
3581                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
3582                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3583                         if (dns_name_equal(&soa.origin, &prisoner) &&
3584                             dns_name_equal(&soa.contact, &hostmaster)) {
3585                                 char buf[DNS_NAME_FORMATSIZE];
3586                                 dns_name_format(fname, buf, sizeof(buf));
3587                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
3588                                               NS_LOGMODULE_QUERY,
3589                                               ISC_LOG_WARNING,
3590                                               "RFC 1918 response from "
3591                                               "Internet for %s", buf);
3592                         }
3593                         dns_rdataset_disassociate(&found);
3594                         return;
3595                 }
3596         }
3597 }
3598
3599 static void
3600 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
3601                        dns_dbversion_t *version, ns_client_t *client,
3602                        dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3603                        dns_name_t *fname, isc_boolean_t exact,
3604                        dns_name_t *found)
3605 {
3606         unsigned char salt[256];
3607         size_t salt_length = sizeof(salt);
3608         isc_uint16_t iterations;
3609         isc_result_t result;
3610         unsigned int dboptions;
3611         dns_fixedname_t fixed;
3612         dns_hash_t hash;
3613         dns_name_t name;
3614         int order;
3615         unsigned int count;
3616         dns_rdata_nsec3_t nsec3;
3617         dns_rdata_t rdata = DNS_RDATA_INIT;
3618         isc_boolean_t optout;
3619
3620         salt_length = sizeof(salt);
3621         result = dns_db_getnsec3parameters(db, version, &hash, NULL,
3622                                            &iterations, salt, &salt_length);
3623         if (result != ISC_R_SUCCESS)
3624                 return;
3625
3626         dns_name_init(&name, NULL);
3627         dns_name_clone(qname, &name);
3628
3629         /*
3630          * Map unknown algorithm to known value.
3631          */
3632         if (hash == DNS_NSEC3_UNKNOWNALG)
3633                 hash = 1;
3634
3635  again:
3636         dns_fixedname_init(&fixed);
3637         result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
3638                                     dns_db_origin(db), hash,
3639                                     iterations, salt, salt_length);
3640         if (result != ISC_R_SUCCESS)
3641                 return;
3642
3643         dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
3644         result = dns_db_find(db, dns_fixedname_name(&fixed), version,
3645                              dns_rdatatype_nsec3, dboptions, client->now,
3646                              NULL, fname, rdataset, sigrdataset);
3647
3648         if (result == DNS_R_NXDOMAIN) {
3649                 if (!dns_rdataset_isassociated(rdataset)) {
3650                         return;
3651                 }
3652                 result = dns_rdataset_first(rdataset);
3653                 INSIST(result == ISC_R_SUCCESS);
3654                 dns_rdataset_current(rdataset, &rdata);
3655                 dns_rdata_tostruct(&rdata, &nsec3, NULL);
3656                 dns_rdata_reset(&rdata);
3657                 optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
3658                 if (found != NULL && optout &&
3659                     dns_name_fullcompare(&name, dns_db_origin(db), &order,
3660                                          &count) == dns_namereln_subdomain) {
3661                         dns_rdataset_disassociate(rdataset);
3662                         if (dns_rdataset_isassociated(sigrdataset))
3663                                 dns_rdataset_disassociate(sigrdataset);
3664                         count = dns_name_countlabels(&name) - 1;
3665                         dns_name_getlabelsequence(&name, 1, count, &name);
3666                         ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
3667                                       NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3),
3668                                       "looking for closest provable encloser");
3669                         goto again;
3670                 }
3671                 if (exact)
3672                         ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
3673                                       NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
3674                                       "expected a exact match NSEC3, got "
3675                                       "a covering record");
3676
3677         } else if (result != ISC_R_SUCCESS) {
3678                 return;
3679         } else if (!exact)
3680                 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
3681                               NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
3682                               "expected covering NSEC3, got an exact match");
3683         if (found != NULL)
3684                 dns_name_copy(&name, found, NULL);
3685         return;
3686 }
3687
3688 /*
3689  * Do the bulk of query processing for the current query of 'client'.
3690  * If 'event' is non-NULL, we are returning from recursion and 'qtype'
3691  * is ignored.  Otherwise, 'qtype' is the query type.
3692  */
3693 static isc_result_t
3694 query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
3695 {
3696         dns_db_t *db, *zdb;
3697         dns_dbnode_t *node;
3698         dns_rdatatype_t type;
3699         dns_name_t *fname, *zfname, *tname, *prefix;
3700         dns_rdataset_t *rdataset, *trdataset;
3701         dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset;
3702         dns_rdataset_t **sigrdatasetp;
3703         dns_rdata_t rdata = DNS_RDATA_INIT;
3704         dns_rdatasetiter_t *rdsiter;
3705         isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof;
3706         unsigned int n, nlabels;
3707         dns_namereln_t namereln;
3708         int order;
3709         isc_buffer_t *dbuf;
3710         isc_buffer_t b;
3711         isc_result_t result, eresult;
3712         dns_fixedname_t fixed;
3713         dns_fixedname_t wildcardname;
3714         dns_dbversion_t *version, *zversion;
3715         dns_zone_t *zone;
3716         dns_rdata_cname_t cname;
3717         dns_rdata_dname_t dname;
3718         unsigned int options;
3719         isc_boolean_t empty_wild;
3720         dns_rdataset_t *noqname;
3721         isc_boolean_t resuming;
3722         int line = -1;
3723
3724         CTRACE("query_find");
3725
3726         /*
3727          * One-time initialization.
3728          *
3729          * It's especially important to initialize anything that the cleanup
3730          * code might cleanup.
3731          */
3732
3733         eresult = ISC_R_SUCCESS;
3734         fname = NULL;
3735         zfname = NULL;
3736         rdataset = NULL;
3737         zrdataset = NULL;
3738         sigrdataset = NULL;
3739         zsigrdataset = NULL;
3740         zversion = NULL;
3741         node = NULL;
3742         db = NULL;
3743         zdb = NULL;
3744         version = NULL;
3745         zone = NULL;
3746         need_wildcardproof = ISC_FALSE;
3747         empty_wild = ISC_FALSE;
3748         options = 0;
3749         resuming = ISC_FALSE;
3750         is_zone = ISC_FALSE;
3751
3752         if (event != NULL) {
3753                 /*
3754                  * We're returning from recursion.  Restore the query context
3755                  * and resume.
3756                  */
3757
3758                 want_restart = ISC_FALSE;
3759                 authoritative = ISC_FALSE;
3760
3761                 qtype = event->qtype;
3762                 if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
3763                         type = dns_rdatatype_any;
3764                 else
3765                         type = qtype;
3766                 db = event->db;
3767                 node = event->node;
3768                 rdataset = event->rdataset;
3769                 sigrdataset = event->sigrdataset;
3770
3771                 /*
3772                  * We'll need some resources...
3773                  */
3774                 dbuf = query_getnamebuf(client);
3775                 if (dbuf == NULL) {
3776                         QUERY_ERROR(DNS_R_SERVFAIL);
3777                         goto cleanup;
3778                 }
3779                 fname = query_newname(client, dbuf, &b);
3780                 if (fname == NULL) {
3781                         QUERY_ERROR(DNS_R_SERVFAIL);
3782                         goto cleanup;
3783                 }
3784                 tname = dns_fixedname_name(&event->foundname);
3785                 result = dns_name_copy(tname, fname, NULL);
3786                 if (result != ISC_R_SUCCESS) {
3787                         QUERY_ERROR(DNS_R_SERVFAIL);
3788                         goto cleanup;
3789                 }
3790
3791                 result = event->result;
3792                 resuming = ISC_TRUE;
3793
3794                 goto resume;
3795         }
3796
3797         /*
3798          * Not returning from recursion.
3799          */
3800
3801         /*
3802          * If it's a SIG query, we'll iterate the node.
3803          */
3804         if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
3805                 type = dns_rdatatype_any;
3806         else
3807                 type = qtype;
3808
3809  restart:
3810         CTRACE("query_find: restart");
3811         want_restart = ISC_FALSE;
3812         authoritative = ISC_FALSE;
3813         version = NULL;
3814         need_wildcardproof = ISC_FALSE;
3815
3816         if (client->view->checknames &&
3817             !dns_rdata_checkowner(client->query.qname,
3818                                   client->message->rdclass,
3819                                   qtype, ISC_FALSE)) {
3820                 char namebuf[DNS_NAME_FORMATSIZE];
3821                 char typename[DNS_RDATATYPE_FORMATSIZE];
3822                 char classname[DNS_RDATACLASS_FORMATSIZE];
3823
3824                 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
3825                 dns_rdatatype_format(qtype, typename, sizeof(typename));
3826                 dns_rdataclass_format(client->message->rdclass, classname,
3827                                       sizeof(classname));
3828                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
3829                               NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
3830                               "check-names failure %s/%s/%s", namebuf,
3831                               typename, classname);
3832                 QUERY_ERROR(DNS_R_REFUSED);
3833                 goto cleanup;
3834         }
3835
3836         /*
3837          * First we must find the right database.
3838          */
3839         options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */
3840         if (dns_rdatatype_atparent(qtype) &&
3841             !dns_name_equal(client->query.qname, dns_rootname))
3842                 options |= DNS_GETDB_NOEXACT;
3843         result = query_getdb(client, client->query.qname, qtype, options,
3844                              &zone, &db, &version, &is_zone);
3845         if ((result != ISC_R_SUCCESS || !is_zone) && !RECURSIONOK(client) &&
3846             (options & DNS_GETDB_NOEXACT) != 0 && qtype == dns_rdatatype_ds) {
3847                 /*
3848                  * Look to see if we are authoritative for the
3849                  * child zone if the query type is DS.
3850                  */
3851                 dns_db_t *tdb = NULL;
3852                 dns_zone_t *tzone = NULL;
3853                 dns_dbversion_t *tversion = NULL;
3854                 isc_result_t tresult;
3855
3856                 tresult = query_getzonedb(client, client->query.qname, qtype,
3857                                          DNS_GETDB_PARTIAL, &tzone, &tdb,
3858                                          &tversion);
3859                 if (tresult == ISC_R_SUCCESS) {
3860                         options &= ~DNS_GETDB_NOEXACT;
3861                         query_putrdataset(client, &rdataset);
3862                         if (db != NULL)
3863                                 dns_db_detach(&db);
3864                         if (zone != NULL)
3865                                 dns_zone_detach(&zone);
3866                         version = tversion;
3867                         db = tdb;
3868                         zone = tzone;
3869                         is_zone = ISC_TRUE;
3870                         result = ISC_R_SUCCESS;
3871                 } else {
3872                         if (tdb != NULL)
3873                                 dns_db_detach(&tdb);
3874                         if (tzone != NULL)
3875                                 dns_zone_detach(&tzone);
3876                 }
3877         }
3878         if (result != ISC_R_SUCCESS) {
3879                 if (result == DNS_R_REFUSED) {
3880                         if (WANTRECURSION(client)) {
3881                                 inc_stats(client,
3882                                           dns_nsstatscounter_recurserej);
3883                         } else
3884                                 inc_stats(client, dns_nsstatscounter_authrej);
3885                         if (!PARTIALANSWER(client))
3886                                 QUERY_ERROR(DNS_R_REFUSED);
3887                 } else
3888                         QUERY_ERROR(DNS_R_SERVFAIL);
3889                 goto cleanup;
3890         }
3891
3892         if (is_zone)
3893                 authoritative = ISC_TRUE;
3894
3895         if (event == NULL && client->query.restarts == 0) {
3896                 if (is_zone) {
3897 #ifdef DLZ
3898                         if (zone != NULL) {
3899                                 /*
3900                                  * if is_zone = true, zone = NULL then this is
3901                                  * a DLZ zone.  Don't attempt to attach zone.
3902                                  */
3903 #endif
3904                                 dns_zone_attach(zone, &client->query.authzone);
3905 #ifdef DLZ
3906                         }
3907 #endif
3908                         dns_db_attach(db, &client->query.authdb);
3909                 }
3910                 client->query.authdbset = ISC_TRUE;
3911         }
3912
3913  db_find:
3914         CTRACE("query_find: db_find");
3915         /*
3916          * We'll need some resources...
3917          */
3918         dbuf = query_getnamebuf(client);
3919         if (dbuf == NULL) {
3920                 QUERY_ERROR(DNS_R_SERVFAIL);
3921                 goto cleanup;
3922         }
3923         fname = query_newname(client, dbuf, &b);
3924         rdataset = query_newrdataset(client);
3925         if (fname == NULL || rdataset == NULL) {
3926                 QUERY_ERROR(DNS_R_SERVFAIL);
3927                 goto cleanup;
3928         }
3929         if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) {
3930                 sigrdataset = query_newrdataset(client);
3931                 if (sigrdataset == NULL) {
3932                         QUERY_ERROR(DNS_R_SERVFAIL);
3933                         goto cleanup;
3934                 }
3935         }
3936
3937         /*
3938          * Now look for an answer in the database.
3939          */
3940         result = dns_db_find(db, client->query.qname, version, type,
3941                              client->query.dboptions, client->now,
3942                              &node, fname, rdataset, sigrdataset);
3943
3944  resume:
3945         CTRACE("query_find: resume");
3946         switch (result) {
3947         case ISC_R_SUCCESS:
3948                 /*
3949                  * This case is handled in the main line below.
3950                  */
3951                 break;
3952         case DNS_R_GLUE:
3953         case DNS_R_ZONECUT:
3954                 /*
3955                  * These cases are handled in the main line below.
3956                  */
3957                 INSIST(is_zone);
3958                 authoritative = ISC_FALSE;
3959                 break;
3960         case ISC_R_NOTFOUND:
3961                 /*
3962                  * The cache doesn't even have the root NS.  Get them from
3963                  * the hints DB.
3964                  */
3965                 INSIST(!is_zone);
3966                 if (db != NULL)
3967                         dns_db_detach(&db);
3968
3969                 if (client->view->hints == NULL) {
3970                         /* We have no hints. */
3971                         result = ISC_R_FAILURE;
3972                 } else {
3973                         dns_db_attach(client->view->hints, &db);
3974                         result = dns_db_find(db, dns_rootname,
3975                                              NULL, dns_rdatatype_ns,
3976                                              0, client->now, &node, fname,
3977                                              rdataset, sigrdataset);
3978                 }
3979                 if (result != ISC_R_SUCCESS) {
3980                         /*
3981                          * Nonsensical root hints may require cleanup.
3982                          */
3983                         if (dns_rdataset_isassociated(rdataset))
3984                                 dns_rdataset_disassociate(rdataset);
3985                         if (sigrdataset != NULL &&
3986                             dns_rdataset_isassociated(sigrdataset))
3987                                 dns_rdataset_disassociate(sigrdataset);
3988                         if (node != NULL)
3989                                 dns_db_detachnode(db, &node);
3990
3991                         /*
3992                          * We don't have any root server hints, but
3993                          * we may have working forwarders, so try to
3994                          * recurse anyway.
3995                          */
3996                         if (RECURSIONOK(client)) {
3997                                 result = query_recurse(client, qtype,
3998                                                        NULL, NULL, resuming);
3999                                 if (result == ISC_R_SUCCESS)
4000                                         client->query.attributes |=
4001                                                 NS_QUERYATTR_RECURSING;
4002                                 else if (result == DNS_R_DUPLICATE ||
4003                                          result == DNS_R_DROP) {
4004                                         /* Duplicate query. */
4005                                         QUERY_ERROR(result);
4006                                 } else {
4007                                         /* Unable to recurse. */
4008                                         QUERY_ERROR(DNS_R_SERVFAIL);
4009                                 }
4010                                 goto cleanup;
4011                         } else {
4012                                 /* Unable to give root server referral. */
4013                                 QUERY_ERROR(DNS_R_SERVFAIL);
4014                                 goto cleanup;
4015                         }
4016                 }
4017                 /*
4018                  * XXXRTH  We should trigger root server priming here.
4019                  */
4020                 /* FALLTHROUGH */
4021         case DNS_R_DELEGATION:
4022                 authoritative = ISC_FALSE;
4023                 if (is_zone) {
4024                         /*
4025                          * Look to see if we are authoritative for the
4026                          * child zone if the query type is DS.
4027                          */
4028                         if (!RECURSIONOK(client) &&
4029                             (options & DNS_GETDB_NOEXACT) != 0 &&
4030                             qtype == dns_rdatatype_ds) {
4031                                 dns_db_t *tdb = NULL;
4032                                 dns_zone_t *tzone = NULL;
4033                                 dns_dbversion_t *tversion = NULL;
4034                                 result = query_getzonedb(client,
4035                                                          client->query.qname,
4036                                                          qtype,
4037                                                          DNS_GETDB_PARTIAL,
4038                                                          &tzone, &tdb,
4039                                                          &tversion);
4040                                 if (result == ISC_R_SUCCESS) {
4041                                         options &= ~DNS_GETDB_NOEXACT;
4042                                         query_putrdataset(client, &rdataset);
4043                                         if (sigrdataset != NULL)
4044                                                 query_putrdataset(client,
4045                                                                   &sigrdataset);
4046                                         if (fname != NULL)
4047                                                 query_releasename(client,
4048                                                                   &fname);
4049                                         if (node != NULL)
4050                                                 dns_db_detachnode(db, &node);
4051                                         if (db != NULL)
4052                                                 dns_db_detach(&db);
4053                                         if (zone != NULL)
4054                                                 dns_zone_detach(&zone);
4055                                         version = tversion;
4056                                         db = tdb;
4057                                         zone = tzone;
4058                                         authoritative = ISC_TRUE;
4059                                         goto db_find;
4060                                 }
4061                                 if (tdb != NULL)
4062                                         dns_db_detach(&tdb);
4063                                 if (tzone != NULL)
4064                                         dns_zone_detach(&tzone);
4065                         }
4066                         /*
4067                          * We're authoritative for an ancestor of QNAME.
4068                          */
4069                         if (!USECACHE(client) || !RECURSIONOK(client)) {
4070                                 dns_fixedname_t fixed;
4071
4072                                 dns_fixedname_init(&fixed);
4073                                 dns_name_copy(fname,
4074                                               dns_fixedname_name(&fixed), NULL);
4075
4076                                 /*
4077                                  * If we don't have a cache, this is the best
4078                                  * answer.
4079                                  *
4080                                  * If the client is making a nonrecursive
4081                                  * query we always give out the authoritative
4082                                  * delegation.  This way even if we get
4083                                  * junk in our cache, we won't fail in our
4084                                  * role as the delegating authority if another
4085                                  * nameserver asks us about a delegated
4086                                  * subzone.
4087                                  *
4088                                  * We enable the retrieval of glue for this
4089                                  * database by setting client->query.gluedb.
4090                                  */
4091                                 client->query.gluedb = db;
4092                                 client->query.isreferral = ISC_TRUE;
4093                                 /*
4094                                  * We must ensure NOADDITIONAL is off,
4095                                  * because the generation of
4096                                  * additional data is required in
4097                                  * delegations.
4098                                  */
4099                                 client->query.attributes &=
4100                                         ~NS_QUERYATTR_NOADDITIONAL;
4101                                 if (sigrdataset != NULL)
4102                                         sigrdatasetp = &sigrdataset;
4103                                 else
4104                                         sigrdatasetp = NULL;
4105                                 query_addrrset(client, &fname,
4106                                                &rdataset, sigrdatasetp,
4107                                                dbuf, DNS_SECTION_AUTHORITY);
4108                                 client->query.gluedb = NULL;
4109                                 if (WANTDNSSEC(client))
4110                                         query_addds(client, db, node, version,
4111                                                    dns_fixedname_name(&fixed));
4112                         } else {
4113                                 /*
4114                                  * We might have a better answer or delegation
4115                                  * in the cache.  We'll remember the current
4116                                  * values of fname, rdataset, and sigrdataset.
4117                                  * We'll then go looking for QNAME in the
4118                                  * cache.  If we find something better, we'll
4119                                  * use it instead.
4120                                  */
4121                                 query_keepname(client, fname, dbuf);
4122                                 zdb = db;
4123                                 zfname = fname;
4124                                 fname = NULL;
4125                                 zrdataset = rdataset;
4126                                 rdataset = NULL;
4127                                 zsigrdataset = sigrdataset;
4128                                 sigrdataset = NULL;
4129                                 dns_db_detachnode(db, &node);
4130                                 zversion = version;
4131                                 version = NULL;
4132                                 db = NULL;
4133                                 dns_db_attach(client->view->cachedb, &db);
4134                                 is_zone = ISC_FALSE;
4135                                 goto db_find;
4136                         }
4137                 } else {
4138                         if (zfname != NULL &&
4139                             !dns_name_issubdomain(fname, zfname)) {
4140                                 /*
4141                                  * We've already got a delegation from
4142                                  * authoritative data, and it is better
4143                                  * than what we found in the cache.  Use
4144                                  * it instead of the cache delegation.
4145                                  */
4146                                 query_releasename(client, &fname);
4147                                 fname = zfname;
4148                                 zfname = NULL;
4149                                 /*
4150                                  * We've already done query_keepname() on
4151                                  * zfname, so we must set dbuf to NULL to
4152                                  * prevent query_addrrset() from trying to
4153                                  * call query_keepname() again.
4154                                  */
4155                                 dbuf = NULL;
4156                                 query_putrdataset(client, &rdataset);
4157                                 if (sigrdataset != NULL)
4158                                         query_putrdataset(client,
4159                                                           &sigrdataset);
4160                                 rdataset = zrdataset;
4161                                 zrdataset = NULL;
4162                                 sigrdataset = zsigrdataset;
4163                                 zsigrdataset = NULL;
4164                                 version = zversion;
4165                                 zversion = NULL;
4166                                 /*
4167                                  * We don't clean up zdb here because we
4168                                  * may still need it.  It will get cleaned
4169                                  * up by the main cleanup code.
4170                                  */
4171                         }
4172
4173                         if (RECURSIONOK(client)) {
4174                                 /*
4175                                  * Recurse!
4176                                  */
4177                                 if (dns_rdatatype_atparent(type))
4178                                         result = query_recurse(client, qtype,
4179                                                                NULL, NULL,
4180                                                                resuming);
4181                                 else
4182                                         result = query_recurse(client, qtype,
4183                                                                fname, rdataset,
4184                                                                resuming);
4185                                 if (result == ISC_R_SUCCESS)
4186                                         client->query.attributes |=
4187                                                 NS_QUERYATTR_RECURSING;
4188                                 else if (result == DNS_R_DUPLICATE ||
4189                                          result == DNS_R_DROP)
4190                                         QUERY_ERROR(result);
4191                                 else
4192                                         QUERY_ERROR(DNS_R_SERVFAIL);
4193                         } else {
4194                                 dns_fixedname_t fixed;
4195
4196                                 dns_fixedname_init(&fixed);
4197                                 dns_name_copy(fname,
4198                                               dns_fixedname_name(&fixed), NULL);
4199                                 /*
4200                                  * This is the best answer.
4201                                  */
4202                                 client->query.attributes |=
4203                                         NS_QUERYATTR_CACHEGLUEOK;
4204                                 client->query.gluedb = zdb;
4205                                 client->query.isreferral = ISC_TRUE;
4206                                 /*
4207                                  * We must ensure NOADDITIONAL is off,
4208                                  * because the generation of
4209                                  * additional data is required in
4210                                  * delegations.
4211                                  */
4212                                 client->query.attributes &=
4213                                         ~NS_QUERYATTR_NOADDITIONAL;
4214                                 if (sigrdataset != NULL)
4215                                         sigrdatasetp = &sigrdataset;
4216                                 else
4217                                         sigrdatasetp = NULL;
4218                                 query_addrrset(client, &fname,
4219                                                &rdataset, sigrdatasetp,
4220                                                dbuf, DNS_SECTION_AUTHORITY);
4221                                 client->query.gluedb = NULL;
4222                                 client->query.attributes &=
4223                                         ~NS_QUERYATTR_CACHEGLUEOK;
4224                                 if (WANTDNSSEC(client))
4225                                         query_addds(client, db, node, version,
4226                                                    dns_fixedname_name(&fixed));
4227                         }
4228                 }
4229                 goto cleanup;
4230         case DNS_R_EMPTYNAME:
4231                 result = DNS_R_NXRRSET;
4232                 /* FALLTHROUGH */
4233         case DNS_R_NXRRSET:
4234                 INSIST(is_zone);
4235                 /*
4236                  * Look for a NSEC3 record if we don't have a NSEC record.
4237                  */
4238                 if (!dns_rdataset_isassociated(rdataset) &&
4239                      WANTDNSSEC(client)) {
4240                         if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
4241                                 dns_name_t *found;
4242                                 dns_name_t *qname;
4243
4244                                 dns_fixedname_init(&fixed);
4245                                 found = dns_fixedname_name(&fixed);
4246                                 qname = client->query.qname;
4247
4248                                 query_findclosestnsec3(qname, db, version,
4249                                                        client, rdataset,
4250                                                        sigrdataset, fname,
4251                                                        ISC_TRUE, found);
4252                                 /*
4253                                  * Did we find the closest provable encloser
4254                                  * instead? If so add the nearest to the
4255                                  * closest provable encloser.
4256                                  */
4257                                 if (found &&
4258                                     dns_rdataset_isassociated(rdataset) &&
4259                                     !dns_name_equal(qname, found))
4260                                 {
4261                                         unsigned int count;
4262                                         unsigned int skip;
4263
4264                                         /*
4265                                          * Add the closest provable encloser.
4266                                          */
4267                                         query_addrrset(client, &fname,
4268                                                        &rdataset, &sigrdataset,
4269                                                        dbuf,
4270                                                        DNS_SECTION_AUTHORITY);
4271
4272                                         count = dns_name_countlabels(found)
4273                                                          + 1;
4274                                         skip = dns_name_countlabels(qname) -
4275                                                          count;
4276                                         dns_name_getlabelsequence(qname, skip,
4277                                                                   count,
4278                                                                   found);
4279
4280                                         fixfname(client, &fname, &dbuf, &b);
4281                                         fixrdataset(client, &rdataset);
4282                                         fixrdataset(client, &sigrdataset);
4283                                         if (fname == NULL ||
4284                                             rdataset == NULL ||
4285                                             sigrdataset == NULL) {
4286                                                 QUERY_ERROR(DNS_R_SERVFAIL);
4287                                                 goto cleanup;
4288                                         }
4289                                         /*
4290                                          * 'nearest' doesn't exist so
4291                                          * 'exist' is set to ISC_FALSE.
4292                                          */
4293                                         query_findclosestnsec3(found, db,
4294                                                                version,
4295                                                                client,
4296                                                                rdataset,
4297                                                                sigrdataset,
4298                                                                fname,
4299                                                                ISC_FALSE,
4300                                                                NULL);
4301                                 }
4302                         } else {
4303                                 query_releasename(client, &fname);
4304                                 query_addwildcardproof(client, db, version,
4305                                                        client->query.qname,
4306                                                        ISC_FALSE);
4307                         }
4308                 }
4309                 if (dns_rdataset_isassociated(rdataset)) {
4310                         /*
4311                          * If we've got a NSEC record, we need to save the
4312                          * name now because we're going call query_addsoa()
4313                          * below, and it needs to use the name buffer.
4314                          */
4315                         query_keepname(client, fname, dbuf);
4316                 } else if (fname != NULL) {
4317                         /*
4318                          * We're not going to use fname, and need to release
4319                          * our hold on the name buffer so query_addsoa()
4320                          * may use it.
4321                          */
4322                         query_releasename(client, &fname);
4323                 }
4324                 /*
4325                  * Add SOA.
4326                  */
4327                 result = query_addsoa(client, db, version, ISC_FALSE);
4328                 if (result != ISC_R_SUCCESS) {
4329                         QUERY_ERROR(result);
4330                         goto cleanup;
4331                 }
4332                 /*
4333                  * Add NSEC record if we found one.
4334                  */
4335                 if (WANTDNSSEC(client)) {
4336                         if (dns_rdataset_isassociated(rdataset))
4337                                 query_addnxrrsetnsec(client, db, version,
4338                                                      &fname, &rdataset,
4339                                                      &sigrdataset);
4340                 }
4341                 goto cleanup;
4342
4343         case DNS_R_EMPTYWILD:
4344                 empty_wild = ISC_TRUE;
4345                 /* FALLTHROUGH */
4346
4347         case DNS_R_NXDOMAIN:
4348                 INSIST(is_zone);
4349                 if (dns_rdataset_isassociated(rdataset)) {
4350                         /*
4351                          * If we've got a NSEC record, we need to save the
4352                          * name now because we're going call query_addsoa()
4353                          * below, and it needs to use the name buffer.
4354                          */
4355                         query_keepname(client, fname, dbuf);
4356                 } else if (fname != NULL) {
4357                         /*
4358                          * We're not going to use fname, and need to release
4359                          * our hold on the name buffer so query_addsoa()
4360                          * may use it.
4361                          */
4362                         query_releasename(client, &fname);
4363                 }
4364                 /*
4365                  * Add SOA.  If the query was for a SOA record force the
4366                  * ttl to zero so that it is possible for clients to find
4367                  * the containing zone of an arbitrary name with a stub
4368                  * resolver and not have it cached.
4369                  */
4370                 if (qtype == dns_rdatatype_soa &&
4371 #ifdef DLZ
4372                     zone != NULL &&
4373 #endif
4374                     dns_zone_getzeronosoattl(zone))
4375                         result = query_addsoa(client, db, version, ISC_TRUE);
4376                 else
4377                         result = query_addsoa(client, db, version, ISC_FALSE);
4378                 if (result != ISC_R_SUCCESS) {
4379                         QUERY_ERROR(result);
4380                         goto cleanup;
4381                 }
4382
4383                 if (WANTDNSSEC(client)) {
4384                         /*
4385                          * Add NSEC record if we found one.
4386                          */
4387                         if (dns_rdataset_isassociated(rdataset))
4388                                 query_addrrset(client, &fname, &rdataset,
4389                                                &sigrdataset,
4390                                                NULL, DNS_SECTION_AUTHORITY);
4391                         query_addwildcardproof(client, db, version,
4392                                                client->query.qname, ISC_FALSE);
4393                 }
4394
4395                 /*
4396                  * Set message rcode.
4397                  */
4398                 if (empty_wild)
4399                         client->message->rcode = dns_rcode_noerror;
4400                 else
4401                         client->message->rcode = dns_rcode_nxdomain;
4402                 goto cleanup;
4403
4404         case DNS_R_NCACHENXDOMAIN:
4405         case DNS_R_NCACHENXRRSET:
4406                 INSIST(!is_zone);
4407                 authoritative = ISC_FALSE;
4408                 /*
4409                  * Set message rcode, if required.
4410                  */
4411                 if (result == DNS_R_NCACHENXDOMAIN)
4412                         client->message->rcode = dns_rcode_nxdomain;
4413                 /*
4414                  * Look for RFC 1918 leakage from Internet.
4415                  */
4416                 if (result == DNS_R_NCACHENXDOMAIN &&
4417                     qtype == dns_rdatatype_ptr &&
4418                     client->message->rdclass == dns_rdataclass_in &&
4419                     dns_name_countlabels(fname) == 7)
4420                         warn_rfc1918(client, fname, rdataset);
4421                 /*
4422                  * We don't call query_addrrset() because we don't need any
4423                  * of its extra features (and things would probably break!).
4424                  */
4425                 query_keepname(client, fname, dbuf);
4426                 dns_message_addname(client->message, fname,
4427                                     DNS_SECTION_AUTHORITY);
4428                 ISC_LIST_APPEND(fname->list, rdataset, link);
4429                 fname = NULL;
4430                 rdataset = NULL;
4431                 goto cleanup;
4432
4433         case DNS_R_CNAME:
4434                 /*
4435                  * Keep a copy of the rdataset.  We have to do this because
4436                  * query_addrrset may clear 'rdataset' (to prevent the
4437                  * cleanup code from cleaning it up).
4438                  */
4439                 trdataset = rdataset;
4440                 /*
4441                  * Add the CNAME to the answer section.
4442                  */
4443                 if (sigrdataset != NULL)
4444                         sigrdatasetp = &sigrdataset;
4445                 else
4446                         sigrdatasetp = NULL;
4447                 if (WANTDNSSEC(client) &&
4448                     (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
4449                 {
4450                         dns_fixedname_init(&wildcardname);
4451                         dns_name_copy(fname, dns_fixedname_name(&wildcardname),
4452                                       NULL);
4453                         need_wildcardproof = ISC_TRUE;
4454                 }
4455                 if (NOQNAME(rdataset) && WANTDNSSEC(client))
4456                         noqname = rdataset;
4457                 else
4458                         noqname = NULL;
4459                 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
4460                                DNS_SECTION_ANSWER);
4461                 if (noqname != NULL)
4462                         query_addnoqnameproof(client, noqname);
4463                 /*
4464                  * We set the PARTIALANSWER attribute so that if anything goes
4465                  * wrong later on, we'll return what we've got so far.
4466                  */
4467                 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
4468                 /*
4469                  * Reset qname to be the target name of the CNAME and restart
4470                  * the query.
4471                  */
4472                 tname = NULL;
4473                 result = dns_message_gettempname(client->message, &tname);
4474                 if (result != ISC_R_SUCCESS)
4475                         goto cleanup;
4476                 result = dns_rdataset_first(trdataset);
4477                 if (result != ISC_R_SUCCESS) {
4478                         dns_message_puttempname(client->message, &tname);
4479                         goto cleanup;
4480                 }
4481                 dns_rdataset_current(trdataset, &rdata);
4482                 result = dns_rdata_tostruct(&rdata, &cname, NULL);
4483                 dns_rdata_reset(&rdata);
4484                 if (result != ISC_R_SUCCESS) {
4485                         dns_message_puttempname(client->message, &tname);
4486                         goto cleanup;
4487                 }
4488                 dns_name_init(tname, NULL);
4489                 result = dns_name_dup(&cname.cname, client->mctx, tname);
4490                 if (result != ISC_R_SUCCESS) {
4491                         dns_message_puttempname(client->message, &tname);
4492                         dns_rdata_freestruct(&cname);
4493                         goto cleanup;
4494                 }
4495                 dns_rdata_freestruct(&cname);
4496                 ns_client_qnamereplace(client, tname);
4497                 want_restart = ISC_TRUE;
4498                 if (!WANTRECURSION(client))
4499                         options |= DNS_GETDB_NOLOG;
4500                 goto addauth;
4501         case DNS_R_DNAME:
4502                 /*
4503                  * Compare the current qname to the found name.  We need
4504                  * to know how many labels and bits are in common because
4505                  * we're going to have to split qname later on.
4506                  */
4507                 namereln = dns_name_fullcompare(client->query.qname, fname,
4508                                                 &order, &nlabels);
4509                 INSIST(namereln == dns_namereln_subdomain);
4510                 /*
4511                  * Keep a copy of the rdataset.  We have to do this because
4512                  * query_addrrset may clear 'rdataset' (to prevent the
4513                  * cleanup code from cleaning it up).
4514                  */
4515                 trdataset = rdataset;
4516                 /*
4517                  * Add the DNAME to the answer section.
4518                  */
4519                 if (sigrdataset != NULL)
4520                         sigrdatasetp = &sigrdataset;
4521                 else
4522                         sigrdatasetp = NULL;
4523                 if (WANTDNSSEC(client) &&
4524                     (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
4525                 {
4526                         dns_fixedname_init(&wildcardname);
4527                         dns_name_copy(fname, dns_fixedname_name(&wildcardname),
4528                                       NULL);
4529                         need_wildcardproof = ISC_TRUE;
4530                 }
4531                 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
4532                                DNS_SECTION_ANSWER);
4533                 /*
4534                  * We set the PARTIALANSWER attribute so that if anything goes
4535                  * wrong later on, we'll return what we've got so far.
4536                  */
4537                 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
4538                 /*
4539                  * Get the target name of the DNAME.
4540                  */
4541                 tname = NULL;
4542                 result = dns_message_gettempname(client->message, &tname);
4543                 if (result != ISC_R_SUCCESS)
4544                         goto cleanup;
4545                 result = dns_rdataset_first(trdataset);
4546                 if (result != ISC_R_SUCCESS) {
4547                         dns_message_puttempname(client->message, &tname);
4548                         goto cleanup;
4549                 }
4550                 dns_rdataset_current(trdataset, &rdata);
4551                 result = dns_rdata_tostruct(&rdata, &dname, NULL);
4552                 dns_rdata_reset(&rdata);
4553                 if (result != ISC_R_SUCCESS) {
4554                         dns_message_puttempname(client->message, &tname);
4555                         goto cleanup;
4556                 }
4557                 dns_name_init(tname, NULL);
4558                 dns_name_clone(&dname.dname, tname);
4559                 dns_rdata_freestruct(&dname);
4560                 /*
4561                  * Construct the new qname.
4562                  */
4563                 dns_fixedname_init(&fixed);
4564                 prefix = dns_fixedname_name(&fixed);
4565                 dns_name_split(client->query.qname, nlabels, prefix, NULL);
4566                 INSIST(fname == NULL);
4567                 dbuf = query_getnamebuf(client);
4568                 if (dbuf == NULL) {
4569                         dns_message_puttempname(client->message, &tname);
4570                         goto cleanup;
4571                 }
4572                 fname = query_newname(client, dbuf, &b);
4573                 if (fname == NULL) {
4574                         dns_message_puttempname(client->message, &tname);
4575                         goto cleanup;
4576                 }
4577                 result = dns_name_concatenate(prefix, tname, fname, NULL);
4578                 if (result != ISC_R_SUCCESS) {
4579                         dns_message_puttempname(client->message, &tname);
4580                         if (result == ISC_R_NOSPACE) {
4581                                 /*
4582                                  * RFC2672, section 4.1, subsection 3c says
4583                                  * we should return YXDOMAIN if the constructed
4584                                  * name would be too long.
4585                                  */
4586                                 client->message->rcode = dns_rcode_yxdomain;
4587                         }
4588                         goto cleanup;
4589                 }
4590                 query_keepname(client, fname, dbuf);
4591                 /*
4592                  * Synthesize a CNAME for this DNAME.
4593                  *
4594                  * We want to synthesize a CNAME since if we don't
4595                  * then older software that doesn't understand DNAME
4596                  * will not chain like it should.
4597                  *
4598                  * We do not try to synthesize a signature because we hope
4599                  * that security aware servers will understand DNAME.  Also,
4600                  * even if we had an online key, making a signature
4601                  * on-the-fly is costly, and not really legitimate anyway
4602                  * since the synthesized CNAME is NOT in the zone.
4603                  */
4604                 dns_name_init(tname, NULL);
4605                 (void)query_addcnamelike(client, client->query.qname, fname,
4606                                          trdataset->trust, &tname,
4607                                          dns_rdatatype_cname);
4608                 if (tname != NULL)
4609                         dns_message_puttempname(client->message, &tname);
4610                 /*
4611                  * Switch to the new qname and restart.
4612                  */
4613                 ns_client_qnamereplace(client, fname);
4614                 fname = NULL;
4615                 want_restart = ISC_TRUE;
4616                 if (!WANTRECURSION(client))
4617                         options |= DNS_GETDB_NOLOG;
4618                 goto addauth;
4619         default:
4620                 /*
4621                  * Something has gone wrong.
4622                  */
4623                 QUERY_ERROR(DNS_R_SERVFAIL);
4624                 goto cleanup;
4625         }
4626
4627         if (WANTDNSSEC(client) &&
4628             (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
4629         {
4630                 dns_fixedname_init(&wildcardname);
4631                 dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL);
4632                 need_wildcardproof = ISC_TRUE;
4633         }
4634
4635         if (type == dns_rdatatype_any) {
4636                 /*
4637                  * XXXRTH  Need to handle zonecuts with special case
4638                  * code.
4639                  */
4640                 n = 0;
4641                 rdsiter = NULL;
4642                 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
4643                 if (result != ISC_R_SUCCESS) {
4644                         QUERY_ERROR(DNS_R_SERVFAIL);
4645                         goto cleanup;
4646                 }
4647                 /*
4648                  * Calling query_addrrset() with a non-NULL dbuf is going
4649                  * to either keep or release the name.  We don't want it to
4650                  * release fname, since we may have to call query_addrrset()
4651                  * more than once.  That means we have to call query_keepname()
4652                  * now, and pass a NULL dbuf to query_addrrset().
4653                  *
4654                  * If we do a query_addrrset() below, we must set fname to
4655                  * NULL before leaving this block, otherwise we might try to
4656                  * cleanup fname even though we're using it!
4657                  */
4658                 query_keepname(client, fname, dbuf);
4659                 tname = fname;
4660                 result = dns_rdatasetiter_first(rdsiter);
4661                 while (result == ISC_R_SUCCESS) {
4662                         dns_rdatasetiter_current(rdsiter, rdataset);
4663                         if (is_zone && qtype == dns_rdatatype_any &&
4664                             !dns_db_issecure(db) &&
4665                             dns_rdatatype_isdnssec(rdataset->type)) {
4666                                 /*
4667                                  * The zone is transitioning from insecure
4668                                  * to secure. Hide the dnssec records from
4669                                  * ANY queries.
4670                                  */
4671                                 dns_rdataset_disassociate(rdataset);
4672                         } else if ((qtype == dns_rdatatype_any ||
4673                              rdataset->type == qtype) && rdataset->type != 0) {
4674                                 if (NOQNAME(rdataset) && WANTDNSSEC(client))
4675                                         noqname = rdataset;
4676                                 else
4677                                         noqname = NULL;
4678                                 query_addrrset(client,
4679                                                fname != NULL ? &fname : &tname,
4680                                                &rdataset, NULL,
4681                                                NULL, DNS_SECTION_ANSWER);
4682                                 if (noqname != NULL)
4683                                         query_addnoqnameproof(client, noqname);
4684                                 n++;
4685                                 INSIST(tname != NULL);
4686                                 /*
4687                                  * rdataset is non-NULL only in certain
4688                                  * pathological cases involving DNAMEs.
4689                                  */
4690                                 if (rdataset != NULL)
4691                                         query_putrdataset(client, &rdataset);
4692                                 rdataset = query_newrdataset(client);
4693                                 if (rdataset == NULL)
4694                                         break;
4695                         } else {
4696                                 /*
4697                                  * We're not interested in this rdataset.
4698                                  */
4699                                 dns_rdataset_disassociate(rdataset);
4700                         }
4701                         result = dns_rdatasetiter_next(rdsiter);
4702                 }
4703
4704                 if (fname != NULL)
4705                         dns_message_puttempname(client->message, &fname);
4706
4707                 if (n == 0 && is_zone) {
4708                         /*
4709                          * We didn't match any rdatasets.
4710                          */
4711                         if (qtype == dns_rdatatype_rrsig &&
4712                             result == ISC_R_NOMORE) {
4713                                 /*
4714                                  * XXXRTH  If this is a secure zone and we
4715                                  * didn't find any SIGs, we should generate
4716                                  * an error unless we were searching for
4717                                  * glue.  Ugh.
4718                                  */
4719                                 if (!is_zone) {
4720                                         authoritative = ISC_FALSE;
4721                                         dns_rdatasetiter_destroy(&rdsiter);
4722                                         if (RECURSIONOK(client)) {
4723                                                 result = query_recurse(client,
4724                                                                        qtype,
4725                                                                        NULL,
4726                                                                        NULL,
4727                                                                        resuming);
4728                                                 if (result == ISC_R_SUCCESS)
4729                                                     client->query.attributes |=
4730                                                         NS_QUERYATTR_RECURSING;
4731                                                 else
4732                                                     QUERY_ERROR(DNS_R_SERVFAIL);                                        }
4733                                         goto addauth;
4734                                 }
4735                                 /*
4736                                  * We were searching for SIG records in
4737                                  * a nonsecure zone.  Send a "no error,
4738                                  * no data" response.
4739                                  */
4740                                 /*
4741                                  * Add SOA.
4742                                  */
4743                                 result = query_addsoa(client, db, version,
4744                                                       ISC_FALSE);
4745                                 if (result == ISC_R_SUCCESS)
4746                                         result = ISC_R_NOMORE;
4747                         } else {
4748                                 /*
4749                                  * Something went wrong.
4750                                  */
4751                                 result = DNS_R_SERVFAIL;
4752                         }
4753                 }
4754                 dns_rdatasetiter_destroy(&rdsiter);
4755                 if (result != ISC_R_NOMORE) {
4756                         QUERY_ERROR(DNS_R_SERVFAIL);
4757                         goto cleanup;
4758                 }
4759         } else {
4760                 /*
4761                  * This is the "normal" case -- an ordinary question to which
4762                  * we know the answer.
4763                  */
4764                 if (sigrdataset != NULL)
4765                         sigrdatasetp = &sigrdataset;
4766                 else
4767                         sigrdatasetp = NULL;
4768                 if (NOQNAME(rdataset) && WANTDNSSEC(client))
4769                         noqname = rdataset;
4770                 else
4771                         noqname = NULL;
4772                 /*
4773                  * BIND 8 priming queries need the additional section.
4774                  */
4775                 if (is_zone && qtype == dns_rdatatype_ns &&
4776                     dns_name_equal(client->query.qname, dns_rootname))
4777                         client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL;
4778
4779                 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
4780                                DNS_SECTION_ANSWER);
4781                 if (noqname != NULL)
4782                         query_addnoqnameproof(client, noqname);
4783                 /*
4784                  * We shouldn't ever fail to add 'rdataset'
4785                  * because it's already in the answer.
4786                  */
4787                 INSIST(rdataset == NULL);
4788         }
4789
4790  addauth:
4791         CTRACE("query_find: addauth");
4792         /*
4793          * Add NS records to the authority section (if we haven't already
4794          * added them to the answer section).
4795          */
4796         if (!want_restart && !NOAUTHORITY(client)) {
4797                 if (is_zone) {
4798                         if (!((qtype == dns_rdatatype_ns ||
4799                                qtype == dns_rdatatype_any) &&
4800                               dns_name_equal(client->query.qname,
4801                                              dns_db_origin(db))))
4802                                 (void)query_addns(client, db, version);
4803                 } else if (qtype != dns_rdatatype_ns) {
4804                         if (fname != NULL)
4805                                 query_releasename(client, &fname);
4806                         query_addbestns(client);
4807                 }
4808         }
4809
4810         /*
4811          * Add NSEC records to the authority section if they're needed for
4812          * DNSSEC wildcard proofs.
4813          */
4814         if (need_wildcardproof && dns_db_issecure(db))
4815                 query_addwildcardproof(client, db, version,
4816                                        dns_fixedname_name(&wildcardname),
4817                                        ISC_TRUE);
4818  cleanup:
4819         CTRACE("query_find: cleanup");
4820         /*
4821          * General cleanup.
4822          */
4823         if (rdataset != NULL)
4824                 query_putrdataset(client, &rdataset);
4825         if (sigrdataset != NULL)
4826                 query_putrdataset(client, &sigrdataset);
4827         if (fname != NULL)
4828                 query_releasename(client, &fname);
4829         if (node != NULL)
4830                 dns_db_detachnode(db, &node);
4831         if (db != NULL)
4832                 dns_db_detach(&db);
4833         if (zone != NULL)
4834                 dns_zone_detach(&zone);
4835         if (zdb != NULL) {
4836                 query_putrdataset(client, &zrdataset);
4837                 if (zsigrdataset != NULL)
4838                         query_putrdataset(client, &zsigrdataset);
4839                 if (zfname != NULL)
4840                         query_releasename(client, &zfname);
4841                 dns_db_detach(&zdb);
4842         }
4843         if (event != NULL)
4844                 isc_event_free(ISC_EVENT_PTR(&event));
4845
4846         /*
4847          * AA bit.
4848          */
4849         if (client->query.restarts == 0 && !authoritative) {
4850                 /*
4851                  * We're not authoritative, so we must ensure the AA bit
4852                  * isn't set.
4853                  */
4854                 client->message->flags &= ~DNS_MESSAGEFLAG_AA;
4855         }
4856
4857         /*
4858          * Restart the query?
4859          */
4860         if (want_restart && client->query.restarts < MAX_RESTARTS) {
4861                 client->query.restarts++;
4862                 goto restart;
4863         }
4864
4865         if (eresult != ISC_R_SUCCESS &&
4866             (!PARTIALANSWER(client) || WANTRECURSION(client))) {
4867                 if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) {
4868                         /*
4869                          * This was a duplicate query that we are
4870                          * recursing on.  Don't send a response now.
4871                          * The original query will still cause a response.
4872                          */
4873                         query_next(client, eresult);
4874                 } else {
4875                         /*
4876                          * If we don't have any answer to give the client,
4877                          * or if the client requested recursion and thus wanted
4878                          * the complete answer, send an error response.
4879                          */
4880                         INSIST(line >= 0);
4881                         query_error(client, eresult, line);
4882                 }
4883                 ns_client_detach(&client);
4884         } else if (!RECURSING(client)) {
4885                 /*
4886                  * We are done.  Set up sortlist data for the message
4887                  * rendering code, make a final tweak to the AA bit if the
4888                  * auth-nxdomain config option says so, then render and
4889                  * send the response.
4890                  */
4891                 setup_query_sortlist(client);
4892
4893                 /*
4894                  * If this is a referral and the answer to the question
4895                  * is in the glue sort it to the start of the additional
4896                  * section.
4897                  */
4898                 if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) &&
4899                     client->message->rcode == dns_rcode_noerror &&
4900                     (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa))
4901                         answer_in_glue(client, qtype);
4902
4903                 if (client->message->rcode == dns_rcode_nxdomain &&
4904                     client->view->auth_nxdomain == ISC_TRUE)
4905                         client->message->flags |= DNS_MESSAGEFLAG_AA;
4906
4907                 /*
4908                  * If the response is somehow unexpected for the client and this
4909                  * is a result of recursion, return an error to the caller
4910                  * to indicate it may need to be logged.
4911                  */
4912                 if (resuming &&
4913                     (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) ||
4914                      client->message->rcode != dns_rcode_noerror))
4915                         eresult = ISC_R_FAILURE;
4916
4917                 query_send(client);
4918                 ns_client_detach(&client);
4919         }
4920         CTRACE("query_find: done");
4921
4922         return (eresult);
4923 }
4924
4925 static inline void
4926 log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
4927         char namebuf[DNS_NAME_FORMATSIZE];
4928         char typename[DNS_RDATATYPE_FORMATSIZE];
4929         char classname[DNS_RDATACLASS_FORMATSIZE];
4930         dns_rdataset_t *rdataset;
4931         int level = ISC_LOG_INFO;
4932
4933         if (! isc_log_wouldlog(ns_g_lctx, level))
4934                 return;
4935
4936         rdataset = ISC_LIST_HEAD(client->query.qname->list);
4937         INSIST(rdataset != NULL);
4938         dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
4939         dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname));
4940         dns_rdatatype_format(rdataset->type, typename, sizeof(typename));
4941
4942         ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
4943                       level, "query: %s %s %s %s%s%s%s%s", namebuf, classname,
4944                       typename, WANTRECURSION(client) ? "+" : "-",
4945                       (client->signer != NULL) ? "S": "",
4946                       (client->opt != NULL) ? "E" : "",
4947                       ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
4948                       ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "");
4949 }
4950
4951 static inline void
4952 log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) {
4953         char namebuf[DNS_NAME_FORMATSIZE];
4954         char typename[DNS_RDATATYPE_FORMATSIZE];
4955         char classname[DNS_RDATACLASS_FORMATSIZE];
4956         const char *namep, *typep, *classp, *sep1, *sep2;
4957         dns_rdataset_t *rdataset;
4958
4959         if (!isc_log_wouldlog(ns_g_lctx, level))
4960                 return;
4961
4962         namep = typep = classp = sep1 = sep2 = "";
4963
4964         /*
4965          * Query errors can happen for various reasons.  In some cases we cannot
4966          * even assume the query contains a valid question section, so we should
4967          * expect exceptional cases.
4968          */
4969         if (client->query.origqname != NULL) {
4970                 dns_name_format(client->query.origqname, namebuf,
4971                                 sizeof(namebuf));
4972                 namep = namebuf;
4973                 sep1 = " for ";
4974
4975                 rdataset = ISC_LIST_HEAD(client->query.origqname->list);
4976                 if (rdataset != NULL) {
4977                         dns_rdataclass_format(rdataset->rdclass, classname,
4978                                               sizeof(classname));
4979                         classp = classname;
4980                         dns_rdatatype_format(rdataset->type, typename,
4981                                              sizeof(typename));
4982                         typep = typename;
4983                         sep2 = "/";
4984                 }
4985         }
4986
4987         ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, NS_LOGMODULE_QUERY,
4988                       level, "query failed (%s)%s%s%s%s%s%s at %s:%d",
4989                       isc_result_totext(result), sep1, namep, sep2,
4990                       classp, sep2, typep, __FILE__, line);
4991 }
4992
4993 void
4994 ns_query_start(ns_client_t *client) {
4995         isc_result_t result;
4996         dns_message_t *message = client->message;
4997         dns_rdataset_t *rdataset;
4998         ns_client_t *qclient;
4999         dns_rdatatype_t qtype;
5000         unsigned int saved_extflags = client->extflags;
5001         unsigned int saved_flags = client->message->flags;
5002         isc_boolean_t want_ad;
5003
5004         CTRACE("ns_query_start");
5005
5006         /*
5007          * Test only.
5008          */
5009         if (ns_g_clienttest && (client->attributes & NS_CLIENTATTR_TCP) == 0)
5010                 RUNTIME_CHECK(ns_client_replace(client) == ISC_R_SUCCESS);
5011
5012         /*
5013          * Ensure that appropriate cleanups occur.
5014          */
5015         client->next = query_next_callback;
5016
5017         /*
5018          * Behave as if we don't support DNSSEC if not enabled.
5019          */
5020         if (!client->view->enablednssec) {
5021                 message->flags &= ~DNS_MESSAGEFLAG_CD;
5022                 client->extflags &= ~DNS_MESSAGEEXTFLAG_DO;
5023                 if (client->opt != NULL)
5024                         client->opt->ttl &= ~DNS_MESSAGEEXTFLAG_DO;
5025         }
5026
5027         if ((message->flags & DNS_MESSAGEFLAG_RD) != 0)
5028                 client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
5029
5030         if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0)
5031                 client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
5032
5033         if (client->view->minimalresponses)
5034                 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
5035                                              NS_QUERYATTR_NOADDITIONAL);
5036
5037         if ((client->view->cachedb == NULL)
5038             || (!client->view->additionalfromcache)) {
5039                 /*
5040                  * We don't have a cache.  Turn off cache support and
5041                  * recursion.
5042                  */
5043                 client->query.attributes &=
5044                         ~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK);
5045         } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
5046                    (message->flags & DNS_MESSAGEFLAG_RD) == 0) {
5047                 /*
5048                  * If the client isn't allowed to recurse (due to
5049                  * "recursion no", the allow-recursion ACL, or the
5050                  * lack of a resolver in this view), or if it
5051                  * doesn't want recursion, turn recursion off.
5052                  */
5053                 client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
5054         }
5055
5056         /*
5057          * Get the question name.
5058          */
5059         result = dns_message_firstname(message, DNS_SECTION_QUESTION);
5060         if (result != ISC_R_SUCCESS) {
5061                 query_error(client, result, __LINE__);
5062                 return;
5063         }
5064         dns_message_currentname(message, DNS_SECTION_QUESTION,
5065                                 &client->query.qname);
5066         client->query.origqname = client->query.qname;
5067         result = dns_message_nextname(message, DNS_SECTION_QUESTION);
5068         if (result != ISC_R_NOMORE) {
5069                 if (result == ISC_R_SUCCESS) {
5070                         /*
5071                          * There's more than one QNAME in the question
5072                          * section.
5073                          */
5074                         query_error(client, DNS_R_FORMERR, __LINE__);
5075                 } else
5076                         query_error(client, result, __LINE__);
5077                 return;
5078         }
5079
5080         if (ns_g_server->log_queries)
5081                 log_query(client, saved_flags, saved_extflags);
5082
5083         /*
5084          * Check for multiple question queries, since edns1 is dead.
5085          */
5086         if (message->counts[DNS_SECTION_QUESTION] > 1) {
5087                 query_error(client, DNS_R_FORMERR, __LINE__);
5088                 return;
5089         }
5090
5091         /*
5092          * Check for meta-queries like IXFR and AXFR.
5093          */
5094         rdataset = ISC_LIST_HEAD(client->query.qname->list);
5095         INSIST(rdataset != NULL);
5096         qtype = rdataset->type;
5097         dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype);
5098         if (dns_rdatatype_ismeta(qtype)) {
5099                 switch (qtype) {
5100                 case dns_rdatatype_any:
5101                         break; /* Let query_find handle it. */
5102                 case dns_rdatatype_ixfr:
5103                 case dns_rdatatype_axfr:
5104                         ns_xfr_start(client, rdataset->type);
5105                         return;
5106                 case dns_rdatatype_maila:
5107                 case dns_rdatatype_mailb:
5108                         query_error(client, DNS_R_NOTIMP, __LINE__);
5109                         return;
5110                 case dns_rdatatype_tkey:
5111                         result = dns_tkey_processquery(client->message,
5112                                                 ns_g_server->tkeyctx,
5113                                                 client->view->dynamickeys);
5114                         if (result == ISC_R_SUCCESS)
5115                                 query_send(client);
5116                         else
5117                                 query_error(client, result, __LINE__);
5118                         return;
5119                 default: /* TSIG, etc. */
5120                         query_error(client, DNS_R_FORMERR, __LINE__);
5121                         return;
5122                 }
5123         }
5124
5125         /*
5126          * Turn on minimal response for DNSKEY queries.
5127          */
5128         if (qtype == dns_rdatatype_dnskey)
5129                 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
5130                                              NS_QUERYATTR_NOADDITIONAL);
5131
5132         /*
5133          * If the client has requested that DNSSEC checking be disabled,
5134          * allow lookups to return pending data and instruct the resolver
5135          * to return data before validation has completed.
5136          *
5137          * We don't need to set DNS_DBFIND_PENDINGOK when validation is
5138          * disabled as there will be no pending data.
5139          */
5140         if (message->flags & DNS_MESSAGEFLAG_CD ||
5141             qtype == dns_rdatatype_rrsig)
5142         {
5143                 client->query.dboptions |= DNS_DBFIND_PENDINGOK;
5144                 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
5145         } else if (!client->view->enablevalidation)
5146                 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
5147
5148         /*
5149          * Allow glue NS records to be added to the authority section
5150          * if the answer is secure.
5151          */
5152         if (message->flags & DNS_MESSAGEFLAG_CD)
5153                 client->query.attributes &= ~NS_QUERYATTR_SECURE;
5154
5155         /*
5156          * Set 'want_ad' if the client has set AD in the query.
5157          * This allows AD to be returned on queries without DO set.
5158          */
5159         if ((message->flags & DNS_MESSAGEFLAG_AD) != 0)
5160                 want_ad = ISC_TRUE;
5161         else
5162                 want_ad = ISC_FALSE;
5163
5164         /*
5165          * This is an ordinary query.
5166          */
5167         result = dns_message_reply(message, ISC_TRUE);
5168         if (result != ISC_R_SUCCESS) {
5169                 query_next(client, result);
5170                 return;
5171         }
5172
5173         /*
5174          * Assume authoritative response until it is known to be
5175          * otherwise.
5176          */
5177         message->flags |= DNS_MESSAGEFLAG_AA;
5178
5179         /*
5180          * Set AD.  We must clear it if we add non-validated data to a
5181          * response.
5182          */
5183         if (WANTDNSSEC(client) || want_ad)
5184                 message->flags |= DNS_MESSAGEFLAG_AD;
5185
5186         qclient = NULL;
5187         ns_client_attach(client, &qclient);
5188         (void)query_find(qclient, NULL, qtype);
5189 }