]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - contrib/bind9/bin/named/query.c
Fix BIND named(8) cache poisoning with DNSSEC validation.
[FreeBSD/releng/8.0.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 2009/03/13 01:38:51 marka Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <string.h>
25
26 #include <isc/hex.h>
27 #include <isc/mem.h>
28 #include <isc/stats.h>
29 #include <isc/util.h>
30
31 #include <dns/adb.h>
32 #include <dns/byaddr.h>
33 #include <dns/db.h>
34 #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 | DNS_DBFIND_GLUEOK,
1164                              client->now, &node, fname, rdataset,
1165                              sigrdataset);
1166         if (result == DNS_R_GLUE &&
1167             validate(client, db, fname, rdataset, sigrdataset))
1168                 result = ISC_R_SUCCESS;
1169         if (!WANTDNSSEC(client))
1170                 query_putrdataset(client, &sigrdataset);
1171         if (result == ISC_R_SUCCESS)
1172                 goto found;
1173
1174         if (dns_rdataset_isassociated(rdataset))
1175                 dns_rdataset_disassociate(rdataset);
1176         if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
1177                 dns_rdataset_disassociate(sigrdataset);
1178         if (node != NULL)
1179                 dns_db_detachnode(db, &node);
1180         dns_db_detach(&db);
1181
1182  try_glue:
1183         /*
1184          * No cached data was found.  Glue is our last chance.
1185          * RFC1035 sayeth:
1186          *
1187          *      NS records cause both the usual additional section
1188          *      processing to locate a type A record, and, when used
1189          *      in a referral, a special search of the zone in which
1190          *      they reside for glue information.
1191          *
1192          * This is the "special search".  Note that we must search
1193          * the zone where the NS record resides, not the zone it
1194          * points to, and that we only do the search in the delegation
1195          * case (identified by client->query.gluedb being set).
1196          */
1197
1198         if (client->query.gluedb == NULL)
1199                 goto cleanup;
1200
1201         /*
1202          * Don't poison caches using the bailiwick protection model.
1203          */
1204         if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
1205                 goto cleanup;
1206
1207         dns_db_attach(client->query.gluedb, &db);
1208         result = dns_db_find(db, name, version, type,
1209                              client->query.dboptions | DNS_DBFIND_GLUEOK,
1210                              client->now, &node, fname, rdataset,
1211                              sigrdataset);
1212         if (!(result == ISC_R_SUCCESS ||
1213               result == DNS_R_ZONECUT ||
1214               result == DNS_R_GLUE))
1215                 goto cleanup;
1216
1217  found:
1218         /*
1219          * We have found a potential additional data rdataset, or
1220          * at least a node to iterate over.
1221          */
1222         query_keepname(client, fname, dbuf);
1223
1224         /*
1225          * If we have an rdataset, add it to the additional data
1226          * section.
1227          */
1228         mname = NULL;
1229         if (dns_rdataset_isassociated(rdataset) &&
1230             !query_isduplicate(client, fname, type, &mname)) {
1231                 if (mname != NULL) {
1232                         query_releasename(client, &fname);
1233                         fname = mname;
1234                 } else
1235                         need_addname = ISC_TRUE;
1236                 ISC_LIST_APPEND(fname->list, rdataset, link);
1237                 trdataset = rdataset;
1238                 rdataset = NULL;
1239                 added_something = ISC_TRUE;
1240                 /*
1241                  * Note: we only add SIGs if we've added the type they cover,
1242                  * so we do not need to check if the SIG rdataset is already
1243                  * in the response.
1244                  */
1245                 if (sigrdataset != NULL &&
1246                     dns_rdataset_isassociated(sigrdataset))
1247                 {
1248                         ISC_LIST_APPEND(fname->list, sigrdataset, link);
1249                         sigrdataset = NULL;
1250                 }
1251         }
1252
1253         if (qtype == dns_rdatatype_a) {
1254                 /*
1255                  * We now go looking for A and AAAA records, along with
1256                  * their signatures.
1257                  *
1258                  * XXXRTH  This code could be more efficient.
1259                  */
1260                 if (rdataset != NULL) {
1261                         if (dns_rdataset_isassociated(rdataset))
1262                                 dns_rdataset_disassociate(rdataset);
1263                 } else {
1264                         rdataset = query_newrdataset(client);
1265                         if (rdataset == NULL)
1266                                 goto addname;
1267                 }
1268                 if (sigrdataset != NULL) {
1269                         if (dns_rdataset_isassociated(sigrdataset))
1270                                 dns_rdataset_disassociate(sigrdataset);
1271                 } else if (WANTDNSSEC(client)) {
1272                         sigrdataset = query_newrdataset(client);
1273                         if (sigrdataset == NULL)
1274                                 goto addname;
1275                 }
1276                 result = dns_db_findrdataset(db, node, version,
1277                                              dns_rdatatype_a, 0,
1278                                              client->now, rdataset,
1279                                              sigrdataset);
1280                 if (result == DNS_R_NCACHENXDOMAIN)
1281                         goto addname;
1282                 if (result == DNS_R_NCACHENXRRSET) {
1283                         dns_rdataset_disassociate(rdataset);
1284                         /*
1285                          * Negative cache entries don't have sigrdatasets.
1286                          */
1287                         INSIST(sigrdataset == NULL ||
1288                                ! dns_rdataset_isassociated(sigrdataset));
1289                 }
1290                 if (result == ISC_R_SUCCESS) {
1291                         mname = NULL;
1292                         if (!query_isduplicate(client, fname,
1293                                                dns_rdatatype_a, &mname)) {
1294                                 if (mname != NULL) {
1295                                         query_releasename(client, &fname);
1296                                         fname = mname;
1297                                 } else
1298                                         need_addname = ISC_TRUE;
1299                                 ISC_LIST_APPEND(fname->list, rdataset, link);
1300                                 added_something = ISC_TRUE;
1301                                 if (sigrdataset != NULL &&
1302                                     dns_rdataset_isassociated(sigrdataset))
1303                                 {
1304                                         ISC_LIST_APPEND(fname->list,
1305                                                         sigrdataset, link);
1306                                         sigrdataset =
1307                                                 query_newrdataset(client);
1308                                 }
1309                                 rdataset = query_newrdataset(client);
1310                                 if (rdataset == NULL)
1311                                         goto addname;
1312                                 if (WANTDNSSEC(client) && sigrdataset == NULL)
1313                                         goto addname;
1314                         } else {
1315                                 dns_rdataset_disassociate(rdataset);
1316                                 if (sigrdataset != NULL &&
1317                                     dns_rdataset_isassociated(sigrdataset))
1318                                         dns_rdataset_disassociate(sigrdataset);
1319                         }
1320                 }
1321                 result = dns_db_findrdataset(db, node, version,
1322                                              dns_rdatatype_aaaa, 0,
1323                                              client->now, rdataset,
1324                                              sigrdataset);
1325                 if (result == DNS_R_NCACHENXDOMAIN)
1326                         goto addname;
1327                 if (result == DNS_R_NCACHENXRRSET) {
1328                         dns_rdataset_disassociate(rdataset);
1329                         INSIST(sigrdataset == NULL ||
1330                                ! dns_rdataset_isassociated(sigrdataset));
1331                 }
1332                 if (result == ISC_R_SUCCESS) {
1333                         mname = NULL;
1334                         if (!query_isduplicate(client, fname,
1335                                                dns_rdatatype_aaaa, &mname)) {
1336                                 if (mname != NULL) {
1337                                         query_releasename(client, &fname);
1338                                         fname = mname;
1339                                 } else
1340                                         need_addname = ISC_TRUE;
1341                                 ISC_LIST_APPEND(fname->list, rdataset, link);
1342                                 added_something = ISC_TRUE;
1343                                 if (sigrdataset != NULL &&
1344                                     dns_rdataset_isassociated(sigrdataset))
1345                                 {
1346                                         ISC_LIST_APPEND(fname->list,
1347                                                         sigrdataset, link);
1348                                         sigrdataset = NULL;
1349                                 }
1350                                 rdataset = NULL;
1351                         }
1352                 }
1353         }
1354
1355  addname:
1356         CTRACE("query_addadditional: addname");
1357         /*
1358          * If we haven't added anything, then we're done.
1359          */
1360         if (!added_something)
1361                 goto cleanup;
1362
1363         /*
1364          * We may have added our rdatasets to an existing name, if so, then
1365          * need_addname will be ISC_FALSE.  Whether we used an existing name
1366          * or a new one, we must set fname to NULL to prevent cleanup.
1367          */
1368         if (need_addname)
1369                 dns_message_addname(client->message, fname,
1370                                     DNS_SECTION_ADDITIONAL);
1371         fname = NULL;
1372
1373         /*
1374          * In a few cases, we want to add additional data for additional
1375          * data.  It's simpler to just deal with special cases here than
1376          * to try to create a general purpose mechanism and allow the
1377          * rdata implementations to do it themselves.
1378          *
1379          * This involves recursion, but the depth is limited.  The
1380          * most complex case is adding a SRV rdataset, which involves
1381          * recursing to add address records, which in turn can cause
1382          * recursion to add KEYs.
1383          */
1384         if (type == dns_rdatatype_srv && trdataset != NULL) {
1385                 /*
1386                  * If we're adding SRV records to the additional data
1387                  * section, it's helpful if we add the SRV additional data
1388                  * as well.
1389                  */
1390                 eresult = dns_rdataset_additionaldata(trdataset,
1391                                                       query_addadditional,
1392                                                       client);
1393         }
1394
1395  cleanup:
1396         CTRACE("query_addadditional: cleanup");
1397         query_putrdataset(client, &rdataset);
1398         if (sigrdataset != NULL)
1399                 query_putrdataset(client, &sigrdataset);
1400         if (fname != NULL)
1401                 query_releasename(client, &fname);
1402         if (node != NULL)
1403                 dns_db_detachnode(db, &node);
1404         if (db != NULL)
1405                 dns_db_detach(&db);
1406         if (zone != NULL)
1407                 dns_zone_detach(&zone);
1408
1409         CTRACE("query_addadditional: done");
1410         return (eresult);
1411 }
1412
1413 static inline void
1414 query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base,
1415                    dns_rdatasetadditional_t additionaltype,
1416                    dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp,
1417                    dns_dbversion_t **versionp, dns_dbnode_t **nodep,
1418                    dns_name_t *fname)
1419 {
1420         dns_rdataset_t *rdataset;
1421
1422         while  ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) {
1423                 ISC_LIST_UNLINK(fname->list, rdataset, link);
1424                 query_putrdataset(client, &rdataset);
1425         }
1426         if (*versionp != NULL)
1427                 dns_db_closeversion(*dbp, versionp, ISC_FALSE);
1428         if (*nodep != NULL)
1429                 dns_db_detachnode(*dbp, nodep);
1430         if (*dbp != NULL)
1431                 dns_db_detach(dbp);
1432         if (*zonep != NULL)
1433                 dns_zone_detach(zonep);
1434         (void)dns_rdataset_putadditional(client->view->acache, rdataset_base,
1435                                          additionaltype, type);
1436 }
1437
1438 static inline isc_result_t
1439 query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0,
1440                    dns_dbversion_t *version)
1441 {
1442         isc_result_t result = ISC_R_SUCCESS;
1443         dns_dbversion_t *version_current = NULL;
1444         dns_db_t *db_current = db0;
1445
1446         if (db_current == NULL) {
1447                 result = dns_zone_getdb(zone, &db_current);
1448                 if (result != ISC_R_SUCCESS)
1449                         return (result);
1450         }
1451         dns_db_currentversion(db_current, &version_current);
1452         if (db_current != db || version_current != version) {
1453                 result = ISC_R_FAILURE;
1454                 goto cleanup;
1455         }
1456
1457  cleanup:
1458         dns_db_closeversion(db_current, &version_current, ISC_FALSE);
1459         if (db0 == NULL && db_current != NULL)
1460                 dns_db_detach(&db_current);
1461
1462         return (result);
1463 }
1464
1465 static isc_result_t
1466 query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
1467         client_additionalctx_t *additionalctx = arg;
1468         dns_rdataset_t *rdataset_base;
1469         ns_client_t *client;
1470         isc_result_t result, eresult;
1471         dns_dbnode_t *node, *cnode;
1472         dns_db_t *db, *cdb;
1473         dns_name_t *fname, *mname0, cfname;
1474         dns_rdataset_t *rdataset, *sigrdataset;
1475         dns_rdataset_t *crdataset, *crdataset_next;
1476         isc_buffer_t *dbuf;
1477         isc_buffer_t b;
1478         dns_dbversion_t *version, *cversion;
1479         isc_boolean_t added_something, need_addname, needadditionalcache;
1480         isc_boolean_t need_sigrrset;
1481         dns_zone_t *zone;
1482         dns_rdatatype_t type;
1483         dns_rdatasetadditional_t additionaltype;
1484
1485         if (qtype != dns_rdatatype_a) {
1486                 /*
1487                  * This function is optimized for "address" types.  For other
1488                  * types, use a generic routine.
1489                  * XXX: ideally, this function should be generic enough.
1490                  */
1491                 return (query_addadditional(additionalctx->client,
1492                                             name, qtype));
1493         }
1494
1495         /*
1496          * Initialization.
1497          */
1498         rdataset_base = additionalctx->rdataset;
1499         client = additionalctx->client;
1500         REQUIRE(NS_CLIENT_VALID(client));
1501         eresult = ISC_R_SUCCESS;
1502         fname = NULL;
1503         rdataset = NULL;
1504         sigrdataset = NULL;
1505         db = NULL;
1506         cdb = NULL;
1507         version = NULL;
1508         cversion = NULL;
1509         node = NULL;
1510         cnode = NULL;
1511         added_something = ISC_FALSE;
1512         need_addname = ISC_FALSE;
1513         zone = NULL;
1514         needadditionalcache = ISC_FALSE;
1515         additionaltype = dns_rdatasetadditional_fromauth;
1516         dns_name_init(&cfname, NULL);
1517
1518         CTRACE("query_addadditional2");
1519
1520         /*
1521          * We treat type A additional section processing as if it
1522          * were "any address type" additional section processing.
1523          * To avoid multiple lookups, we do an 'any' database
1524          * lookup and iterate over the node.
1525          * XXXJT: this approach can cause a suboptimal result when the cache
1526          * DB only has partial address types and the glue DB has remaining
1527          * ones.
1528          */
1529         type = dns_rdatatype_any;
1530
1531         /*
1532          * Get some resources.
1533          */
1534         dbuf = query_getnamebuf(client);
1535         if (dbuf == NULL)
1536                 goto cleanup;
1537         fname = query_newname(client, dbuf, &b);
1538         if (fname == NULL)
1539                 goto cleanup;
1540         dns_name_setbuffer(&cfname, &b); /* share the buffer */
1541
1542         /* Check additional cache */
1543         result = dns_rdataset_getadditional(rdataset_base, additionaltype,
1544                                             type, client->view->acache, &zone,
1545                                             &cdb, &cversion, &cnode, &cfname,
1546                                             client->message, client->now);
1547         if (result != ISC_R_SUCCESS)
1548                 goto findauthdb;
1549         if (zone == NULL) {
1550                 CTRACE("query_addadditional2: auth zone not found");
1551                 goto try_cache;
1552         }
1553
1554         /* Is the cached DB up-to-date? */
1555         result = query_iscachevalid(zone, cdb, NULL, cversion);
1556         if (result != ISC_R_SUCCESS) {
1557                 CTRACE("query_addadditional2: old auth additional cache");
1558                 query_discardcache(client, rdataset_base, additionaltype,
1559                                    type, &zone, &cdb, &cversion, &cnode,
1560                                    &cfname);
1561                 goto findauthdb;
1562         }
1563
1564         if (cnode == NULL) {
1565                 /*
1566                  * We have a negative cache.  We don't have to check the zone
1567                  * ACL, since the result (not using this zone) would be same
1568                  * regardless of the result.
1569                  */
1570                 CTRACE("query_addadditional2: negative auth additional cache");
1571                 dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1572                 dns_db_detach(&cdb);
1573                 dns_zone_detach(&zone);
1574                 goto try_cache;
1575         }
1576
1577         result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG,
1578                                       zone, cdb, NULL);
1579         if (result != ISC_R_SUCCESS) {
1580                 query_discardcache(client, rdataset_base, additionaltype,
1581                                    type, &zone, &cdb, &cversion, &cnode,
1582                                    &cfname);
1583                 goto try_cache;
1584         }
1585
1586         /* We've got an active cache. */
1587         CTRACE("query_addadditional2: auth additional cache");
1588         dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1589         db = cdb;
1590         node = cnode;
1591         dns_name_clone(&cfname, fname);
1592         query_keepname(client, fname, dbuf);
1593         goto foundcache;
1594
1595         /*
1596          * Look for a zone database that might contain authoritative
1597          * additional data.
1598          */
1599  findauthdb:
1600         result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
1601                                  &zone, &db, &version);
1602         if (result != ISC_R_SUCCESS) {
1603                 /* Cache the negative result */
1604                 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1605                                                  type, client->view->acache,
1606                                                  NULL, NULL, NULL, NULL,
1607                                                  NULL);
1608                 goto try_cache;
1609         }
1610
1611         CTRACE("query_addadditional2: db_find");
1612
1613         /*
1614          * Since we are looking for authoritative data, we do not set
1615          * the GLUEOK flag.  Glue will be looked for later, but not
1616          * necessarily in the same database.
1617          */
1618         node = NULL;
1619         result = dns_db_find(db, name, version, type, client->query.dboptions,
1620                              client->now, &node, fname, NULL, NULL);
1621         if (result == ISC_R_SUCCESS)
1622                 goto found;
1623
1624         /* Cache the negative result */
1625         (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1626                                          type, client->view->acache, zone, db,
1627                                          version, NULL, fname);
1628
1629         if (node != NULL)
1630                 dns_db_detachnode(db, &node);
1631         version = NULL;
1632         dns_db_detach(&db);
1633
1634         /*
1635          * No authoritative data was found.  The cache is our next best bet.
1636          */
1637
1638  try_cache:
1639         additionaltype = dns_rdatasetadditional_fromcache;
1640         result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
1641         if (result != ISC_R_SUCCESS)
1642                 /*
1643                  * Most likely the client isn't allowed to query the cache.
1644                  */
1645                 goto try_glue;
1646
1647         result = dns_db_find(db, name, version, type,
1648                              client->query.dboptions | DNS_DBFIND_GLUEOK,
1649                              client->now, &node, fname, NULL, NULL);
1650         if (result == ISC_R_SUCCESS)
1651                 goto found;
1652
1653         if (node != NULL)
1654                 dns_db_detachnode(db, &node);
1655         dns_db_detach(&db);
1656
1657  try_glue:
1658         /*
1659          * No cached data was found.  Glue is our last chance.
1660          * RFC1035 sayeth:
1661          *
1662          *      NS records cause both the usual additional section
1663          *      processing to locate a type A record, and, when used
1664          *      in a referral, a special search of the zone in which
1665          *      they reside for glue information.
1666          *
1667          * This is the "special search".  Note that we must search
1668          * the zone where the NS record resides, not the zone it
1669          * points to, and that we only do the search in the delegation
1670          * case (identified by client->query.gluedb being set).
1671          */
1672         if (client->query.gluedb == NULL)
1673                 goto cleanup;
1674
1675         /*
1676          * Don't poison caches using the bailiwick protection model.
1677          */
1678         if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
1679                 goto cleanup;
1680
1681         /* Check additional cache */
1682         additionaltype = dns_rdatasetadditional_fromglue;
1683         result = dns_rdataset_getadditional(rdataset_base, additionaltype,
1684                                             type, client->view->acache, NULL,
1685                                             &cdb, &cversion, &cnode, &cfname,
1686                                             client->message, client->now);
1687         if (result != ISC_R_SUCCESS)
1688                 goto findglue;
1689
1690         result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion);
1691         if (result != ISC_R_SUCCESS) {
1692                 CTRACE("query_addadditional2: old glue additional cache");
1693                 query_discardcache(client, rdataset_base, additionaltype,
1694                                    type, &zone, &cdb, &cversion, &cnode,
1695                                    &cfname);
1696                 goto findglue;
1697         }
1698
1699         if (cnode == NULL) {
1700                 /* We have a negative cache. */
1701                 CTRACE("query_addadditional2: negative glue additional cache");
1702                 dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1703                 dns_db_detach(&cdb);
1704                 goto cleanup;
1705         }
1706
1707         /* Cache hit. */
1708         CTRACE("query_addadditional2: glue additional cache");
1709         dns_db_closeversion(cdb, &cversion, ISC_FALSE);
1710         db = cdb;
1711         node = cnode;
1712         dns_name_clone(&cfname, fname);
1713         query_keepname(client, fname, dbuf);
1714         goto foundcache;
1715
1716  findglue:
1717         dns_db_attach(client->query.gluedb, &db);
1718         result = dns_db_find(db, name, version, type,
1719                              client->query.dboptions | DNS_DBFIND_GLUEOK,
1720                              client->now, &node, fname, NULL, NULL);
1721         if (!(result == ISC_R_SUCCESS ||
1722               result == DNS_R_ZONECUT ||
1723               result == DNS_R_GLUE)) {
1724                 /* cache the negative result */
1725                 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1726                                                  type, client->view->acache,
1727                                                  NULL, db, version, NULL,
1728                                                  fname);
1729                 goto cleanup;
1730         }
1731
1732  found:
1733         /*
1734          * We have found a DB node to iterate over from a DB.
1735          * We are going to look for address RRsets (i.e., A and AAAA) in the DB
1736          * node we've just found.  We'll then store the complete information
1737          * in the additional data cache.
1738          */
1739         dns_name_clone(fname, &cfname);
1740         query_keepname(client, fname, dbuf);
1741         needadditionalcache = ISC_TRUE;
1742
1743         rdataset = query_newrdataset(client);
1744         if (rdataset == NULL)
1745                 goto cleanup;
1746
1747         sigrdataset = query_newrdataset(client);
1748         if (sigrdataset == NULL)
1749                 goto cleanup;
1750
1751         /*
1752          * Find A RRset with sig RRset.  Even if we don't find a sig RRset
1753          * for a client using DNSSEC, we'll continue the process to make a
1754          * complete list to be cached.  However, we need to cancel the
1755          * caching when something unexpected happens, in order to avoid
1756          * caching incomplete information.
1757          */
1758         result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0,
1759                                      client->now, rdataset, sigrdataset);
1760         /*
1761          * If we can't promote glue/pending from the cache to secure
1762          * then drop it.
1763          */
1764         if (result == ISC_R_SUCCESS &&
1765             additionaltype == dns_rdatasetadditional_fromcache &&
1766             (DNS_TRUST_PENDING(rdataset->trust) ||
1767              DNS_TRUST_GLUE(rdataset->trust)) &&
1768             !validate(client, db, fname, rdataset, sigrdataset)) {
1769                 dns_rdataset_disassociate(rdataset);
1770                 if (dns_rdataset_isassociated(sigrdataset))
1771                         dns_rdataset_disassociate(sigrdataset);
1772                 result = ISC_R_NOTFOUND;
1773         }
1774         if (result == DNS_R_NCACHENXDOMAIN)
1775                 goto setcache;
1776         if (result == DNS_R_NCACHENXRRSET) {
1777                 dns_rdataset_disassociate(rdataset);
1778                 /*
1779                  * Negative cache entries don't have sigrdatasets.
1780                  */
1781                 INSIST(! dns_rdataset_isassociated(sigrdataset));
1782         }
1783         if (result == ISC_R_SUCCESS) {
1784                 /* Remember the result as a cache */
1785                 ISC_LIST_APPEND(cfname.list, rdataset, link);
1786                 if (dns_rdataset_isassociated(sigrdataset)) {
1787                         ISC_LIST_APPEND(cfname.list, sigrdataset, link);
1788                         sigrdataset = query_newrdataset(client);
1789                 }
1790                 rdataset = query_newrdataset(client);
1791                 if (sigrdataset == NULL || rdataset == NULL) {
1792                         /* do not cache incomplete information */
1793                         goto foundcache;
1794                 }
1795         }
1796
1797         /* Find AAAA RRset with sig RRset */
1798         result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa,
1799                                      0, client->now, rdataset, sigrdataset);
1800         /*
1801          * If we can't promote glue/pending from the cache to secure
1802          * then drop it.
1803          */
1804         if (result == ISC_R_SUCCESS &&
1805             additionaltype == dns_rdatasetadditional_fromcache &&
1806             (DNS_TRUST_PENDING(rdataset->trust) ||
1807              DNS_TRUST_GLUE(rdataset->trust)) &&
1808             !validate(client, db, fname, rdataset, sigrdataset)) {
1809                 dns_rdataset_disassociate(rdataset);
1810                 if (dns_rdataset_isassociated(sigrdataset))
1811                         dns_rdataset_disassociate(sigrdataset);
1812                 result = ISC_R_NOTFOUND;
1813         }
1814         if (result == ISC_R_SUCCESS) {
1815                 ISC_LIST_APPEND(cfname.list, rdataset, link);
1816                 rdataset = NULL;
1817                 if (dns_rdataset_isassociated(sigrdataset)) {
1818                         ISC_LIST_APPEND(cfname.list, sigrdataset, link);
1819                         sigrdataset = NULL;
1820                 }
1821         }
1822
1823  setcache:
1824         /*
1825          * Set the new result in the cache if required.  We do not support
1826          * caching additional data from a cache DB.
1827          */
1828         if (needadditionalcache == ISC_TRUE &&
1829             (additionaltype == dns_rdatasetadditional_fromauth ||
1830              additionaltype == dns_rdatasetadditional_fromglue)) {
1831                 (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
1832                                                  type, client->view->acache,
1833                                                  zone, db, version, node,
1834                                                  &cfname);
1835         }
1836
1837  foundcache:
1838         need_sigrrset = ISC_FALSE;
1839         mname0 = NULL;
1840         for (crdataset = ISC_LIST_HEAD(cfname.list);
1841              crdataset != NULL;
1842              crdataset = crdataset_next) {
1843                 dns_name_t *mname;
1844
1845                 crdataset_next = ISC_LIST_NEXT(crdataset, link);
1846
1847                 mname = NULL;
1848                 if (crdataset->type == dns_rdatatype_a ||
1849                     crdataset->type == dns_rdatatype_aaaa) {
1850                         if (!query_isduplicate(client, fname, crdataset->type,
1851                                                &mname)) {
1852                                 if (mname != NULL) {
1853                                         /*
1854                                          * A different type of this name is
1855                                          * already stored in the additional
1856                                          * section.  We'll reuse the name.
1857                                          * Note that this should happen at most
1858                                          * once.  Otherwise, fname->link could
1859                                          * leak below.
1860                                          */
1861                                         INSIST(mname0 == NULL);
1862
1863                                         query_releasename(client, &fname);
1864                                         fname = mname;
1865                                         mname0 = mname;
1866                                 } else
1867                                         need_addname = ISC_TRUE;
1868                                 ISC_LIST_UNLINK(cfname.list, crdataset, link);
1869                                 ISC_LIST_APPEND(fname->list, crdataset, link);
1870                                 added_something = ISC_TRUE;
1871                                 need_sigrrset = ISC_TRUE;
1872                         } else
1873                                 need_sigrrset = ISC_FALSE;
1874                 } else if (crdataset->type == dns_rdatatype_rrsig &&
1875                            need_sigrrset && WANTDNSSEC(client)) {
1876                         ISC_LIST_UNLINK(cfname.list, crdataset, link);
1877                         ISC_LIST_APPEND(fname->list, crdataset, link);
1878                         added_something = ISC_TRUE; /* just in case */
1879                         need_sigrrset = ISC_FALSE;
1880                 }
1881         }
1882
1883         CTRACE("query_addadditional2: addname");
1884
1885         /*
1886          * If we haven't added anything, then we're done.
1887          */
1888         if (!added_something)
1889                 goto cleanup;
1890
1891         /*
1892          * We may have added our rdatasets to an existing name, if so, then
1893          * need_addname will be ISC_FALSE.  Whether we used an existing name
1894          * or a new one, we must set fname to NULL to prevent cleanup.
1895          */
1896         if (need_addname)
1897                 dns_message_addname(client->message, fname,
1898                                     DNS_SECTION_ADDITIONAL);
1899         fname = NULL;
1900
1901  cleanup:
1902         CTRACE("query_addadditional2: cleanup");
1903
1904         if (rdataset != NULL)
1905                 query_putrdataset(client, &rdataset);
1906         if (sigrdataset != NULL)
1907                 query_putrdataset(client, &sigrdataset);
1908         while  ((crdataset = ISC_LIST_HEAD(cfname.list)) != NULL) {
1909                 ISC_LIST_UNLINK(cfname.list, crdataset, link);
1910                 query_putrdataset(client, &crdataset);
1911         }
1912         if (fname != NULL)
1913                 query_releasename(client, &fname);
1914         if (node != NULL)
1915                 dns_db_detachnode(db, &node);
1916         if (db != NULL)
1917                 dns_db_detach(&db);
1918         if (zone != NULL)
1919                 dns_zone_detach(&zone);
1920
1921         CTRACE("query_addadditional2: done");
1922         return (eresult);
1923 }
1924
1925 static inline void
1926 query_addrdataset(ns_client_t *client, dns_name_t *fname,
1927                   dns_rdataset_t *rdataset)
1928 {
1929         client_additionalctx_t additionalctx;
1930
1931         /*
1932          * Add 'rdataset' and any pertinent additional data to
1933          * 'fname', a name in the response message for 'client'.
1934          */
1935
1936         CTRACE("query_addrdataset");
1937
1938         ISC_LIST_APPEND(fname->list, rdataset, link);
1939
1940         if (client->view->order != NULL)
1941                 rdataset->attributes |= dns_order_find(client->view->order,
1942                                                        fname, rdataset->type,
1943                                                        rdataset->rdclass);
1944         rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
1945
1946         if (NOADDITIONAL(client))
1947                 return;
1948
1949         /*
1950          * Add additional data.
1951          *
1952          * We don't care if dns_rdataset_additionaldata() fails.
1953          */
1954         additionalctx.client = client;
1955         additionalctx.rdataset = rdataset;
1956         (void)dns_rdataset_additionaldata(rdataset, query_addadditional2,
1957                                           &additionalctx);
1958         CTRACE("query_addrdataset: done");
1959 }
1960
1961 static void
1962 query_addrrset(ns_client_t *client, dns_name_t **namep,
1963                dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
1964                isc_buffer_t *dbuf, dns_section_t section)
1965 {
1966         dns_name_t *name, *mname;
1967         dns_rdataset_t *rdataset, *mrdataset, *sigrdataset;
1968         isc_result_t result;
1969
1970         /*%
1971          * To the current response for 'client', add the answer RRset
1972          * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
1973          * owner name '*namep', to section 'section', unless they are
1974          * already there.  Also add any pertinent additional data.
1975          *
1976          * If 'dbuf' is not NULL, then '*namep' is the name whose data is
1977          * stored in 'dbuf'.  In this case, query_addrrset() guarantees that
1978          * when it returns the name will either have been kept or released.
1979          */
1980         CTRACE("query_addrrset");
1981         name = *namep;
1982         rdataset = *rdatasetp;
1983         if (sigrdatasetp != NULL)
1984                 sigrdataset = *sigrdatasetp;
1985         else
1986                 sigrdataset = NULL;
1987         mname = NULL;
1988         mrdataset = NULL;
1989         result = dns_message_findname(client->message, section,
1990                                       name, rdataset->type, rdataset->covers,
1991                                       &mname, &mrdataset);
1992         if (result == ISC_R_SUCCESS) {
1993                 /*
1994                  * We've already got an RRset of the given name and type.
1995                  * There's nothing else to do;
1996                  */
1997                 CTRACE("query_addrrset: dns_message_findname succeeded: done");
1998                 if (dbuf != NULL)
1999                         query_releasename(client, namep);
2000                 return;
2001         } else if (result == DNS_R_NXDOMAIN) {
2002                 /*
2003                  * The name doesn't exist.
2004                  */
2005                 if (dbuf != NULL)
2006                         query_keepname(client, name, dbuf);
2007                 dns_message_addname(client->message, name, section);
2008                 *namep = NULL;
2009                 mname = name;
2010         } else {
2011                 RUNTIME_CHECK(result == DNS_R_NXRRSET);
2012                 if (dbuf != NULL)
2013                         query_releasename(client, namep);
2014         }
2015
2016         if (rdataset->trust != dns_trust_secure &&
2017             (section == DNS_SECTION_ANSWER ||
2018              section == DNS_SECTION_AUTHORITY))
2019                 client->query.attributes &= ~NS_QUERYATTR_SECURE;
2020         /*
2021          * Note: we only add SIGs if we've added the type they cover, so
2022          * we do not need to check if the SIG rdataset is already in the
2023          * response.
2024          */
2025         query_addrdataset(client, mname, rdataset);
2026         *rdatasetp = NULL;
2027         if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
2028                 /*
2029                  * We have a signature.  Add it to the response.
2030                  */
2031                 ISC_LIST_APPEND(mname->list, sigrdataset, link);
2032                 *sigrdatasetp = NULL;
2033         }
2034         CTRACE("query_addrrset: done");
2035 }
2036
2037 static inline isc_result_t
2038 query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
2039              isc_boolean_t zero_ttl)
2040 {
2041         dns_name_t *name;
2042         dns_dbnode_t *node;
2043         isc_result_t result, eresult;
2044         dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2045         dns_rdataset_t **sigrdatasetp = NULL;
2046
2047         CTRACE("query_addsoa");
2048         /*
2049          * Initialization.
2050          */
2051         eresult = ISC_R_SUCCESS;
2052         name = NULL;
2053         rdataset = NULL;
2054         node = NULL;
2055
2056         /*
2057          * Get resources and make 'name' be the database origin.
2058          */
2059         result = dns_message_gettempname(client->message, &name);
2060         if (result != ISC_R_SUCCESS)
2061                 return (result);
2062         dns_name_init(name, NULL);
2063         dns_name_clone(dns_db_origin(db), name);
2064         rdataset = query_newrdataset(client);
2065         if (rdataset == NULL) {
2066                 eresult = DNS_R_SERVFAIL;
2067                 goto cleanup;
2068         }
2069         if (WANTDNSSEC(client) && dns_db_issecure(db)) {
2070                 sigrdataset = query_newrdataset(client);
2071                 if (sigrdataset == NULL) {
2072                         eresult = DNS_R_SERVFAIL;
2073                         goto cleanup;
2074                 }
2075         }
2076
2077         /*
2078          * Find the SOA.
2079          */
2080         result = dns_db_getoriginnode(db, &node);
2081         if (result == ISC_R_SUCCESS) {
2082                 result = dns_db_findrdataset(db, node, version,
2083                                              dns_rdatatype_soa,
2084                                              0, client->now, rdataset,
2085                                              sigrdataset);
2086         } else {
2087                 dns_fixedname_t foundname;
2088                 dns_name_t *fname;
2089
2090                 dns_fixedname_init(&foundname);
2091                 fname = dns_fixedname_name(&foundname);
2092
2093                 result = dns_db_find(db, name, version, dns_rdatatype_soa,
2094                                      client->query.dboptions, 0, &node,
2095                                      fname, rdataset, sigrdataset);
2096         }
2097         if (result != ISC_R_SUCCESS) {
2098                 /*
2099                  * This is bad.  We tried to get the SOA RR at the zone top
2100                  * and it didn't work!
2101                  */
2102                 eresult = DNS_R_SERVFAIL;
2103         } else {
2104                 /*
2105                  * Extract the SOA MINIMUM.
2106                  */
2107                 dns_rdata_soa_t soa;
2108                 dns_rdata_t rdata = DNS_RDATA_INIT;
2109                 result = dns_rdataset_first(rdataset);
2110                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2111                 dns_rdataset_current(rdataset, &rdata);
2112                 result = dns_rdata_tostruct(&rdata, &soa, NULL);
2113                 if (result != ISC_R_SUCCESS)
2114                         goto cleanup;
2115
2116                 if (zero_ttl) {
2117                         rdataset->ttl = 0;
2118                         if (sigrdataset != NULL)
2119                                 sigrdataset->ttl = 0;
2120                 }
2121
2122                 /*
2123                  * Add the SOA and its SIG to the response, with the
2124                  * TTLs adjusted per RFC2308 section 3.
2125                  */
2126                 if (rdataset->ttl > soa.minimum)
2127                         rdataset->ttl = soa.minimum;
2128                 if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum)
2129                         sigrdataset->ttl = soa.minimum;
2130
2131                 if (sigrdataset != NULL)
2132                         sigrdatasetp = &sigrdataset;
2133                 else
2134                         sigrdatasetp = NULL;
2135                 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
2136                                DNS_SECTION_AUTHORITY);
2137         }
2138
2139  cleanup:
2140         query_putrdataset(client, &rdataset);
2141         if (sigrdataset != NULL)
2142                 query_putrdataset(client, &sigrdataset);
2143         if (name != NULL)
2144                 query_releasename(client, &name);
2145         if (node != NULL)
2146                 dns_db_detachnode(db, &node);
2147
2148         return (eresult);
2149 }
2150
2151 static inline isc_result_t
2152 query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
2153         dns_name_t *name, *fname;
2154         dns_dbnode_t *node;
2155         isc_result_t result, eresult;
2156         dns_fixedname_t foundname;
2157         dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2158         dns_rdataset_t **sigrdatasetp = NULL;
2159
2160         CTRACE("query_addns");
2161         /*
2162          * Initialization.
2163          */
2164         eresult = ISC_R_SUCCESS;
2165         name = NULL;
2166         rdataset = NULL;
2167         node = NULL;
2168         dns_fixedname_init(&foundname);
2169         fname = dns_fixedname_name(&foundname);
2170
2171         /*
2172          * Get resources and make 'name' be the database origin.
2173          */
2174         result = dns_message_gettempname(client->message, &name);
2175         if (result != ISC_R_SUCCESS) {
2176                 CTRACE("query_addns: dns_message_gettempname failed: done");
2177                 return (result);
2178         }
2179         dns_name_init(name, NULL);
2180         dns_name_clone(dns_db_origin(db), name);
2181         rdataset = query_newrdataset(client);
2182         if (rdataset == NULL) {
2183                 CTRACE("query_addns: query_newrdataset failed");
2184                 eresult = DNS_R_SERVFAIL;
2185                 goto cleanup;
2186         }
2187         if (WANTDNSSEC(client) && dns_db_issecure(db)) {
2188                 sigrdataset = query_newrdataset(client);
2189                 if (sigrdataset == NULL) {
2190                         CTRACE("query_addns: query_newrdataset failed");
2191                         eresult = DNS_R_SERVFAIL;
2192                         goto cleanup;
2193                 }
2194         }
2195
2196         /*
2197          * Find the NS rdataset.
2198          */
2199         result = dns_db_getoriginnode(db, &node);
2200         if (result == ISC_R_SUCCESS) {
2201                 result = dns_db_findrdataset(db, node, version,
2202                                              dns_rdatatype_ns,
2203                                              0, client->now, rdataset,
2204                                              sigrdataset);
2205         } else {
2206                 CTRACE("query_addns: calling dns_db_find");
2207                 result = dns_db_find(db, name, NULL, dns_rdatatype_ns,
2208                                      client->query.dboptions, 0, &node,
2209                                      fname, rdataset, sigrdataset);
2210                 CTRACE("query_addns: dns_db_find complete");
2211         }
2212         if (result != ISC_R_SUCCESS) {
2213                 CTRACE("query_addns: "
2214                        "dns_db_findrdataset or dns_db_find failed");
2215                 /*
2216                  * This is bad.  We tried to get the NS rdataset at the zone
2217                  * top and it didn't work!
2218                  */
2219                 eresult = DNS_R_SERVFAIL;
2220         } else {
2221                 if (sigrdataset != NULL)
2222                         sigrdatasetp = &sigrdataset;
2223                 else
2224                         sigrdatasetp = NULL;
2225                 query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
2226                                DNS_SECTION_AUTHORITY);
2227         }
2228
2229  cleanup:
2230         CTRACE("query_addns: cleanup");
2231         query_putrdataset(client, &rdataset);
2232         if (sigrdataset != NULL)
2233                 query_putrdataset(client, &sigrdataset);
2234         if (name != NULL)
2235                 query_releasename(client, &name);
2236         if (node != NULL)
2237                 dns_db_detachnode(db, &node);
2238
2239         CTRACE("query_addns: done");
2240         return (eresult);
2241 }
2242
2243 static inline isc_result_t
2244 query_addcnamelike(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
2245                    dns_trust_t trust, dns_name_t **anamep, dns_rdatatype_t type)
2246 {
2247         dns_rdataset_t *rdataset;
2248         dns_rdatalist_t *rdatalist;
2249         dns_rdata_t *rdata;
2250         isc_result_t result;
2251         isc_region_t r;
2252
2253         /*
2254          * We assume the name data referred to by tname won't go away.
2255          */
2256
2257         REQUIRE(anamep != NULL);
2258
2259         rdatalist = NULL;
2260         result = dns_message_gettemprdatalist(client->message, &rdatalist);
2261         if (result != ISC_R_SUCCESS)
2262                 return (result);
2263         rdata = NULL;
2264         result = dns_message_gettemprdata(client->message, &rdata);
2265         if (result != ISC_R_SUCCESS)
2266                 return (result);
2267         rdataset = NULL;
2268         result = dns_message_gettemprdataset(client->message, &rdataset);
2269         if (result != ISC_R_SUCCESS)
2270                 return (result);
2271         dns_rdataset_init(rdataset);
2272         result = dns_name_dup(qname, client->mctx, *anamep);
2273         if (result != ISC_R_SUCCESS) {
2274                 dns_message_puttemprdataset(client->message, &rdataset);
2275                 return (result);
2276         }
2277
2278         rdatalist->type = type;
2279         rdatalist->covers = 0;
2280         rdatalist->rdclass = client->message->rdclass;
2281         rdatalist->ttl = 0;
2282
2283         dns_name_toregion(tname, &r);
2284         rdata->data = r.base;
2285         rdata->length = r.length;
2286         rdata->rdclass = client->message->rdclass;
2287         rdata->type = type;
2288
2289         ISC_LIST_INIT(rdatalist->rdata);
2290         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2291         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
2292                       == ISC_R_SUCCESS);
2293         rdataset->trust = trust;
2294
2295         query_addrrset(client, anamep, &rdataset, NULL, NULL,
2296                        DNS_SECTION_ANSWER);
2297
2298         if (rdataset != NULL) {
2299                 if (dns_rdataset_isassociated(rdataset))
2300                         dns_rdataset_disassociate(rdataset);
2301                 dns_message_puttemprdataset(client->message, &rdataset);
2302         }
2303
2304         return (ISC_R_SUCCESS);
2305 }
2306
2307 /*
2308  * Mark the RRsets as secure.  Update the cache (db) to reflect the
2309  * change in trust level.
2310  */
2311 static void
2312 mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
2313             isc_uint32_t ttl, dns_rdataset_t *rdataset,
2314             dns_rdataset_t *sigrdataset)
2315 {
2316         isc_result_t result;
2317         dns_dbnode_t *node = NULL;
2318
2319         rdataset->trust = dns_trust_secure;
2320         sigrdataset->trust = dns_trust_secure;
2321
2322         /*
2323          * Save the updated secure state.  Ignore failures.
2324          */
2325         result = dns_db_findnode(db, name, ISC_TRUE, &node);
2326         if (result != ISC_R_SUCCESS)
2327                 return;
2328         /*
2329          * Bound the validated ttls then minimise.
2330          */
2331         if (sigrdataset->ttl > ttl)
2332                 sigrdataset->ttl = ttl;
2333         if (rdataset->ttl > ttl)
2334                 rdataset->ttl = ttl;
2335         if (rdataset->ttl > sigrdataset->ttl)
2336                 rdataset->ttl = sigrdataset->ttl;
2337         else
2338                 sigrdataset->ttl = rdataset->ttl;
2339
2340         (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset,
2341                                  0, NULL);
2342         (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset,
2343                                  0, NULL);
2344         dns_db_detachnode(db, &node);
2345 }
2346
2347 /*
2348  * Find the secure key that corresponds to rrsig.
2349  * Note: 'keyrdataset' maintains state between successive calls,
2350  * there may be multiple keys with the same keyid.
2351  * Return ISC_FALSE if we have exhausted all the possible keys.
2352  */
2353 static isc_boolean_t
2354 get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
2355         dns_rdataset_t *keyrdataset, dst_key_t **keyp)
2356 {
2357         isc_result_t result;
2358         dns_dbnode_t *node = NULL;
2359         isc_boolean_t secure = ISC_FALSE;
2360
2361         if (!dns_rdataset_isassociated(keyrdataset)) {
2362                 result = dns_db_findnode(db, &rrsig->signer, ISC_FALSE, &node);
2363                 if (result != ISC_R_SUCCESS)
2364                         return (ISC_FALSE);
2365
2366                 result = dns_db_findrdataset(db, node, NULL,
2367                                              dns_rdatatype_dnskey, 0,
2368                                              client->now, keyrdataset, NULL);
2369                 dns_db_detachnode(db, &node);
2370                 if (result != ISC_R_SUCCESS)
2371                         return (ISC_FALSE);
2372
2373                 if (keyrdataset->trust != dns_trust_secure)
2374                         return (ISC_FALSE);
2375
2376                 result = dns_rdataset_first(keyrdataset);
2377         } else
2378                 result = dns_rdataset_next(keyrdataset);
2379
2380         for ( ; result == ISC_R_SUCCESS;
2381              result = dns_rdataset_next(keyrdataset)) {
2382                 dns_rdata_t rdata = DNS_RDATA_INIT;
2383                 isc_buffer_t b;
2384
2385                 dns_rdataset_current(keyrdataset, &rdata);
2386                 isc_buffer_init(&b, rdata.data, rdata.length);
2387                 isc_buffer_add(&b, rdata.length);
2388                 result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
2389                                          client->mctx, keyp);
2390                 if (result != ISC_R_SUCCESS)
2391                         continue;
2392                 if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
2393                     rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
2394                     dst_key_iszonekey(*keyp)) {
2395                         secure = ISC_TRUE;
2396                         break;
2397                 }
2398                 dst_key_free(keyp);
2399         }
2400         return (secure);
2401 }
2402
2403 static isc_boolean_t
2404 verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,
2405        dns_rdata_t *rdata, isc_mem_t *mctx, isc_boolean_t acceptexpired)
2406 {
2407         isc_result_t result;
2408         dns_fixedname_t fixed;
2409         isc_boolean_t ignore = ISC_FALSE;
2410
2411         dns_fixedname_init(&fixed);
2412
2413 again:
2414         result = dns_dnssec_verify2(name, rdataset, key, ignore, mctx,
2415                                     rdata, NULL);
2416         if (result == DNS_R_SIGEXPIRED && acceptexpired) {
2417                 ignore = ISC_TRUE;
2418                 goto again;
2419         }
2420         if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD)
2421                 return (ISC_TRUE);
2422         return (ISC_FALSE);
2423 }
2424
2425 /*
2426  * Validate the rdataset if possible with available records.
2427  */
2428 static isc_boolean_t
2429 validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
2430          dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
2431 {
2432         isc_result_t result;
2433         dns_rdata_t rdata = DNS_RDATA_INIT;
2434         dns_rdata_rrsig_t rrsig;
2435         dst_key_t *key = NULL;
2436         dns_rdataset_t keyrdataset;
2437
2438         if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
2439                 return (ISC_FALSE);
2440
2441         for (result = dns_rdataset_first(sigrdataset);
2442              result == ISC_R_SUCCESS;
2443              result = dns_rdataset_next(sigrdataset)) {
2444
2445                 dns_rdata_reset(&rdata);
2446                 dns_rdataset_current(sigrdataset, &rdata);
2447                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
2448                 if (result != ISC_R_SUCCESS)
2449                         return (ISC_FALSE);
2450                 if (!dns_resolver_algorithm_supported(client->view->resolver,
2451                                                       name, rrsig.algorithm))
2452                         continue;
2453                 if (!dns_name_issubdomain(name, &rrsig.signer))
2454                         continue;
2455                 dns_rdataset_init(&keyrdataset);
2456                 do {
2457                         if (!get_key(client, db, &rrsig, &keyrdataset, &key))
2458                                 break;
2459                         if (verify(key, name, rdataset, &rdata, client->mctx,
2460                                    client->view->acceptexpired)) {
2461                                 dst_key_free(&key);
2462                                 dns_rdataset_disassociate(&keyrdataset);
2463                                 mark_secure(client, db, name,
2464                                             rrsig.originalttl,
2465                                             rdataset, sigrdataset);
2466                                 return (ISC_TRUE);
2467                         }
2468                         dst_key_free(&key);
2469                 } while (1);
2470                 if (dns_rdataset_isassociated(&keyrdataset))
2471                         dns_rdataset_disassociate(&keyrdataset);
2472         }
2473         return (ISC_FALSE);
2474 }
2475
2476 static void
2477 query_addbestns(ns_client_t *client) {
2478         dns_db_t *db, *zdb;
2479         dns_dbnode_t *node;
2480         dns_name_t *fname, *zfname;
2481         dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset;
2482         isc_boolean_t is_zone, use_zone;
2483         isc_buffer_t *dbuf;
2484         isc_result_t result;
2485         dns_dbversion_t *version;
2486         dns_zone_t *zone;
2487         isc_buffer_t b;
2488
2489         CTRACE("query_addbestns");
2490         fname = NULL;
2491         zfname = NULL;
2492         rdataset = NULL;
2493         zrdataset = NULL;
2494         sigrdataset = NULL;
2495         zsigrdataset = NULL;
2496         node = NULL;
2497         db = NULL;
2498         zdb = NULL;
2499         version = NULL;
2500         zone = NULL;
2501         is_zone = ISC_FALSE;
2502         use_zone = ISC_FALSE;
2503
2504         /*
2505          * Find the right database.
2506          */
2507         result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0,
2508                              &zone, &db, &version, &is_zone);
2509         if (result != ISC_R_SUCCESS)
2510                 goto cleanup;
2511
2512  db_find:
2513         /*
2514          * We'll need some resources...
2515          */
2516         dbuf = query_getnamebuf(client);
2517         if (dbuf == NULL)
2518                 goto cleanup;
2519         fname = query_newname(client, dbuf, &b);
2520         rdataset = query_newrdataset(client);
2521         if (fname == NULL || rdataset == NULL)
2522                 goto cleanup;
2523         /*
2524          * Get the RRSIGs if the client requested them or if we may
2525          * need to validate answers from the cache.
2526          */
2527         if (WANTDNSSEC(client) || !is_zone) {
2528                 sigrdataset = query_newrdataset(client);
2529                 if (sigrdataset == NULL)
2530                         goto cleanup;
2531         }
2532
2533         /*
2534          * Now look for the zonecut.
2535          */
2536         if (is_zone) {
2537                 result = dns_db_find(db, client->query.qname, version,
2538                                      dns_rdatatype_ns, client->query.dboptions,
2539                                      client->now, &node, fname,
2540                                      rdataset, sigrdataset);
2541                 if (result != DNS_R_DELEGATION)
2542                         goto cleanup;
2543                 if (USECACHE(client)) {
2544                         query_keepname(client, fname, dbuf);
2545                         zdb = db;
2546                         zfname = fname;
2547                         fname = NULL;
2548                         zrdataset = rdataset;
2549                         rdataset = NULL;
2550                         zsigrdataset = sigrdataset;
2551                         sigrdataset = NULL;
2552                         dns_db_detachnode(db, &node);
2553                         version = NULL;
2554                         db = NULL;
2555                         dns_db_attach(client->view->cachedb, &db);
2556                         is_zone = ISC_FALSE;
2557                         goto db_find;
2558                 }
2559         } else {
2560                 result = dns_db_findzonecut(db, client->query.qname,
2561                                             client->query.dboptions,
2562                                             client->now, &node, fname,
2563                                             rdataset, sigrdataset);
2564                 if (result == ISC_R_SUCCESS) {
2565                         if (zfname != NULL &&
2566                             !dns_name_issubdomain(fname, zfname)) {
2567                                 /*
2568                                  * We found a zonecut in the cache, but our
2569                                  * zone delegation is better.
2570                                  */
2571                                 use_zone = ISC_TRUE;
2572                         }
2573                 } else if (result == ISC_R_NOTFOUND && zfname != NULL) {
2574                         /*
2575                          * We didn't find anything in the cache, but we
2576                          * have a zone delegation, so use it.
2577                          */
2578                         use_zone = ISC_TRUE;
2579                 } else
2580                         goto cleanup;
2581         }
2582
2583         if (use_zone) {
2584                 query_releasename(client, &fname);
2585                 fname = zfname;
2586                 zfname = NULL;
2587                 /*
2588                  * We've already done query_keepname() on
2589                  * zfname, so we must set dbuf to NULL to
2590                  * prevent query_addrrset() from trying to
2591                  * call query_keepname() again.
2592                  */
2593                 dbuf = NULL;
2594                 query_putrdataset(client, &rdataset);
2595                 if (sigrdataset != NULL)
2596                         query_putrdataset(client, &sigrdataset);
2597                 rdataset = zrdataset;
2598                 zrdataset = NULL;
2599                 sigrdataset = zsigrdataset;
2600                 zsigrdataset = NULL;
2601         }
2602
2603         /*
2604          * Attempt to validate RRsets that are pending or that are glue.
2605          */
2606         if ((DNS_TRUST_PENDING(rdataset->trust) ||
2607              (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust)))
2608             && !validate(client, db, fname, rdataset, sigrdataset) &&
2609             !PENDINGOK(client->query.dboptions))
2610                 goto cleanup;
2611
2612         if ((DNS_TRUST_GLUE(rdataset->trust) ||
2613              (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
2614             !validate(client, db, fname, rdataset, sigrdataset) &&
2615             SECURE(client) && WANTDNSSEC(client))
2616                 goto cleanup;
2617
2618         /*
2619          * If the client doesn't want DNSSEC we can discard the sigrdataset
2620          * now.
2621          */
2622         if (!WANTDNSSEC(client))
2623                 query_putrdataset(client, &sigrdataset);
2624         query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
2625                        DNS_SECTION_AUTHORITY);
2626
2627  cleanup:
2628         if (rdataset != NULL)
2629                 query_putrdataset(client, &rdataset);
2630         if (sigrdataset != NULL)
2631                 query_putrdataset(client, &sigrdataset);
2632         if (fname != NULL)
2633                 query_releasename(client, &fname);
2634         if (node != NULL)
2635                 dns_db_detachnode(db, &node);
2636         if (db != NULL)
2637                 dns_db_detach(&db);
2638         if (zone != NULL)
2639                 dns_zone_detach(&zone);
2640         if (zdb != NULL) {
2641                 query_putrdataset(client, &zrdataset);
2642                 if (zsigrdataset != NULL)
2643                         query_putrdataset(client, &zsigrdataset);
2644                 if (zfname != NULL)
2645                         query_releasename(client, &zfname);
2646                 dns_db_detach(&zdb);
2647         }
2648 }
2649
2650 static void
2651 fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) {
2652         if (*rdataset == NULL)
2653                 *rdataset = query_newrdataset(client);
2654         else  if (dns_rdataset_isassociated(*rdataset))
2655                 dns_rdataset_disassociate(*rdataset);
2656 }
2657
2658 static void
2659 fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf,
2660          isc_buffer_t *nbuf)
2661 {
2662         if (*fname == NULL) {
2663                 *dbuf = query_getnamebuf(client);
2664                 if (*dbuf == NULL)
2665                         return;
2666                 *fname = query_newname(client, *dbuf, nbuf);
2667         }
2668 }
2669
2670 static void
2671 query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node,
2672             dns_dbversion_t *version, dns_name_t *name)
2673 {
2674         dns_fixedname_t fixed;
2675         dns_name_t *fname = NULL;
2676         dns_name_t *rname;
2677         dns_rdataset_t *rdataset, *sigrdataset;
2678         isc_buffer_t *dbuf, b;
2679         isc_result_t result;
2680         unsigned int count;
2681
2682         CTRACE("query_addds");
2683         rname = NULL;
2684         rdataset = NULL;
2685         sigrdataset = NULL;
2686
2687         /*
2688          * We'll need some resources...
2689          */
2690         rdataset = query_newrdataset(client);
2691         sigrdataset = query_newrdataset(client);
2692         if (rdataset == NULL || sigrdataset == NULL)
2693                 goto cleanup;
2694
2695         /*
2696          * Look for the DS record, which may or may not be present.
2697          */
2698         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ds, 0,
2699                                      client->now, rdataset, sigrdataset);
2700         /*
2701          * If we didn't find it, look for an NSEC.
2702          */
2703         if (result == ISC_R_NOTFOUND)
2704                 result = dns_db_findrdataset(db, node, version,
2705                                              dns_rdatatype_nsec, 0, client->now,
2706                                              rdataset, sigrdataset);
2707         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
2708                 goto addnsec3;
2709         if (!dns_rdataset_isassociated(rdataset) ||
2710             !dns_rdataset_isassociated(sigrdataset))
2711                 goto addnsec3;
2712
2713         /*
2714          * We've already added the NS record, so if the name's not there,
2715          * we have other problems.  Use this name rather than calling
2716          * query_addrrset().
2717          */
2718         result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
2719         if (result != ISC_R_SUCCESS)
2720                 goto cleanup;
2721
2722         rname = NULL;
2723         dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
2724                                 &rname);
2725         result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
2726         if (result != ISC_R_SUCCESS)
2727                 goto cleanup;
2728
2729         ISC_LIST_APPEND(rname->list, rdataset, link);
2730         ISC_LIST_APPEND(rname->list, sigrdataset, link);
2731         rdataset = NULL;
2732         sigrdataset = NULL;
2733         return;
2734
2735    addnsec3:
2736         if (dns_db_iscache(db))
2737                 goto cleanup;
2738         /*
2739          * Add the NSEC3 which proves the DS does not exist.
2740          */
2741         dbuf = query_getnamebuf(client);
2742         if (dbuf == NULL)
2743                 goto cleanup;
2744         fname = query_newname(client, dbuf, &b);
2745         dns_fixedname_init(&fixed);
2746         if (dns_rdataset_isassociated(rdataset))
2747                 dns_rdataset_disassociate(rdataset);
2748         if (dns_rdataset_isassociated(sigrdataset))
2749                 dns_rdataset_disassociate(sigrdataset);
2750         query_findclosestnsec3(name, db, version, client, rdataset,
2751                                sigrdataset, fname, ISC_TRUE,
2752                                dns_fixedname_name(&fixed));
2753         if (!dns_rdataset_isassociated(rdataset))
2754                 goto cleanup;
2755         query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
2756                        DNS_SECTION_AUTHORITY);
2757         /*
2758          * Did we find the closest provable encloser instead?
2759          * If so add the nearest to the closest provable encloser.
2760          */
2761         if (!dns_name_equal(name, dns_fixedname_name(&fixed))) {
2762                 count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1;
2763                 dns_name_getlabelsequence(name,
2764                                           dns_name_countlabels(name) - count,
2765                                           count, dns_fixedname_name(&fixed));
2766                 fixfname(client, &fname, &dbuf, &b);
2767                 fixrdataset(client, &rdataset);
2768                 fixrdataset(client, &sigrdataset);
2769                 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
2770                                 goto cleanup;
2771                 query_findclosestnsec3(dns_fixedname_name(&fixed), db, version,
2772                                        client, rdataset, sigrdataset, fname,
2773                                        ISC_FALSE, NULL);
2774                 if (!dns_rdataset_isassociated(rdataset))
2775                         goto cleanup;
2776                 query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
2777                                DNS_SECTION_AUTHORITY);
2778         }
2779
2780  cleanup:
2781         if (rdataset != NULL)
2782                 query_putrdataset(client, &rdataset);
2783         if (sigrdataset != NULL)
2784                 query_putrdataset(client, &sigrdataset);
2785         if (fname != NULL)
2786                 query_releasename(client, &fname);
2787 }
2788
2789 static void
2790 query_addwildcardproof(ns_client_t *client, dns_db_t *db,
2791                        dns_dbversion_t *version, dns_name_t *name,
2792                        isc_boolean_t ispositive)
2793 {
2794         isc_buffer_t *dbuf, b;
2795         dns_name_t *fname;
2796         dns_rdataset_t *rdataset, *sigrdataset;
2797         dns_fixedname_t wfixed;
2798         dns_name_t *wname;
2799         dns_dbnode_t *node;
2800         unsigned int options;
2801         unsigned int olabels, nlabels, labels;
2802         isc_result_t result;
2803         dns_rdata_t rdata = DNS_RDATA_INIT;
2804         dns_rdata_nsec_t nsec;
2805         isc_boolean_t have_wname;
2806         int order;
2807         dns_fixedname_t cfixed;
2808         dns_name_t *cname;
2809
2810         CTRACE("query_addwildcardproof");
2811         fname = NULL;
2812         rdataset = NULL;
2813         sigrdataset = NULL;
2814         node = NULL;
2815
2816         /*
2817          * Get the NOQNAME proof then if !ispositive
2818          * get the NOWILDCARD proof.
2819          *
2820          * DNS_DBFIND_NOWILD finds the NSEC records that covers the
2821          * name ignoring any wildcard.  From the owner and next names
2822          * of this record you can compute which wildcard (if it exists)
2823          * will match by finding the longest common suffix of the
2824          * owner name and next names with the qname and prefixing that
2825          * with the wildcard label.
2826          *
2827          * e.g.
2828          *   Given:
2829          *      example SOA
2830          *      example NSEC b.example
2831          *      b.example A
2832          *      b.example NSEC a.d.example
2833          *      a.d.example A
2834          *      a.d.example NSEC g.f.example
2835          *      g.f.example A
2836          *      g.f.example NSEC z.i.example
2837          *      z.i.example A
2838          *      z.i.example NSEC example
2839          *
2840          *   QNAME:
2841          *   a.example -> example NSEC b.example
2842          *      owner common example
2843          *      next common example
2844          *      wild *.example
2845          *   d.b.example -> b.example NSEC a.d.example
2846          *      owner common b.example
2847          *      next common example
2848          *      wild *.b.example
2849          *   a.f.example -> a.d.example NSEC g.f.example
2850          *      owner common example
2851          *      next common f.example
2852          *      wild *.f.example
2853          *  j.example -> z.i.example NSEC example
2854          *      owner common example
2855          *      next common example
2856          *      wild *.f.example
2857          */
2858         options = client->query.dboptions | DNS_DBFIND_NOWILD;
2859         dns_fixedname_init(&wfixed);
2860         wname = dns_fixedname_name(&wfixed);
2861  again:
2862         have_wname = ISC_FALSE;
2863         /*
2864          * We'll need some resources...
2865          */
2866         dbuf = query_getnamebuf(client);
2867         if (dbuf == NULL)
2868                 goto cleanup;
2869         fname = query_newname(client, dbuf, &b);
2870         rdataset = query_newrdataset(client);
2871         sigrdataset = query_newrdataset(client);
2872         if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
2873                 goto cleanup;
2874
2875         result = dns_db_find(db, name, version, dns_rdatatype_nsec, options,
2876                              0, &node, fname, rdataset, sigrdataset);
2877         if (node != NULL)
2878                 dns_db_detachnode(db, &node);
2879
2880         if (!dns_rdataset_isassociated(rdataset)) {
2881                 /*
2882                  * No NSEC proof available, return NSEC3 proofs instead.
2883                  */
2884                 dns_fixedname_init(&cfixed);
2885                 cname = dns_fixedname_name(&cfixed);
2886                 /*
2887                  * Find the closest encloser.
2888                  */
2889                 dns_name_copy(name, cname, NULL);
2890                 while (result == DNS_R_NXDOMAIN) {
2891                         labels = dns_name_countlabels(cname) - 1;
2892                         dns_name_split(cname, labels, NULL, cname);
2893                         result = dns_db_find(db, cname, version,
2894                                              dns_rdatatype_nsec,
2895                                              options, 0, NULL, fname,
2896                                              NULL, NULL);
2897                 }
2898                 /*
2899                  * Add closest (provable) encloser NSEC3.
2900                  */
2901                 query_findclosestnsec3(cname, db, NULL, client, rdataset,
2902                                        sigrdataset, fname, ISC_TRUE, cname);
2903                 if (!dns_rdataset_isassociated(rdataset))
2904                         goto cleanup;
2905                 query_addrrset(client, &fname, &rdataset, &sigrdataset,
2906                                dbuf, DNS_SECTION_AUTHORITY);
2907
2908                 /*
2909                  * Replace resources which were consumed by query_addrrset.
2910                  */
2911                 if (fname == NULL) {
2912                         dbuf = query_getnamebuf(client);
2913                         if (dbuf == NULL)
2914                                 goto cleanup;
2915                         fname = query_newname(client, dbuf, &b);
2916                 }
2917
2918                 if (rdataset == NULL)
2919                         rdataset = query_newrdataset(client);
2920                 else if (dns_rdataset_isassociated(rdataset))
2921                         dns_rdataset_disassociate(rdataset);
2922
2923                 if (sigrdataset == NULL)
2924                         sigrdataset = query_newrdataset(client);
2925                 else if (dns_rdataset_isassociated(sigrdataset))
2926                         dns_rdataset_disassociate(sigrdataset);
2927
2928                 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
2929                         goto cleanup;
2930                 /*
2931                  * Add no qname proof.
2932                  */
2933                 labels = dns_name_countlabels(cname) + 1;
2934                 if (dns_name_countlabels(name) == labels)
2935                         dns_name_copy(name, wname, NULL);
2936                 else
2937                         dns_name_split(name, labels, NULL, wname);
2938
2939                 query_findclosestnsec3(wname, db, NULL, client, rdataset,
2940                                        sigrdataset, fname, ISC_FALSE, NULL);
2941                 if (!dns_rdataset_isassociated(rdataset))
2942                         goto cleanup;
2943                 query_addrrset(client, &fname, &rdataset, &sigrdataset,
2944                                dbuf, DNS_SECTION_AUTHORITY);
2945
2946                 if (ispositive)
2947                         goto cleanup;
2948
2949                 /*
2950                  * Replace resources which were consumed by query_addrrset.
2951                  */
2952                 if (fname == NULL) {
2953                         dbuf = query_getnamebuf(client);
2954                         if (dbuf == NULL)
2955                                 goto cleanup;
2956                         fname = query_newname(client, dbuf, &b);
2957                 }
2958
2959                 if (rdataset == NULL)
2960                         rdataset = query_newrdataset(client);
2961                 else if (dns_rdataset_isassociated(rdataset))
2962                         dns_rdataset_disassociate(rdataset);
2963
2964                 if (sigrdataset == NULL)
2965                         sigrdataset = query_newrdataset(client);
2966                 else if (dns_rdataset_isassociated(sigrdataset))
2967                         dns_rdataset_disassociate(sigrdataset);
2968
2969                 if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
2970                         goto cleanup;
2971                 /*
2972                  * Add the no wildcard proof.
2973                  */
2974                 result = dns_name_concatenate(dns_wildcardname,
2975                                               cname, wname, NULL);
2976                 if (result != ISC_R_SUCCESS)
2977                         goto cleanup;
2978
2979                 query_findclosestnsec3(wname, db, NULL, client, rdataset,
2980                                        sigrdataset, fname, ISC_FALSE, NULL);
2981                 if (!dns_rdataset_isassociated(rdataset))
2982                         goto cleanup;
2983                 query_addrrset(client, &fname, &rdataset, &sigrdataset,
2984                                dbuf, DNS_SECTION_AUTHORITY);
2985
2986                 goto cleanup;
2987         } else if (result == DNS_R_NXDOMAIN) {
2988                 if (!ispositive)
2989                         result = dns_rdataset_first(rdataset);
2990                 if (result == ISC_R_SUCCESS) {
2991                         dns_rdataset_current(rdataset, &rdata);
2992                         result = dns_rdata_tostruct(&rdata, &nsec, NULL);
2993                 }
2994                 if (result == ISC_R_SUCCESS) {
2995                         (void)dns_name_fullcompare(name, fname, &order,
2996                                                    &olabels);
2997                         (void)dns_name_fullcompare(name, &nsec.next, &order,
2998                                                    &nlabels);
2999                         /*
3000                          * Check for a pathological condition created when
3001                          * serving some malformed signed zones and bail out.
3002                          */
3003                         if (dns_name_countlabels(name) == nlabels)
3004                                 goto cleanup;
3005
3006                         if (olabels > nlabels)
3007                                 dns_name_split(name, olabels, NULL, wname);
3008                         else
3009                                 dns_name_split(name, nlabels, NULL, wname);
3010                         result = dns_name_concatenate(dns_wildcardname,
3011                                                       wname, wname, NULL);
3012                         if (result == ISC_R_SUCCESS)
3013                                 have_wname = ISC_TRUE;
3014                         dns_rdata_freestruct(&nsec);
3015                 }
3016                 query_addrrset(client, &fname, &rdataset, &sigrdataset,
3017                                dbuf, DNS_SECTION_AUTHORITY);
3018         }
3019         if (rdataset != NULL)
3020                 query_putrdataset(client, &rdataset);
3021         if (sigrdataset != NULL)
3022                 query_putrdataset(client, &sigrdataset);
3023         if (fname != NULL)
3024                 query_releasename(client, &fname);
3025         if (have_wname) {
3026                 ispositive = ISC_TRUE;  /* prevent loop */
3027                 if (!dns_name_equal(name, wname)) {
3028                         name = wname;
3029                         goto again;
3030                 }
3031         }
3032  cleanup:
3033         if (rdataset != NULL)
3034                 query_putrdataset(client, &rdataset);
3035         if (sigrdataset != NULL)
3036                 query_putrdataset(client, &sigrdataset);
3037         if (fname != NULL)
3038                 query_releasename(client, &fname);
3039 }
3040
3041 static void
3042 query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db,
3043                      dns_dbversion_t *version, dns_name_t **namep,
3044                      dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp)
3045 {
3046         dns_name_t *name;
3047         dns_rdataset_t *sigrdataset;
3048         dns_rdata_t sigrdata;
3049         dns_rdata_rrsig_t sig;
3050         unsigned int labels;
3051         isc_buffer_t *dbuf, b;
3052         dns_name_t *fname;
3053         isc_result_t result;
3054
3055         name = *namep;
3056         if ((name->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
3057                 query_addrrset(client, namep, rdatasetp, sigrdatasetp,
3058                                NULL, DNS_SECTION_AUTHORITY);
3059                 return;
3060         }
3061
3062         if (sigrdatasetp == NULL)
3063                 return;
3064
3065         sigrdataset = *sigrdatasetp;
3066         if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
3067                 return;
3068         result = dns_rdataset_first(sigrdataset);
3069         if (result != ISC_R_SUCCESS)
3070                 return;
3071         dns_rdata_init(&sigrdata);
3072         dns_rdataset_current(sigrdataset, &sigrdata);
3073         result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
3074         if (result != ISC_R_SUCCESS)
3075                 return;
3076
3077         labels = dns_name_countlabels(name);
3078         if ((unsigned int)sig.labels + 1 >= labels)
3079                 return;
3080
3081         /* XXX */
3082         query_addwildcardproof(client, db, version, client->query.qname,
3083                                ISC_TRUE);
3084
3085         /*
3086          * We'll need some resources...
3087          */
3088         dbuf = query_getnamebuf(client);
3089         if (dbuf == NULL)
3090                 return;
3091         fname = query_newname(client, dbuf, &b);
3092         if (fname == NULL)
3093                 return;
3094         dns_name_split(name, sig.labels + 1, NULL, fname);
3095         /* This will succeed, since we've stripped labels. */
3096         RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,
3097                                            NULL) == ISC_R_SUCCESS);
3098         query_addrrset(client, &fname, rdatasetp, sigrdatasetp,
3099                        dbuf, DNS_SECTION_AUTHORITY);
3100 }
3101
3102 static void
3103 query_resume(isc_task_t *task, isc_event_t *event) {
3104         dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
3105         dns_fetch_t *fetch;
3106         ns_client_t *client;
3107         isc_boolean_t fetch_canceled, client_shuttingdown;
3108         isc_result_t result;
3109         isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_EERRORS;
3110         int errorloglevel;
3111
3112         /*
3113          * Resume a query after recursion.
3114          */
3115
3116         UNUSED(task);
3117
3118         REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
3119         client = devent->ev_arg;
3120         REQUIRE(NS_CLIENT_VALID(client));
3121         REQUIRE(task == client->task);
3122         REQUIRE(RECURSING(client));
3123
3124         LOCK(&client->query.fetchlock);
3125         if (client->query.fetch != NULL) {
3126                 /*
3127                  * This is the fetch we've been waiting for.
3128                  */
3129                 INSIST(devent->fetch == client->query.fetch);
3130                 client->query.fetch = NULL;
3131                 fetch_canceled = ISC_FALSE;
3132                 /*
3133                  * Update client->now.
3134                  */
3135                 isc_stdtime_get(&client->now);
3136         } else {
3137                 /*
3138                  * This is a fetch completion event for a canceled fetch.
3139                  * Clean up and don't resume the find.
3140                  */
3141                 fetch_canceled = ISC_TRUE;
3142         }
3143         UNLOCK(&client->query.fetchlock);
3144         INSIST(client->query.fetch == NULL);
3145
3146         client->query.attributes &= ~NS_QUERYATTR_RECURSING;
3147         fetch = devent->fetch;
3148         devent->fetch = NULL;
3149
3150         /*
3151          * If this client is shutting down, or this transaction
3152          * has timed out, do not resume the find.
3153          */
3154         client_shuttingdown = ns_client_shuttingdown(client);
3155         if (fetch_canceled || client_shuttingdown) {
3156                 if (devent->node != NULL)
3157                         dns_db_detachnode(devent->db, &devent->node);
3158                 if (devent->db != NULL)
3159                         dns_db_detach(&devent->db);
3160                 query_putrdataset(client, &devent->rdataset);
3161                 if (devent->sigrdataset != NULL)
3162                         query_putrdataset(client, &devent->sigrdataset);
3163                 isc_event_free(&event);
3164                 if (fetch_canceled)
3165                         query_error(client, DNS_R_SERVFAIL, __LINE__);
3166                 else
3167                         query_next(client, ISC_R_CANCELED);
3168                 /*
3169                  * This may destroy the client.
3170                  */
3171                 ns_client_detach(&client);
3172         } else {
3173                 result = query_find(client, devent, 0);
3174                 if (result != ISC_R_SUCCESS) {
3175                         if (result == DNS_R_SERVFAIL)
3176                                 errorloglevel = ISC_LOG_DEBUG(2);
3177                         else
3178                                 errorloglevel = ISC_LOG_DEBUG(4);
3179                         if (isc_log_wouldlog(ns_g_lctx, errorloglevel)) {
3180                                 dns_resolver_logfetch(fetch, ns_g_lctx,
3181                                                       logcategory,
3182                                                       NS_LOGMODULE_QUERY,
3183                                                       errorloglevel, ISC_FALSE);
3184                         }
3185                 }
3186         }
3187
3188         dns_resolver_destroyfetch(&fetch);
3189 }
3190
3191 static isc_result_t
3192 query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
3193               dns_rdataset_t *nameservers, isc_boolean_t resuming)
3194 {
3195         isc_result_t result;
3196         dns_rdataset_t *rdataset, *sigrdataset;
3197         isc_sockaddr_t *peeraddr;
3198
3199         if (!resuming)
3200                 inc_stats(client, dns_nsstatscounter_recursion);
3201
3202         /*
3203          * We are about to recurse, which means that this client will
3204          * be unavailable for serving new requests for an indeterminate
3205          * amount of time.  If this client is currently responsible
3206          * for handling incoming queries, set up a new client
3207          * object to handle them while we are waiting for a
3208          * response.  There is no need to replace TCP clients
3209          * because those have already been replaced when the
3210          * connection was accepted (if allowed by the TCP quota).
3211          */
3212         if (client->recursionquota == NULL) {
3213                 result = isc_quota_attach(&ns_g_server->recursionquota,
3214                                           &client->recursionquota);
3215                 if  (result == ISC_R_SOFTQUOTA) {
3216                         static isc_stdtime_t last = 0;
3217                         isc_stdtime_t now;
3218                         isc_stdtime_get(&now);
3219                         if (now != last) {
3220                                 last = now;
3221                                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3222                                               NS_LOGMODULE_QUERY,
3223                                               ISC_LOG_WARNING,
3224                                               "recursive-clients soft limit "
3225                                               "exceeded, aborting oldest query");
3226                         }
3227                         ns_client_killoldestquery(client);
3228                         result = ISC_R_SUCCESS;
3229                 } else if (result == ISC_R_QUOTA) {
3230                         static isc_stdtime_t last = 0;
3231                         isc_stdtime_t now;
3232                         isc_stdtime_get(&now);
3233                         if (now != last) {
3234                                 last = now;
3235                                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3236                                               NS_LOGMODULE_QUERY,
3237                                               ISC_LOG_WARNING,
3238                                               "no more recursive clients: %s",
3239                                               isc_result_totext(result));
3240                         }
3241                         ns_client_killoldestquery(client);
3242                 }
3243                 if (result == ISC_R_SUCCESS && !client->mortal &&
3244                     (client->attributes & NS_CLIENTATTR_TCP) == 0) {
3245                         result = ns_client_replace(client);
3246                         if (result != ISC_R_SUCCESS) {
3247                                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
3248                                               NS_LOGMODULE_QUERY,
3249                                               ISC_LOG_WARNING,
3250                                               "ns_client_replace() failed: %s",
3251                                               isc_result_totext(result));
3252                                 isc_quota_detach(&client->recursionquota);
3253                         }
3254                 }
3255                 if (result != ISC_R_SUCCESS)
3256                         return (result);
3257                 ns_client_recursing(client);
3258         }
3259
3260         /*
3261          * Invoke the resolver.
3262          */
3263         REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
3264         REQUIRE(client->query.fetch == NULL);
3265
3266         rdataset = query_newrdataset(client);
3267         if (rdataset == NULL)
3268                 return (ISC_R_NOMEMORY);
3269         if (WANTDNSSEC(client)) {
3270                 sigrdataset = query_newrdataset(client);
3271                 if (sigrdataset == NULL) {
3272                         query_putrdataset(client, &rdataset);
3273                         return (ISC_R_NOMEMORY);
3274                 }
3275         } else
3276                 sigrdataset = NULL;
3277
3278         if (client->query.timerset == ISC_FALSE)
3279                 ns_client_settimeout(client, 60);
3280         if ((client->attributes & NS_CLIENTATTR_TCP) == 0)
3281                 peeraddr = &client->peeraddr;
3282         else
3283                 peeraddr = NULL;
3284         result = dns_resolver_createfetch2(client->view->resolver,
3285                                            client->query.qname,
3286                                            qtype, qdomain, nameservers,
3287                                            NULL, peeraddr, client->message->id,
3288                                            client->query.fetchoptions,
3289                                            client->task,
3290                                            query_resume, client,
3291                                            rdataset, sigrdataset,
3292                                            &client->query.fetch);
3293
3294         if (result == ISC_R_SUCCESS) {
3295                 /*
3296                  * Record that we're waiting for an event.  A client which
3297                  * is shutting down will not be destroyed until all the
3298                  * events have been received.
3299                  */
3300         } else {
3301                 query_putrdataset(client, &rdataset);
3302                 if (sigrdataset != NULL)
3303                         query_putrdataset(client, &sigrdataset);
3304         }
3305
3306         return (result);
3307 }
3308
3309 #define MAX_RESTARTS 16
3310
3311 #define QUERY_ERROR(r) \
3312 do { \
3313         eresult = r; \
3314         want_restart = ISC_FALSE; \
3315         line = __LINE__; \
3316 } while (0)
3317
3318 /*
3319  * Extract a network address from the RDATA of an A or AAAA
3320  * record.
3321  *
3322  * Returns:
3323  *      ISC_R_SUCCESS
3324  *      ISC_R_NOTIMPLEMENTED    The rdata is not a known address type.
3325  */
3326 static isc_result_t
3327 rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
3328         struct in_addr ina;
3329         struct in6_addr in6a;
3330
3331         switch (rdata->type) {
3332         case dns_rdatatype_a:
3333                 INSIST(rdata->length == 4);
3334                 memcpy(&ina.s_addr, rdata->data, 4);
3335                 isc_netaddr_fromin(netaddr, &ina);
3336                 return (ISC_R_SUCCESS);
3337         case dns_rdatatype_aaaa:
3338                 INSIST(rdata->length == 16);
3339                 memcpy(in6a.s6_addr, rdata->data, 16);
3340                 isc_netaddr_fromin6(netaddr, &in6a);
3341                 return (ISC_R_SUCCESS);
3342         default:
3343                 return (ISC_R_NOTIMPLEMENTED);
3344         }
3345 }
3346
3347 /*
3348  * Find the sort order of 'rdata' in the topology-like
3349  * ACL forming the second element in a 2-element top-level
3350  * sortlist statement.
3351  */
3352 static int
3353 query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) {
3354         isc_netaddr_t netaddr;
3355
3356         if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
3357                 return (INT_MAX);
3358         return (ns_sortlist_addrorder2(&netaddr, arg));
3359 }
3360
3361 /*
3362  * Find the sort order of 'rdata' in the matching element
3363  * of a 1-element top-level sortlist statement.
3364  */
3365 static int
3366 query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) {
3367         isc_netaddr_t netaddr;
3368
3369         if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
3370                 return (INT_MAX);
3371         return (ns_sortlist_addrorder1(&netaddr, arg));
3372 }
3373
3374 /*
3375  * Find the sortlist statement that applies to 'client' and set up
3376  * the sortlist info in in client->message appropriately.
3377  */
3378 static void
3379 setup_query_sortlist(ns_client_t *client) {
3380         isc_netaddr_t netaddr;
3381         dns_rdatasetorderfunc_t order = NULL;
3382         const void *order_arg = NULL;
3383
3384         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
3385         switch (ns_sortlist_setup(client->view->sortlist,
3386                                &netaddr, &order_arg)) {
3387         case NS_SORTLISTTYPE_1ELEMENT:
3388                 order = query_sortlist_order_1element;
3389                 break;
3390         case NS_SORTLISTTYPE_2ELEMENT:
3391                 order = query_sortlist_order_2element;
3392                 break;
3393         case NS_SORTLISTTYPE_NONE:
3394                 order = NULL;
3395                 break;
3396         default:
3397                 INSIST(0);
3398                 break;
3399         }
3400         dns_message_setsortorder(client->message, order, order_arg);
3401 }
3402
3403 static void
3404 query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
3405         isc_buffer_t *dbuf, b;
3406         dns_name_t *fname;
3407         dns_rdataset_t *neg, *negsig;
3408         isc_result_t result = ISC_R_NOMEMORY;
3409
3410         CTRACE("query_addnoqnameproof");
3411
3412         fname = NULL;
3413         neg = NULL;
3414         negsig = NULL;
3415
3416         dbuf = query_getnamebuf(client);
3417         if (dbuf == NULL)
3418                 goto cleanup;
3419         fname = query_newname(client, dbuf, &b);
3420         neg = query_newrdataset(client);
3421         negsig = query_newrdataset(client);
3422         if (fname == NULL || neg == NULL || negsig == NULL)
3423                 goto cleanup;
3424
3425         result = dns_rdataset_getnoqname(rdataset, fname, neg, negsig);
3426         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3427
3428         query_addrrset(client, &fname, &neg, &negsig, dbuf,
3429                        DNS_SECTION_AUTHORITY);
3430
3431         if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) == 0)
3432                 goto cleanup;
3433
3434         if (fname == NULL) {
3435                 dbuf = query_getnamebuf(client);
3436                 if (dbuf == NULL)
3437                         goto cleanup;
3438                 fname = query_newname(client, dbuf, &b);
3439         }
3440         if (neg == NULL)
3441                 neg = query_newrdataset(client);
3442         else if (dns_rdataset_isassociated(neg))
3443                 dns_rdataset_disassociate(neg);
3444         if (negsig == NULL)
3445                 negsig = query_newrdataset(client);
3446         else if (dns_rdataset_isassociated(negsig))
3447                 dns_rdataset_disassociate(negsig);
3448         if (fname == NULL || neg == NULL || negsig == NULL)
3449                 goto cleanup;
3450         result = dns_rdataset_getclosest(rdataset, fname, neg, negsig);
3451         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3452
3453         query_addrrset(client, &fname, &neg, &negsig, dbuf,
3454                        DNS_SECTION_AUTHORITY);
3455
3456  cleanup:
3457         if (neg != NULL)
3458                 query_putrdataset(client, &neg);
3459         if (negsig != NULL)
3460                 query_putrdataset(client, &negsig);
3461         if (fname != NULL)
3462                 query_releasename(client, &fname);
3463 }
3464
3465 static inline void
3466 answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
3467         dns_name_t *name;
3468         dns_message_t *msg;
3469         dns_section_t section = DNS_SECTION_ADDITIONAL;
3470         dns_rdataset_t *rdataset = NULL;
3471
3472         msg = client->message;
3473         for (name = ISC_LIST_HEAD(msg->sections[section]);
3474              name != NULL;
3475              name = ISC_LIST_NEXT(name, link))
3476                 if (dns_name_equal(name, client->query.qname)) {
3477                         for (rdataset = ISC_LIST_HEAD(name->list);
3478                              rdataset != NULL;
3479                              rdataset = ISC_LIST_NEXT(rdataset, link))
3480                                 if (rdataset->type == qtype)
3481                                         break;
3482                         break;
3483                 }
3484         if (rdataset != NULL) {
3485                 ISC_LIST_UNLINK(msg->sections[section], name, link);
3486                 ISC_LIST_PREPEND(msg->sections[section], name, link);
3487                 ISC_LIST_UNLINK(name->list, rdataset, link);
3488                 ISC_LIST_PREPEND(name->list, rdataset, link);
3489                 rdataset->attributes |= DNS_RDATASETATTR_REQUIREDGLUE;
3490         }
3491 }
3492
3493 #define NS_NAME_INIT(A,B) \
3494          { \
3495                 DNS_NAME_MAGIC, \
3496                 A, sizeof(A), sizeof(B), \
3497                 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
3498                 B, NULL, { (void *)-1, (void *)-1}, \
3499                 {NULL, NULL} \
3500         }
3501
3502 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
3503 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
3504 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
3505
3506 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
3507
3508 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
3509 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
3510 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
3511 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
3512 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
3513 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
3514 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
3515 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
3516 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
3517 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
3518 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
3519 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
3520 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
3521 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
3522 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
3523 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
3524
3525 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
3526
3527 static dns_name_t rfc1918names[] = {
3528         NS_NAME_INIT(inaddr10, inaddr10_offsets),
3529         NS_NAME_INIT(inaddr16172, inaddr172_offsets),
3530         NS_NAME_INIT(inaddr17172, inaddr172_offsets),
3531         NS_NAME_INIT(inaddr18172, inaddr172_offsets),
3532         NS_NAME_INIT(inaddr19172, inaddr172_offsets),
3533         NS_NAME_INIT(inaddr20172, inaddr172_offsets),
3534         NS_NAME_INIT(inaddr21172, inaddr172_offsets),
3535         NS_NAME_INIT(inaddr22172, inaddr172_offsets),
3536         NS_NAME_INIT(inaddr23172, inaddr172_offsets),
3537         NS_NAME_INIT(inaddr24172, inaddr172_offsets),
3538         NS_NAME_INIT(inaddr25172, inaddr172_offsets),
3539         NS_NAME_INIT(inaddr26172, inaddr172_offsets),
3540         NS_NAME_INIT(inaddr27172, inaddr172_offsets),
3541         NS_NAME_INIT(inaddr28172, inaddr172_offsets),
3542         NS_NAME_INIT(inaddr29172, inaddr172_offsets),
3543         NS_NAME_INIT(inaddr30172, inaddr172_offsets),
3544         NS_NAME_INIT(inaddr31172, inaddr172_offsets),
3545         NS_NAME_INIT(inaddr168192, inaddr192_offsets)
3546 };
3547
3548
3549 static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
3550 static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org";
3551
3552 static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
3553 static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
3554
3555 static dns_name_t prisoner = NS_NAME_INIT(prisoner_data, prisoner_offsets);
3556 static dns_name_t hostmaster = NS_NAME_INIT(hostmaster_data, hostmaster_offsets);
3557
3558 static void
3559 warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
3560         unsigned int i;
3561         dns_rdata_t rdata = DNS_RDATA_INIT;
3562         dns_rdata_soa_t soa;
3563         dns_rdataset_t found;
3564         isc_result_t result;
3565
3566         for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) {
3567                 if (dns_name_issubdomain(fname, &rfc1918names[i])) {
3568                         dns_rdataset_init(&found);
3569                         result = dns_ncache_getrdataset(rdataset,
3570                                                         &rfc1918names[i],
3571                                                         dns_rdatatype_soa,
3572                                                         &found);
3573                         if (result != ISC_R_SUCCESS)
3574                                 return;
3575
3576                         result = dns_rdataset_first(&found);
3577                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3578                         dns_rdataset_current(&found, &rdata);
3579                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
3580                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3581                         if (dns_name_equal(&soa.origin, &prisoner) &&
3582                             dns_name_equal(&soa.contact, &hostmaster)) {
3583                                 char buf[DNS_NAME_FORMATSIZE];
3584                                 dns_name_format(fname, buf, sizeof(buf));
3585                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
3586                                               NS_LOGMODULE_QUERY,
3587                                               ISC_LOG_WARNING,
3588                                               "RFC 1918 response from "
3589                                               "Internet for %s", buf);
3590                         }
3591                         dns_rdataset_disassociate(&found);
3592                         return;
3593                 }
3594         }
3595 }
3596
3597 static void
3598 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
3599                        dns_dbversion_t *version, ns_client_t *client,
3600                        dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3601                        dns_name_t *fname, isc_boolean_t exact,
3602                        dns_name_t *found)
3603 {
3604         unsigned char salt[256];
3605         size_t salt_length = sizeof(salt);
3606         isc_uint16_t iterations;
3607         isc_result_t result;
3608         unsigned int dboptions;
3609         dns_fixedname_t fixed;
3610         dns_hash_t hash;
3611         dns_name_t name;
3612         int order;
3613         unsigned int count;
3614         dns_rdata_nsec3_t nsec3;
3615         dns_rdata_t rdata = DNS_RDATA_INIT;
3616         isc_boolean_t optout;
3617
3618         salt_length = sizeof(salt);
3619         result = dns_db_getnsec3parameters(db, version, &hash, NULL,
3620                                            &iterations, salt, &salt_length);
3621         if (result != ISC_R_SUCCESS)
3622                 return;
3623
3624         dns_name_init(&name, NULL);
3625         dns_name_clone(qname, &name);
3626
3627         /*
3628          * Map unknown algorithm to known value.
3629          */
3630         if (hash == DNS_NSEC3_UNKNOWNALG)
3631                 hash = 1;
3632
3633  again:
3634         dns_fixedname_init(&fixed);
3635         result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
3636                                     dns_db_origin(db), hash,
3637                                     iterations, salt, salt_length);
3638         if (result != ISC_R_SUCCESS)
3639                 return;
3640
3641         dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
3642         result = dns_db_find(db, dns_fixedname_name(&fixed), version,
3643                              dns_rdatatype_nsec3, dboptions, client->now,
3644                              NULL, fname, rdataset, sigrdataset);
3645
3646         if (result == DNS_R_NXDOMAIN) {
3647                 if (!dns_rdataset_isassociated(rdataset)) {
3648                         return;
3649                 }
3650                 result = dns_rdataset_first(rdataset);
3651                 INSIST(result == ISC_R_SUCCESS);
3652                 dns_rdataset_current(rdataset, &rdata);
3653                 dns_rdata_tostruct(&rdata, &nsec3, NULL);
3654                 dns_rdata_reset(&rdata);
3655                 optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
3656                 if (found != NULL && optout &&
3657                     dns_name_fullcompare(&name, dns_db_origin(db), &order,
3658                                          &count) == dns_namereln_subdomain) {
3659                         dns_rdataset_disassociate(rdataset);
3660                         if (dns_rdataset_isassociated(sigrdataset))
3661                                 dns_rdataset_disassociate(sigrdataset);
3662                         count = dns_name_countlabels(&name) - 1;
3663                         dns_name_getlabelsequence(&name, 1, count, &name);
3664                         ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
3665                                       NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3),
3666                                       "looking for closest provable encloser");
3667                         goto again;
3668                 }
3669                 if (exact)
3670                         ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
3671                                       NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
3672                                       "expected a exact match NSEC3, got "
3673                                       "a covering record");
3674
3675         } else if (result != ISC_R_SUCCESS) {
3676                 return;
3677         } else if (!exact)
3678                 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
3679                               NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
3680                               "expected covering NSEC3, got an exact match");
3681         if (found != NULL)
3682                 dns_name_copy(&name, found, NULL);
3683         return;
3684 }
3685
3686 /*
3687  * Do the bulk of query processing for the current query of 'client'.
3688  * If 'event' is non-NULL, we are returning from recursion and 'qtype'
3689  * is ignored.  Otherwise, 'qtype' is the query type.
3690  */
3691 static isc_result_t
3692 query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
3693 {
3694         dns_db_t *db, *zdb;
3695         dns_dbnode_t *node;
3696         dns_rdatatype_t type;
3697         dns_name_t *fname, *zfname, *tname, *prefix;
3698         dns_rdataset_t *rdataset, *trdataset;
3699         dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset;
3700         dns_rdataset_t **sigrdatasetp;
3701         dns_rdata_t rdata = DNS_RDATA_INIT;
3702         dns_rdatasetiter_t *rdsiter;
3703         isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof;
3704         unsigned int n, nlabels;
3705         dns_namereln_t namereln;
3706         int order;
3707         isc_buffer_t *dbuf;
3708         isc_buffer_t b;
3709         isc_result_t result, eresult;
3710         dns_fixedname_t fixed;
3711         dns_fixedname_t wildcardname;
3712         dns_dbversion_t *version, *zversion;
3713         dns_zone_t *zone;
3714         dns_rdata_cname_t cname;
3715         dns_rdata_dname_t dname;
3716         unsigned int options;
3717         isc_boolean_t empty_wild;
3718         dns_rdataset_t *noqname;
3719         isc_boolean_t resuming;
3720         int line = -1;
3721         dns_rdataset_t tmprdataset;
3722         unsigned int dboptions;
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         dboptions = client->query.dboptions;
3941         if (sigrdataset == NULL && client->view->enablednssec) {
3942                 /*
3943                  * If the client doesn't want DNSSEC we still want to
3944                  * look for any data pending validation to save a remote
3945                  * lookup if possible.
3946                  */
3947                 dns_rdataset_init(&tmprdataset);
3948                 sigrdataset = &tmprdataset;
3949                 dboptions |= DNS_DBFIND_PENDINGOK;
3950         }
3951  refind:
3952         result = dns_db_find(db, client->query.qname, version, type,
3953                              dboptions, client->now, &node, fname,
3954                              rdataset, sigrdataset);
3955         /*
3956          * If we have found pending data try to validate it.
3957          * If the data does not validate as secure and we can't
3958          * use the unvalidated data requery the database with
3959          * pending disabled to prevent infinite looping.
3960          */
3961         if (result != ISC_R_SUCCESS || !DNS_TRUST_PENDING(rdataset->trust))
3962                 goto validation_done;
3963         if (validate(client, db, fname, rdataset, sigrdataset))
3964                 goto validation_done;
3965         if (rdataset->trust != dns_trust_pending_answer ||
3966             !PENDINGOK(client->query.dboptions)) {
3967                 dns_rdataset_disassociate(rdataset);
3968                 if (sigrdataset != NULL &&
3969                     dns_rdataset_isassociated(sigrdataset))
3970                         dns_rdataset_disassociate(sigrdataset);
3971                 if (sigrdataset == &tmprdataset)
3972                         sigrdataset = NULL;
3973                 dns_db_detachnode(db, &node);
3974                 dboptions &= ~DNS_DBFIND_PENDINGOK;
3975                 goto refind;
3976         }
3977  validation_done:
3978         if (sigrdataset == &tmprdataset) {
3979                 if (dns_rdataset_isassociated(sigrdataset))
3980                         dns_rdataset_disassociate(sigrdataset);
3981                 sigrdataset = NULL;
3982         }
3983
3984  resume:
3985         CTRACE("query_find: resume");
3986         switch (result) {
3987         case ISC_R_SUCCESS:
3988                 /*
3989                  * This case is handled in the main line below.
3990                  */
3991                 break;
3992         case DNS_R_GLUE:
3993         case DNS_R_ZONECUT:
3994                 /*
3995                  * These cases are handled in the main line below.
3996                  */
3997                 INSIST(is_zone);
3998                 authoritative = ISC_FALSE;
3999                 break;
4000         case ISC_R_NOTFOUND:
4001                 /*
4002                  * The cache doesn't even have the root NS.  Get them from
4003                  * the hints DB.
4004                  */
4005                 INSIST(!is_zone);
4006                 if (db != NULL)
4007                         dns_db_detach(&db);
4008
4009                 if (client->view->hints == NULL) {
4010                         /* We have no hints. */
4011                         result = ISC_R_FAILURE;
4012                 } else {
4013                         dns_db_attach(client->view->hints, &db);
4014                         result = dns_db_find(db, dns_rootname,
4015                                              NULL, dns_rdatatype_ns,
4016                                              0, client->now, &node, fname,
4017                                              rdataset, sigrdataset);
4018                 }
4019                 if (result != ISC_R_SUCCESS) {
4020                         /*
4021                          * Nonsensical root hints may require cleanup.
4022                          */
4023                         if (dns_rdataset_isassociated(rdataset))
4024                                 dns_rdataset_disassociate(rdataset);
4025                         if (sigrdataset != NULL &&
4026                             dns_rdataset_isassociated(sigrdataset))
4027                                 dns_rdataset_disassociate(sigrdataset);
4028                         if (node != NULL)
4029                                 dns_db_detachnode(db, &node);
4030
4031                         /*
4032                          * We don't have any root server hints, but
4033                          * we may have working forwarders, so try to
4034                          * recurse anyway.
4035                          */
4036                         if (RECURSIONOK(client)) {
4037                                 result = query_recurse(client, qtype,
4038                                                        NULL, NULL, resuming);
4039                                 if (result == ISC_R_SUCCESS)
4040                                         client->query.attributes |=
4041                                                 NS_QUERYATTR_RECURSING;
4042                                 else if (result == DNS_R_DUPLICATE ||
4043                                          result == DNS_R_DROP) {
4044                                         /* Duplicate query. */
4045                                         QUERY_ERROR(result);
4046                                 } else {
4047                                         /* Unable to recurse. */
4048                                         QUERY_ERROR(DNS_R_SERVFAIL);
4049                                 }
4050                                 goto cleanup;
4051                         } else {
4052                                 /* Unable to give root server referral. */
4053                                 QUERY_ERROR(DNS_R_SERVFAIL);
4054                                 goto cleanup;
4055                         }
4056                 }
4057                 /*
4058                  * XXXRTH  We should trigger root server priming here.
4059                  */
4060                 /* FALLTHROUGH */
4061         case DNS_R_DELEGATION:
4062                 authoritative = ISC_FALSE;
4063                 if (is_zone) {
4064                         /*
4065                          * Look to see if we are authoritative for the
4066                          * child zone if the query type is DS.
4067                          */
4068                         if (!RECURSIONOK(client) &&
4069                             (options & DNS_GETDB_NOEXACT) != 0 &&
4070                             qtype == dns_rdatatype_ds) {
4071                                 dns_db_t *tdb = NULL;
4072                                 dns_zone_t *tzone = NULL;
4073                                 dns_dbversion_t *tversion = NULL;
4074                                 result = query_getzonedb(client,
4075                                                          client->query.qname,
4076                                                          qtype,
4077                                                          DNS_GETDB_PARTIAL,
4078                                                          &tzone, &tdb,
4079                                                          &tversion);
4080                                 if (result == ISC_R_SUCCESS) {
4081                                         options &= ~DNS_GETDB_NOEXACT;
4082                                         query_putrdataset(client, &rdataset);
4083                                         if (sigrdataset != NULL)
4084                                                 query_putrdataset(client,
4085                                                                   &sigrdataset);
4086                                         if (fname != NULL)
4087                                                 query_releasename(client,
4088                                                                   &fname);
4089                                         if (node != NULL)
4090                                                 dns_db_detachnode(db, &node);
4091                                         if (db != NULL)
4092                                                 dns_db_detach(&db);
4093                                         if (zone != NULL)
4094                                                 dns_zone_detach(&zone);
4095                                         version = tversion;
4096                                         db = tdb;
4097                                         zone = tzone;
4098                                         authoritative = ISC_TRUE;
4099                                         goto db_find;
4100                                 }
4101                                 if (tdb != NULL)
4102                                         dns_db_detach(&tdb);
4103                                 if (tzone != NULL)
4104                                         dns_zone_detach(&tzone);
4105                         }
4106                         /*
4107                          * We're authoritative for an ancestor of QNAME.
4108                          */
4109                         if (!USECACHE(client) || !RECURSIONOK(client)) {
4110                                 dns_fixedname_t fixed;
4111
4112                                 dns_fixedname_init(&fixed);
4113                                 dns_name_copy(fname,
4114                                               dns_fixedname_name(&fixed), NULL);
4115
4116                                 /*
4117                                  * If we don't have a cache, this is the best
4118                                  * answer.
4119                                  *
4120                                  * If the client is making a nonrecursive
4121                                  * query we always give out the authoritative
4122                                  * delegation.  This way even if we get
4123                                  * junk in our cache, we won't fail in our
4124                                  * role as the delegating authority if another
4125                                  * nameserver asks us about a delegated
4126                                  * subzone.
4127                                  *
4128                                  * We enable the retrieval of glue for this
4129                                  * database by setting client->query.gluedb.
4130                                  */
4131                                 client->query.gluedb = db;
4132                                 client->query.isreferral = ISC_TRUE;
4133                                 /*
4134                                  * We must ensure NOADDITIONAL is off,
4135                                  * because the generation of
4136                                  * additional data is required in
4137                                  * delegations.
4138                                  */
4139                                 client->query.attributes &=
4140                                         ~NS_QUERYATTR_NOADDITIONAL;
4141                                 if (sigrdataset != NULL)
4142                                         sigrdatasetp = &sigrdataset;
4143                                 else
4144                                         sigrdatasetp = NULL;
4145                                 query_addrrset(client, &fname,
4146                                                &rdataset, sigrdatasetp,
4147                                                dbuf, DNS_SECTION_AUTHORITY);
4148                                 client->query.gluedb = NULL;
4149                                 if (WANTDNSSEC(client))
4150                                         query_addds(client, db, node, version,
4151                                                    dns_fixedname_name(&fixed));
4152                         } else {
4153                                 /*
4154                                  * We might have a better answer or delegation
4155                                  * in the cache.  We'll remember the current
4156                                  * values of fname, rdataset, and sigrdataset.
4157                                  * We'll then go looking for QNAME in the
4158                                  * cache.  If we find something better, we'll
4159                                  * use it instead.
4160                                  */
4161                                 query_keepname(client, fname, dbuf);
4162                                 zdb = db;
4163                                 zfname = fname;
4164                                 fname = NULL;
4165                                 zrdataset = rdataset;
4166                                 rdataset = NULL;
4167                                 zsigrdataset = sigrdataset;
4168                                 sigrdataset = NULL;
4169                                 dns_db_detachnode(db, &node);
4170                                 zversion = version;
4171                                 version = NULL;
4172                                 db = NULL;
4173                                 dns_db_attach(client->view->cachedb, &db);
4174                                 is_zone = ISC_FALSE;
4175                                 goto db_find;
4176                         }
4177                 } else {
4178                         if (zfname != NULL &&
4179                             !dns_name_issubdomain(fname, zfname)) {
4180                                 /*
4181                                  * We've already got a delegation from
4182                                  * authoritative data, and it is better
4183                                  * than what we found in the cache.  Use
4184                                  * it instead of the cache delegation.
4185                                  */
4186                                 query_releasename(client, &fname);
4187                                 fname = zfname;
4188                                 zfname = NULL;
4189                                 /*
4190                                  * We've already done query_keepname() on
4191                                  * zfname, so we must set dbuf to NULL to
4192                                  * prevent query_addrrset() from trying to
4193                                  * call query_keepname() again.
4194                                  */
4195                                 dbuf = NULL;
4196                                 query_putrdataset(client, &rdataset);
4197                                 if (sigrdataset != NULL)
4198                                         query_putrdataset(client,
4199                                                           &sigrdataset);
4200                                 rdataset = zrdataset;
4201                                 zrdataset = NULL;
4202                                 sigrdataset = zsigrdataset;
4203                                 zsigrdataset = NULL;
4204                                 version = zversion;
4205                                 zversion = NULL;
4206                                 /*
4207                                  * We don't clean up zdb here because we
4208                                  * may still need it.  It will get cleaned
4209                                  * up by the main cleanup code.
4210                                  */
4211                         }
4212
4213                         if (RECURSIONOK(client)) {
4214                                 /*
4215                                  * Recurse!
4216                                  */
4217                                 if (dns_rdatatype_atparent(type))
4218                                         result = query_recurse(client, qtype,
4219                                                                NULL, NULL,
4220                                                                resuming);
4221                                 else
4222                                         result = query_recurse(client, qtype,
4223                                                                fname, rdataset,
4224                                                                resuming);
4225                                 if (result == ISC_R_SUCCESS)
4226                                         client->query.attributes |=
4227                                                 NS_QUERYATTR_RECURSING;
4228                                 else if (result == DNS_R_DUPLICATE ||
4229                                          result == DNS_R_DROP)
4230                                         QUERY_ERROR(result);
4231                                 else
4232                                         QUERY_ERROR(DNS_R_SERVFAIL);
4233                         } else {
4234                                 dns_fixedname_t fixed;
4235
4236                                 dns_fixedname_init(&fixed);
4237                                 dns_name_copy(fname,
4238                                               dns_fixedname_name(&fixed), NULL);
4239                                 /*
4240                                  * This is the best answer.
4241                                  */
4242                                 client->query.attributes |=
4243                                         NS_QUERYATTR_CACHEGLUEOK;
4244                                 client->query.gluedb = zdb;
4245                                 client->query.isreferral = ISC_TRUE;
4246                                 /*
4247                                  * We must ensure NOADDITIONAL is off,
4248                                  * because the generation of
4249                                  * additional data is required in
4250                                  * delegations.
4251                                  */
4252                                 client->query.attributes &=
4253                                         ~NS_QUERYATTR_NOADDITIONAL;
4254                                 if (sigrdataset != NULL)
4255                                         sigrdatasetp = &sigrdataset;
4256                                 else
4257                                         sigrdatasetp = NULL;
4258                                 query_addrrset(client, &fname,
4259                                                &rdataset, sigrdatasetp,
4260                                                dbuf, DNS_SECTION_AUTHORITY);
4261                                 client->query.gluedb = NULL;
4262                                 client->query.attributes &=
4263                                         ~NS_QUERYATTR_CACHEGLUEOK;
4264                                 if (WANTDNSSEC(client))
4265                                         query_addds(client, db, node, version,
4266                                                    dns_fixedname_name(&fixed));
4267                         }
4268                 }
4269                 goto cleanup;
4270         case DNS_R_EMPTYNAME:
4271                 result = DNS_R_NXRRSET;
4272                 /* FALLTHROUGH */
4273         case DNS_R_NXRRSET:
4274                 INSIST(is_zone);
4275                 /*
4276                  * Look for a NSEC3 record if we don't have a NSEC record.
4277                  */
4278                 if (!dns_rdataset_isassociated(rdataset) &&
4279                      WANTDNSSEC(client)) {
4280                         if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
4281                                 dns_name_t *found;
4282                                 dns_name_t *qname;
4283
4284                                 dns_fixedname_init(&fixed);
4285                                 found = dns_fixedname_name(&fixed);
4286                                 qname = client->query.qname;
4287
4288                                 query_findclosestnsec3(qname, db, version,
4289                                                        client, rdataset,
4290                                                        sigrdataset, fname,
4291                                                        ISC_TRUE, found);
4292                                 /*
4293                                  * Did we find the closest provable encloser
4294                                  * instead? If so add the nearest to the
4295                                  * closest provable encloser.
4296                                  */
4297                                 if (found &&
4298                                     dns_rdataset_isassociated(rdataset) &&
4299                                     !dns_name_equal(qname, found))
4300                                 {
4301                                         unsigned int count;
4302                                         unsigned int skip;
4303
4304                                         /*
4305                                          * Add the closest provable encloser.
4306                                          */
4307                                         query_addrrset(client, &fname,
4308                                                        &rdataset, &sigrdataset,
4309                                                        dbuf,
4310                                                        DNS_SECTION_AUTHORITY);
4311
4312                                         count = dns_name_countlabels(found)
4313                                                          + 1;
4314                                         skip = dns_name_countlabels(qname) -
4315                                                          count;
4316                                         dns_name_getlabelsequence(qname, skip,
4317                                                                   count,
4318                                                                   found);
4319
4320                                         fixfname(client, &fname, &dbuf, &b);
4321                                         fixrdataset(client, &rdataset);
4322                                         fixrdataset(client, &sigrdataset);
4323                                         if (fname == NULL ||
4324                                             rdataset == NULL ||
4325                                             sigrdataset == NULL) {
4326                                                 QUERY_ERROR(DNS_R_SERVFAIL);
4327                                                 goto cleanup;
4328                                         }
4329                                         /*
4330                                          * 'nearest' doesn't exist so
4331                                          * 'exist' is set to ISC_FALSE.
4332                                          */
4333                                         query_findclosestnsec3(found, db,
4334                                                                version,
4335                                                                client,
4336                                                                rdataset,
4337                                                                sigrdataset,
4338                                                                fname,
4339                                                                ISC_FALSE,
4340                                                                NULL);
4341                                 }
4342                         } else {
4343                                 query_releasename(client, &fname);
4344                                 query_addwildcardproof(client, db, version,
4345                                                        client->query.qname,
4346                                                        ISC_FALSE);
4347                         }
4348                 }
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.
4366                  */
4367                 result = query_addsoa(client, db, version, ISC_FALSE);
4368                 if (result != ISC_R_SUCCESS) {
4369                         QUERY_ERROR(result);
4370                         goto cleanup;
4371                 }
4372                 /*
4373                  * Add NSEC record if we found one.
4374                  */
4375                 if (WANTDNSSEC(client)) {
4376                         if (dns_rdataset_isassociated(rdataset))
4377                                 query_addnxrrsetnsec(client, db, version,
4378                                                      &fname, &rdataset,
4379                                                      &sigrdataset);
4380                 }
4381                 goto cleanup;
4382
4383         case DNS_R_EMPTYWILD:
4384                 empty_wild = ISC_TRUE;
4385                 /* FALLTHROUGH */
4386
4387         case DNS_R_NXDOMAIN:
4388                 INSIST(is_zone);
4389                 if (dns_rdataset_isassociated(rdataset)) {
4390                         /*
4391                          * If we've got a NSEC record, we need to save the
4392                          * name now because we're going call query_addsoa()
4393                          * below, and it needs to use the name buffer.
4394                          */
4395                         query_keepname(client, fname, dbuf);
4396                 } else if (fname != NULL) {
4397                         /*
4398                          * We're not going to use fname, and need to release
4399                          * our hold on the name buffer so query_addsoa()
4400                          * may use it.
4401                          */
4402                         query_releasename(client, &fname);
4403                 }
4404                 /*
4405                  * Add SOA.  If the query was for a SOA record force the
4406                  * ttl to zero so that it is possible for clients to find
4407                  * the containing zone of an arbitrary name with a stub
4408                  * resolver and not have it cached.
4409                  */
4410                 if (qtype == dns_rdatatype_soa &&
4411 #ifdef DLZ
4412                     zone != NULL &&
4413 #endif
4414                     dns_zone_getzeronosoattl(zone))
4415                         result = query_addsoa(client, db, version, ISC_TRUE);
4416                 else
4417                         result = query_addsoa(client, db, version, ISC_FALSE);
4418                 if (result != ISC_R_SUCCESS) {
4419                         QUERY_ERROR(result);
4420                         goto cleanup;
4421                 }
4422
4423                 if (WANTDNSSEC(client)) {
4424                         /*
4425                          * Add NSEC record if we found one.
4426                          */
4427                         if (dns_rdataset_isassociated(rdataset))
4428                                 query_addrrset(client, &fname, &rdataset,
4429                                                &sigrdataset,
4430                                                NULL, DNS_SECTION_AUTHORITY);
4431                         query_addwildcardproof(client, db, version,
4432                                                client->query.qname, ISC_FALSE);
4433                 }
4434
4435                 /*
4436                  * Set message rcode.
4437                  */
4438                 if (empty_wild)
4439                         client->message->rcode = dns_rcode_noerror;
4440                 else
4441                         client->message->rcode = dns_rcode_nxdomain;
4442                 goto cleanup;
4443
4444         case DNS_R_NCACHENXDOMAIN:
4445         case DNS_R_NCACHENXRRSET:
4446                 INSIST(!is_zone);
4447                 authoritative = ISC_FALSE;
4448                 /*
4449                  * Set message rcode, if required.
4450                  */
4451                 if (result == DNS_R_NCACHENXDOMAIN)
4452                         client->message->rcode = dns_rcode_nxdomain;
4453                 /*
4454                  * Look for RFC 1918 leakage from Internet.
4455                  */
4456                 if (result == DNS_R_NCACHENXDOMAIN &&
4457                     qtype == dns_rdatatype_ptr &&
4458                     client->message->rdclass == dns_rdataclass_in &&
4459                     dns_name_countlabels(fname) == 7)
4460                         warn_rfc1918(client, fname, rdataset);
4461                 /*
4462                  * We don't call query_addrrset() because we don't need any
4463                  * of its extra features (and things would probably break!).
4464                  */
4465                 query_keepname(client, fname, dbuf);
4466                 dns_message_addname(client->message, fname,
4467                                     DNS_SECTION_AUTHORITY);
4468                 ISC_LIST_APPEND(fname->list, rdataset, link);
4469                 fname = NULL;
4470                 rdataset = NULL;
4471                 goto cleanup;
4472
4473         case DNS_R_CNAME:
4474                 /*
4475                  * Keep a copy of the rdataset.  We have to do this because
4476                  * query_addrrset may clear 'rdataset' (to prevent the
4477                  * cleanup code from cleaning it up).
4478                  */
4479                 trdataset = rdataset;
4480                 /*
4481                  * Add the CNAME to the answer section.
4482                  */
4483                 if (sigrdataset != NULL)
4484                         sigrdatasetp = &sigrdataset;
4485                 else
4486                         sigrdatasetp = NULL;
4487                 if (WANTDNSSEC(client) &&
4488                     (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
4489                 {
4490                         dns_fixedname_init(&wildcardname);
4491                         dns_name_copy(fname, dns_fixedname_name(&wildcardname),
4492                                       NULL);
4493                         need_wildcardproof = ISC_TRUE;
4494                 }
4495                 if (NOQNAME(rdataset) && WANTDNSSEC(client))
4496                         noqname = rdataset;
4497                 else
4498                         noqname = NULL;
4499                 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
4500                                DNS_SECTION_ANSWER);
4501                 if (noqname != NULL)
4502                         query_addnoqnameproof(client, noqname);
4503                 /*
4504                  * We set the PARTIALANSWER attribute so that if anything goes
4505                  * wrong later on, we'll return what we've got so far.
4506                  */
4507                 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
4508                 /*
4509                  * Reset qname to be the target name of the CNAME and restart
4510                  * the query.
4511                  */
4512                 tname = NULL;
4513                 result = dns_message_gettempname(client->message, &tname);
4514                 if (result != ISC_R_SUCCESS)
4515                         goto cleanup;
4516                 result = dns_rdataset_first(trdataset);
4517                 if (result != ISC_R_SUCCESS) {
4518                         dns_message_puttempname(client->message, &tname);
4519                         goto cleanup;
4520                 }
4521                 dns_rdataset_current(trdataset, &rdata);
4522                 result = dns_rdata_tostruct(&rdata, &cname, NULL);
4523                 dns_rdata_reset(&rdata);
4524                 if (result != ISC_R_SUCCESS) {
4525                         dns_message_puttempname(client->message, &tname);
4526                         goto cleanup;
4527                 }
4528                 dns_name_init(tname, NULL);
4529                 result = dns_name_dup(&cname.cname, client->mctx, tname);
4530                 if (result != ISC_R_SUCCESS) {
4531                         dns_message_puttempname(client->message, &tname);
4532                         dns_rdata_freestruct(&cname);
4533                         goto cleanup;
4534                 }
4535                 dns_rdata_freestruct(&cname);
4536                 ns_client_qnamereplace(client, tname);
4537                 want_restart = ISC_TRUE;
4538                 if (!WANTRECURSION(client))
4539                         options |= DNS_GETDB_NOLOG;
4540                 goto addauth;
4541         case DNS_R_DNAME:
4542                 /*
4543                  * Compare the current qname to the found name.  We need
4544                  * to know how many labels and bits are in common because
4545                  * we're going to have to split qname later on.
4546                  */
4547                 namereln = dns_name_fullcompare(client->query.qname, fname,
4548                                                 &order, &nlabels);
4549                 INSIST(namereln == dns_namereln_subdomain);
4550                 /*
4551                  * Keep a copy of the rdataset.  We have to do this because
4552                  * query_addrrset may clear 'rdataset' (to prevent the
4553                  * cleanup code from cleaning it up).
4554                  */
4555                 trdataset = rdataset;
4556                 /*
4557                  * Add the DNAME to the answer section.
4558                  */
4559                 if (sigrdataset != NULL)
4560                         sigrdatasetp = &sigrdataset;
4561                 else
4562                         sigrdatasetp = NULL;
4563                 if (WANTDNSSEC(client) &&
4564                     (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
4565                 {
4566                         dns_fixedname_init(&wildcardname);
4567                         dns_name_copy(fname, dns_fixedname_name(&wildcardname),
4568                                       NULL);
4569                         need_wildcardproof = ISC_TRUE;
4570                 }
4571                 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
4572                                DNS_SECTION_ANSWER);
4573                 /*
4574                  * We set the PARTIALANSWER attribute so that if anything goes
4575                  * wrong later on, we'll return what we've got so far.
4576                  */
4577                 client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
4578                 /*
4579                  * Get the target name of the DNAME.
4580                  */
4581                 tname = NULL;
4582                 result = dns_message_gettempname(client->message, &tname);
4583                 if (result != ISC_R_SUCCESS)
4584                         goto cleanup;
4585                 result = dns_rdataset_first(trdataset);
4586                 if (result != ISC_R_SUCCESS) {
4587                         dns_message_puttempname(client->message, &tname);
4588                         goto cleanup;
4589                 }
4590                 dns_rdataset_current(trdataset, &rdata);
4591                 result = dns_rdata_tostruct(&rdata, &dname, NULL);
4592                 dns_rdata_reset(&rdata);
4593                 if (result != ISC_R_SUCCESS) {
4594                         dns_message_puttempname(client->message, &tname);
4595                         goto cleanup;
4596                 }
4597                 dns_name_init(tname, NULL);
4598                 dns_name_clone(&dname.dname, tname);
4599                 dns_rdata_freestruct(&dname);
4600                 /*
4601                  * Construct the new qname.
4602                  */
4603                 dns_fixedname_init(&fixed);
4604                 prefix = dns_fixedname_name(&fixed);
4605                 dns_name_split(client->query.qname, nlabels, prefix, NULL);
4606                 INSIST(fname == NULL);
4607                 dbuf = query_getnamebuf(client);
4608                 if (dbuf == NULL) {
4609                         dns_message_puttempname(client->message, &tname);
4610                         goto cleanup;
4611                 }
4612                 fname = query_newname(client, dbuf, &b);
4613                 if (fname == NULL) {
4614                         dns_message_puttempname(client->message, &tname);
4615                         goto cleanup;
4616                 }
4617                 result = dns_name_concatenate(prefix, tname, fname, NULL);
4618                 if (result != ISC_R_SUCCESS) {
4619                         dns_message_puttempname(client->message, &tname);
4620                         if (result == ISC_R_NOSPACE) {
4621                                 /*
4622                                  * RFC2672, section 4.1, subsection 3c says
4623                                  * we should return YXDOMAIN if the constructed
4624                                  * name would be too long.
4625                                  */
4626                                 client->message->rcode = dns_rcode_yxdomain;
4627                         }
4628                         goto cleanup;
4629                 }
4630                 query_keepname(client, fname, dbuf);
4631                 /*
4632                  * Synthesize a CNAME for this DNAME.
4633                  *
4634                  * We want to synthesize a CNAME since if we don't
4635                  * then older software that doesn't understand DNAME
4636                  * will not chain like it should.
4637                  *
4638                  * We do not try to synthesize a signature because we hope
4639                  * that security aware servers will understand DNAME.  Also,
4640                  * even if we had an online key, making a signature
4641                  * on-the-fly is costly, and not really legitimate anyway
4642                  * since the synthesized CNAME is NOT in the zone.
4643                  */
4644                 dns_name_init(tname, NULL);
4645                 (void)query_addcnamelike(client, client->query.qname, fname,
4646                                          trdataset->trust, &tname,
4647                                          dns_rdatatype_cname);
4648                 if (tname != NULL)
4649                         dns_message_puttempname(client->message, &tname);
4650                 /*
4651                  * Switch to the new qname and restart.
4652                  */
4653                 ns_client_qnamereplace(client, fname);
4654                 fname = NULL;
4655                 want_restart = ISC_TRUE;
4656                 if (!WANTRECURSION(client))
4657                         options |= DNS_GETDB_NOLOG;
4658                 goto addauth;
4659         default:
4660                 /*
4661                  * Something has gone wrong.
4662                  */
4663                 QUERY_ERROR(DNS_R_SERVFAIL);
4664                 goto cleanup;
4665         }
4666
4667         if (WANTDNSSEC(client) &&
4668             (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
4669         {
4670                 dns_fixedname_init(&wildcardname);
4671                 dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL);
4672                 need_wildcardproof = ISC_TRUE;
4673         }
4674
4675         if (type == dns_rdatatype_any) {
4676                 /*
4677                  * XXXRTH  Need to handle zonecuts with special case
4678                  * code.
4679                  */
4680                 n = 0;
4681                 rdsiter = NULL;
4682                 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
4683                 if (result != ISC_R_SUCCESS) {
4684                         QUERY_ERROR(DNS_R_SERVFAIL);
4685                         goto cleanup;
4686                 }
4687                 /*
4688                  * Calling query_addrrset() with a non-NULL dbuf is going
4689                  * to either keep or release the name.  We don't want it to
4690                  * release fname, since we may have to call query_addrrset()
4691                  * more than once.  That means we have to call query_keepname()
4692                  * now, and pass a NULL dbuf to query_addrrset().
4693                  *
4694                  * If we do a query_addrrset() below, we must set fname to
4695                  * NULL before leaving this block, otherwise we might try to
4696                  * cleanup fname even though we're using it!
4697                  */
4698                 query_keepname(client, fname, dbuf);
4699                 tname = fname;
4700                 result = dns_rdatasetiter_first(rdsiter);
4701                 while (result == ISC_R_SUCCESS) {
4702                         dns_rdatasetiter_current(rdsiter, rdataset);
4703                         if (is_zone && qtype == dns_rdatatype_any &&
4704                             !dns_db_issecure(db) &&
4705                             dns_rdatatype_isdnssec(rdataset->type)) {
4706                                 /*
4707                                  * The zone is transitioning from insecure
4708                                  * to secure. Hide the dnssec records from
4709                                  * ANY queries.
4710                                  */
4711                                 dns_rdataset_disassociate(rdataset);
4712                         } else if ((qtype == dns_rdatatype_any ||
4713                              rdataset->type == qtype) && rdataset->type != 0) {
4714                                 if (NOQNAME(rdataset) && WANTDNSSEC(client))
4715                                         noqname = rdataset;
4716                                 else
4717                                         noqname = NULL;
4718                                 query_addrrset(client,
4719                                                fname != NULL ? &fname : &tname,
4720                                                &rdataset, NULL,
4721                                                NULL, DNS_SECTION_ANSWER);
4722                                 if (noqname != NULL)
4723                                         query_addnoqnameproof(client, noqname);
4724                                 n++;
4725                                 INSIST(tname != NULL);
4726                                 /*
4727                                  * rdataset is non-NULL only in certain
4728                                  * pathological cases involving DNAMEs.
4729                                  */
4730                                 if (rdataset != NULL)
4731                                         query_putrdataset(client, &rdataset);
4732                                 rdataset = query_newrdataset(client);
4733                                 if (rdataset == NULL)
4734                                         break;
4735                         } else {
4736                                 /*
4737                                  * We're not interested in this rdataset.
4738                                  */
4739                                 dns_rdataset_disassociate(rdataset);
4740                         }
4741                         result = dns_rdatasetiter_next(rdsiter);
4742                 }
4743
4744                 if (fname != NULL)
4745                         dns_message_puttempname(client->message, &fname);
4746
4747                 if (n == 0 && is_zone) {
4748                         /*
4749                          * We didn't match any rdatasets.
4750                          */
4751                         if (qtype == dns_rdatatype_rrsig &&
4752                             result == ISC_R_NOMORE) {
4753                                 /*
4754                                  * XXXRTH  If this is a secure zone and we
4755                                  * didn't find any SIGs, we should generate
4756                                  * an error unless we were searching for
4757                                  * glue.  Ugh.
4758                                  */
4759                                 if (!is_zone) {
4760                                         authoritative = ISC_FALSE;
4761                                         dns_rdatasetiter_destroy(&rdsiter);
4762                                         if (RECURSIONOK(client)) {
4763                                                 result = query_recurse(client,
4764                                                                        qtype,
4765                                                                        NULL,
4766                                                                        NULL,
4767                                                                        resuming);
4768                                                 if (result == ISC_R_SUCCESS)
4769                                                     client->query.attributes |=
4770                                                         NS_QUERYATTR_RECURSING;
4771                                                 else
4772                                                     QUERY_ERROR(DNS_R_SERVFAIL);                                        }
4773                                         goto addauth;
4774                                 }
4775                                 /*
4776                                  * We were searching for SIG records in
4777                                  * a nonsecure zone.  Send a "no error,
4778                                  * no data" response.
4779                                  */
4780                                 /*
4781                                  * Add SOA.
4782                                  */
4783                                 result = query_addsoa(client, db, version,
4784                                                       ISC_FALSE);
4785                                 if (result == ISC_R_SUCCESS)
4786                                         result = ISC_R_NOMORE;
4787                         } else {
4788                                 /*
4789                                  * Something went wrong.
4790                                  */
4791                                 result = DNS_R_SERVFAIL;
4792                         }
4793                 }
4794                 dns_rdatasetiter_destroy(&rdsiter);
4795                 if (result != ISC_R_NOMORE) {
4796                         QUERY_ERROR(DNS_R_SERVFAIL);
4797                         goto cleanup;
4798                 }
4799         } else {
4800                 /*
4801                  * This is the "normal" case -- an ordinary question to which
4802                  * we know the answer.
4803                  */
4804                 if (sigrdataset != NULL)
4805                         sigrdatasetp = &sigrdataset;
4806                 else
4807                         sigrdatasetp = NULL;
4808                 if (NOQNAME(rdataset) && WANTDNSSEC(client))
4809                         noqname = rdataset;
4810                 else
4811                         noqname = NULL;
4812                 /*
4813                  * BIND 8 priming queries need the additional section.
4814                  */
4815                 if (is_zone && qtype == dns_rdatatype_ns &&
4816                     dns_name_equal(client->query.qname, dns_rootname))
4817                         client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL;
4818
4819                 query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
4820                                DNS_SECTION_ANSWER);
4821                 if (noqname != NULL)
4822                         query_addnoqnameproof(client, noqname);
4823                 /*
4824                  * We shouldn't ever fail to add 'rdataset'
4825                  * because it's already in the answer.
4826                  */
4827                 INSIST(rdataset == NULL);
4828         }
4829
4830  addauth:
4831         CTRACE("query_find: addauth");
4832         /*
4833          * Add NS records to the authority section (if we haven't already
4834          * added them to the answer section).
4835          */
4836         if (!want_restart && !NOAUTHORITY(client)) {
4837                 if (is_zone) {
4838                         if (!((qtype == dns_rdatatype_ns ||
4839                                qtype == dns_rdatatype_any) &&
4840                               dns_name_equal(client->query.qname,
4841                                              dns_db_origin(db))))
4842                                 (void)query_addns(client, db, version);
4843                 } else if (qtype != dns_rdatatype_ns) {
4844                         if (fname != NULL)
4845                                 query_releasename(client, &fname);
4846                         query_addbestns(client);
4847                 }
4848         }
4849
4850         /*
4851          * Add NSEC records to the authority section if they're needed for
4852          * DNSSEC wildcard proofs.
4853          */
4854         if (need_wildcardproof && dns_db_issecure(db))
4855                 query_addwildcardproof(client, db, version,
4856                                        dns_fixedname_name(&wildcardname),
4857                                        ISC_TRUE);
4858  cleanup:
4859         CTRACE("query_find: cleanup");
4860         /*
4861          * General cleanup.
4862          */
4863         if (rdataset != NULL)
4864                 query_putrdataset(client, &rdataset);
4865         if (sigrdataset != NULL)
4866                 query_putrdataset(client, &sigrdataset);
4867         if (fname != NULL)
4868                 query_releasename(client, &fname);
4869         if (node != NULL)
4870                 dns_db_detachnode(db, &node);
4871         if (db != NULL)
4872                 dns_db_detach(&db);
4873         if (zone != NULL)
4874                 dns_zone_detach(&zone);
4875         if (zdb != NULL) {
4876                 query_putrdataset(client, &zrdataset);
4877                 if (zsigrdataset != NULL)
4878                         query_putrdataset(client, &zsigrdataset);
4879                 if (zfname != NULL)
4880                         query_releasename(client, &zfname);
4881                 dns_db_detach(&zdb);
4882         }
4883         if (event != NULL)
4884                 isc_event_free(ISC_EVENT_PTR(&event));
4885
4886         /*
4887          * AA bit.
4888          */
4889         if (client->query.restarts == 0 && !authoritative) {
4890                 /*
4891                  * We're not authoritative, so we must ensure the AA bit
4892                  * isn't set.
4893                  */
4894                 client->message->flags &= ~DNS_MESSAGEFLAG_AA;
4895         }
4896
4897         /*
4898          * Restart the query?
4899          */
4900         if (want_restart && client->query.restarts < MAX_RESTARTS) {
4901                 client->query.restarts++;
4902                 goto restart;
4903         }
4904
4905         if (eresult != ISC_R_SUCCESS &&
4906             (!PARTIALANSWER(client) || WANTRECURSION(client))) {
4907                 if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) {
4908                         /*
4909                          * This was a duplicate query that we are
4910                          * recursing on.  Don't send a response now.
4911                          * The original query will still cause a response.
4912                          */
4913                         query_next(client, eresult);
4914                 } else {
4915                         /*
4916                          * If we don't have any answer to give the client,
4917                          * or if the client requested recursion and thus wanted
4918                          * the complete answer, send an error response.
4919                          */
4920                         INSIST(line >= 0);
4921                         query_error(client, eresult, line);
4922                 }
4923                 ns_client_detach(&client);
4924         } else if (!RECURSING(client)) {
4925                 /*
4926                  * We are done.  Set up sortlist data for the message
4927                  * rendering code, make a final tweak to the AA bit if the
4928                  * auth-nxdomain config option says so, then render and
4929                  * send the response.
4930                  */
4931                 setup_query_sortlist(client);
4932
4933                 /*
4934                  * If this is a referral and the answer to the question
4935                  * is in the glue sort it to the start of the additional
4936                  * section.
4937                  */
4938                 if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) &&
4939                     client->message->rcode == dns_rcode_noerror &&
4940                     (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa))
4941                         answer_in_glue(client, qtype);
4942
4943                 if (client->message->rcode == dns_rcode_nxdomain &&
4944                     client->view->auth_nxdomain == ISC_TRUE)
4945                         client->message->flags |= DNS_MESSAGEFLAG_AA;
4946
4947                 /*
4948                  * If the response is somehow unexpected for the client and this
4949                  * is a result of recursion, return an error to the caller
4950                  * to indicate it may need to be logged.
4951                  */
4952                 if (resuming &&
4953                     (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) ||
4954                      client->message->rcode != dns_rcode_noerror))
4955                         eresult = ISC_R_FAILURE;
4956
4957                 query_send(client);
4958                 ns_client_detach(&client);
4959         }
4960         CTRACE("query_find: done");
4961
4962         return (eresult);
4963 }
4964
4965 static inline void
4966 log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
4967         char namebuf[DNS_NAME_FORMATSIZE];
4968         char typename[DNS_RDATATYPE_FORMATSIZE];
4969         char classname[DNS_RDATACLASS_FORMATSIZE];
4970         dns_rdataset_t *rdataset;
4971         int level = ISC_LOG_INFO;
4972
4973         if (! isc_log_wouldlog(ns_g_lctx, level))
4974                 return;
4975
4976         rdataset = ISC_LIST_HEAD(client->query.qname->list);
4977         INSIST(rdataset != NULL);
4978         dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
4979         dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname));
4980         dns_rdatatype_format(rdataset->type, typename, sizeof(typename));
4981
4982         ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
4983                       level, "query: %s %s %s %s%s%s%s%s", namebuf, classname,
4984                       typename, WANTRECURSION(client) ? "+" : "-",
4985                       (client->signer != NULL) ? "S": "",
4986                       (client->opt != NULL) ? "E" : "",
4987                       ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
4988                       ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "");
4989 }
4990
4991 static inline void
4992 log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) {
4993         char namebuf[DNS_NAME_FORMATSIZE];
4994         char typename[DNS_RDATATYPE_FORMATSIZE];
4995         char classname[DNS_RDATACLASS_FORMATSIZE];
4996         const char *namep, *typep, *classp, *sep1, *sep2;
4997         dns_rdataset_t *rdataset;
4998
4999         if (!isc_log_wouldlog(ns_g_lctx, level))
5000                 return;
5001
5002         namep = typep = classp = sep1 = sep2 = "";
5003
5004         /*
5005          * Query errors can happen for various reasons.  In some cases we cannot
5006          * even assume the query contains a valid question section, so we should
5007          * expect exceptional cases.
5008          */
5009         if (client->query.origqname != NULL) {
5010                 dns_name_format(client->query.origqname, namebuf,
5011                                 sizeof(namebuf));
5012                 namep = namebuf;
5013                 sep1 = " for ";
5014
5015                 rdataset = ISC_LIST_HEAD(client->query.origqname->list);
5016                 if (rdataset != NULL) {
5017                         dns_rdataclass_format(rdataset->rdclass, classname,
5018                                               sizeof(classname));
5019                         classp = classname;
5020                         dns_rdatatype_format(rdataset->type, typename,
5021                                              sizeof(typename));
5022                         typep = typename;
5023                         sep2 = "/";
5024                 }
5025         }
5026
5027         ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, NS_LOGMODULE_QUERY,
5028                       level, "query failed (%s)%s%s%s%s%s%s at %s:%d",
5029                       isc_result_totext(result), sep1, namep, sep2,
5030                       classp, sep2, typep, __FILE__, line);
5031 }
5032
5033 void
5034 ns_query_start(ns_client_t *client) {
5035         isc_result_t result;
5036         dns_message_t *message = client->message;
5037         dns_rdataset_t *rdataset;
5038         ns_client_t *qclient;
5039         dns_rdatatype_t qtype;
5040         unsigned int saved_extflags = client->extflags;
5041         unsigned int saved_flags = client->message->flags;
5042         isc_boolean_t want_ad;
5043
5044         CTRACE("ns_query_start");
5045
5046         /*
5047          * Test only.
5048          */
5049         if (ns_g_clienttest && (client->attributes & NS_CLIENTATTR_TCP) == 0)
5050                 RUNTIME_CHECK(ns_client_replace(client) == ISC_R_SUCCESS);
5051
5052         /*
5053          * Ensure that appropriate cleanups occur.
5054          */
5055         client->next = query_next_callback;
5056
5057         /*
5058          * Behave as if we don't support DNSSEC if not enabled.
5059          */
5060         if (!client->view->enablednssec) {
5061                 message->flags &= ~DNS_MESSAGEFLAG_CD;
5062                 client->extflags &= ~DNS_MESSAGEEXTFLAG_DO;
5063                 if (client->opt != NULL)
5064                         client->opt->ttl &= ~DNS_MESSAGEEXTFLAG_DO;
5065         }
5066
5067         if ((message->flags & DNS_MESSAGEFLAG_RD) != 0)
5068                 client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
5069
5070         if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0)
5071                 client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
5072
5073         if (client->view->minimalresponses)
5074                 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
5075                                              NS_QUERYATTR_NOADDITIONAL);
5076
5077         if ((client->view->cachedb == NULL)
5078             || (!client->view->additionalfromcache)) {
5079                 /*
5080                  * We don't have a cache.  Turn off cache support and
5081                  * recursion.
5082                  */
5083                 client->query.attributes &=
5084                         ~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK);
5085         } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
5086                    (message->flags & DNS_MESSAGEFLAG_RD) == 0) {
5087                 /*
5088                  * If the client isn't allowed to recurse (due to
5089                  * "recursion no", the allow-recursion ACL, or the
5090                  * lack of a resolver in this view), or if it
5091                  * doesn't want recursion, turn recursion off.
5092                  */
5093                 client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
5094         }
5095
5096         /*
5097          * Get the question name.
5098          */
5099         result = dns_message_firstname(message, DNS_SECTION_QUESTION);
5100         if (result != ISC_R_SUCCESS) {
5101                 query_error(client, result, __LINE__);
5102                 return;
5103         }
5104         dns_message_currentname(message, DNS_SECTION_QUESTION,
5105                                 &client->query.qname);
5106         client->query.origqname = client->query.qname;
5107         result = dns_message_nextname(message, DNS_SECTION_QUESTION);
5108         if (result != ISC_R_NOMORE) {
5109                 if (result == ISC_R_SUCCESS) {
5110                         /*
5111                          * There's more than one QNAME in the question
5112                          * section.
5113                          */
5114                         query_error(client, DNS_R_FORMERR, __LINE__);
5115                 } else
5116                         query_error(client, result, __LINE__);
5117                 return;
5118         }
5119
5120         if (ns_g_server->log_queries)
5121                 log_query(client, saved_flags, saved_extflags);
5122
5123         /*
5124          * Check for multiple question queries, since edns1 is dead.
5125          */
5126         if (message->counts[DNS_SECTION_QUESTION] > 1) {
5127                 query_error(client, DNS_R_FORMERR, __LINE__);
5128                 return;
5129         }
5130
5131         /*
5132          * Check for meta-queries like IXFR and AXFR.
5133          */
5134         rdataset = ISC_LIST_HEAD(client->query.qname->list);
5135         INSIST(rdataset != NULL);
5136         qtype = rdataset->type;
5137         dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype);
5138         if (dns_rdatatype_ismeta(qtype)) {
5139                 switch (qtype) {
5140                 case dns_rdatatype_any:
5141                         break; /* Let query_find handle it. */
5142                 case dns_rdatatype_ixfr:
5143                 case dns_rdatatype_axfr:
5144                         ns_xfr_start(client, rdataset->type);
5145                         return;
5146                 case dns_rdatatype_maila:
5147                 case dns_rdatatype_mailb:
5148                         query_error(client, DNS_R_NOTIMP, __LINE__);
5149                         return;
5150                 case dns_rdatatype_tkey:
5151                         result = dns_tkey_processquery(client->message,
5152                                                 ns_g_server->tkeyctx,
5153                                                 client->view->dynamickeys);
5154                         if (result == ISC_R_SUCCESS)
5155                                 query_send(client);
5156                         else
5157                                 query_error(client, result, __LINE__);
5158                         return;
5159                 default: /* TSIG, etc. */
5160                         query_error(client, DNS_R_FORMERR, __LINE__);
5161                         return;
5162                 }
5163         }
5164
5165         /*
5166          * Turn on minimal response for DNSKEY queries.
5167          */
5168         if (qtype == dns_rdatatype_dnskey)
5169                 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
5170                                              NS_QUERYATTR_NOADDITIONAL);
5171
5172         /*
5173          * If the client has requested that DNSSEC checking be disabled,
5174          * allow lookups to return pending data and instruct the resolver
5175          * to return data before validation has completed.
5176          *
5177          * We don't need to set DNS_DBFIND_PENDINGOK when validation is
5178          * disabled as there will be no pending data.
5179          */
5180         if (message->flags & DNS_MESSAGEFLAG_CD ||
5181             qtype == dns_rdatatype_rrsig)
5182         {
5183                 client->query.dboptions |= DNS_DBFIND_PENDINGOK;
5184                 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
5185         } else if (!client->view->enablevalidation)
5186                 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
5187
5188         /*
5189          * Allow glue NS records to be added to the authority section
5190          * if the answer is secure.
5191          */
5192         if (message->flags & DNS_MESSAGEFLAG_CD)
5193                 client->query.attributes &= ~NS_QUERYATTR_SECURE;
5194
5195         /*
5196          * Set 'want_ad' if the client has set AD in the query.
5197          * This allows AD to be returned on queries without DO set.
5198          */
5199         if ((message->flags & DNS_MESSAGEFLAG_AD) != 0)
5200                 want_ad = ISC_TRUE;
5201         else
5202                 want_ad = ISC_FALSE;
5203
5204         /*
5205          * This is an ordinary query.
5206          */
5207         result = dns_message_reply(message, ISC_TRUE);
5208         if (result != ISC_R_SUCCESS) {
5209                 query_next(client, result);
5210                 return;
5211         }
5212
5213         /*
5214          * Assume authoritative response until it is known to be
5215          * otherwise.
5216          */
5217         message->flags |= DNS_MESSAGEFLAG_AA;
5218
5219         /*
5220          * Set AD.  We must clear it if we add non-validated data to a
5221          * response.
5222          */
5223         if (WANTDNSSEC(client) || want_ad)
5224                 message->flags |= DNS_MESSAGEFLAG_AD;
5225
5226         qclient = NULL;
5227         ns_client_attach(client, &qclient);
5228         (void)query_find(qclient, NULL, qtype);
5229 }