Home | History | Annotate | Line # | Download | only in ns
query.c revision 1.11
      1  1.10  christos /*	$NetBSD: query.c,v 1.11 2021/02/19 16:42:22 christos Exp $	*/
      2   1.1  christos 
      3   1.1  christos /*
      4   1.1  christos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5   1.1  christos  *
      6   1.1  christos  * This Source Code Form is subject to the terms of the Mozilla Public
      7   1.1  christos  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  1.11  christos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
      9   1.1  christos  *
     10   1.1  christos  * See the COPYRIGHT file distributed with this work for additional
     11   1.1  christos  * information regarding copyright ownership.
     12   1.1  christos  */
     13   1.1  christos 
     14   1.1  christos /*! \file */
     15   1.1  christos 
     16   1.3  christos #include <inttypes.h>
     17   1.3  christos #include <stdbool.h>
     18   1.1  christos #include <string.h>
     19   1.1  christos 
     20   1.1  christos #include <isc/hex.h>
     21   1.1  christos #include <isc/mem.h>
     22   1.9  christos #include <isc/once.h>
     23   1.1  christos #include <isc/print.h>
     24   1.1  christos #include <isc/random.h>
     25   1.1  christos #include <isc/rwlock.h>
     26   1.1  christos #include <isc/serial.h>
     27   1.1  christos #include <isc/stats.h>
     28   1.1  christos #include <isc/string.h>
     29   1.1  christos #include <isc/thread.h>
     30   1.1  christos #include <isc/util.h>
     31   1.1  christos 
     32   1.1  christos #include <dns/adb.h>
     33   1.1  christos #include <dns/badcache.h>
     34   1.1  christos #include <dns/byaddr.h>
     35   1.1  christos #include <dns/cache.h>
     36   1.1  christos #include <dns/db.h>
     37   1.1  christos #include <dns/dlz.h>
     38   1.1  christos #include <dns/dns64.h>
     39   1.1  christos #include <dns/dnsrps.h>
     40   1.1  christos #include <dns/dnssec.h>
     41   1.1  christos #include <dns/events.h>
     42   1.1  christos #include <dns/keytable.h>
     43   1.1  christos #include <dns/message.h>
     44   1.1  christos #include <dns/ncache.h>
     45   1.1  christos #include <dns/nsec.h>
     46   1.1  christos #include <dns/nsec3.h>
     47   1.1  christos #include <dns/order.h>
     48   1.1  christos #include <dns/rdata.h>
     49   1.1  christos #include <dns/rdataclass.h>
     50   1.1  christos #include <dns/rdatalist.h>
     51   1.1  christos #include <dns/rdataset.h>
     52   1.1  christos #include <dns/rdatasetiter.h>
     53   1.1  christos #include <dns/rdatastruct.h>
     54   1.1  christos #include <dns/rdatatype.h>
     55   1.1  christos #include <dns/resolver.h>
     56   1.1  christos #include <dns/result.h>
     57   1.1  christos #include <dns/stats.h>
     58   1.1  christos #include <dns/tkey.h>
     59   1.1  christos #include <dns/types.h>
     60   1.1  christos #include <dns/view.h>
     61   1.1  christos #include <dns/zone.h>
     62   1.1  christos #include <dns/zt.h>
     63   1.1  christos 
     64   1.1  christos #include <ns/client.h>
     65   1.9  christos #include <ns/hooks.h>
     66   1.1  christos #include <ns/interfacemgr.h>
     67   1.1  christos #include <ns/log.h>
     68   1.1  christos #include <ns/server.h>
     69   1.1  christos #include <ns/sortlist.h>
     70   1.1  christos #include <ns/stats.h>
     71   1.1  christos #include <ns/xfrout.h>
     72   1.1  christos 
     73   1.7  christos #include <ns/pfilter.h>
     74   1.7  christos 
     75   1.1  christos #if 0
     76   1.1  christos /*
     77   1.1  christos  * It has been recommended that DNS64 be changed to return excluded
     78   1.1  christos  * AAAA addresses if DNS64 synthesis does not occur.  This minimises
     79   1.1  christos  * the impact on the lookup results.  While most DNS AAAA lookups are
     80   1.1  christos  * done to send IP packets to a host, not all of them are and filtering
     81   1.1  christos  * excluded addresses has a negative impact on those uses.
     82   1.1  christos  */
     83   1.1  christos #define dns64_bis_return_excluded_addresses 1
     84   1.9  christos #endif /* if 0 */
     85   1.1  christos 
     86   1.1  christos /*%
     87   1.1  christos  * Maximum number of chained queries before we give up
     88   1.1  christos  * to prevent CNAME loops.
     89   1.1  christos  */
     90   1.1  christos #define MAX_RESTARTS 16
     91   1.1  christos 
     92  1.11  christos #define QUERY_ERROR(qctx, r)                  \
     93  1.11  christos 	do {                                  \
     94  1.11  christos 		(qctx)->result = r;           \
     95  1.11  christos 		(qctx)->want_restart = false; \
     96  1.11  christos 		(qctx)->line = __LINE__;      \
     97   1.9  christos 	} while (/*CONSTCOND*/0)
     98   1.1  christos 
     99   1.1  christos /*% Partial answer? */
    100   1.9  christos #define PARTIALANSWER(c) \
    101   1.9  christos 	(((c)->query.attributes & NS_QUERYATTR_PARTIALANSWER) != 0)
    102   1.1  christos /*% Use Cache? */
    103   1.9  christos #define USECACHE(c) (((c)->query.attributes & NS_QUERYATTR_CACHEOK) != 0)
    104   1.1  christos /*% Recursion OK? */
    105   1.9  christos #define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0)
    106   1.1  christos /*% Recursing? */
    107   1.9  christos #define RECURSING(c) (((c)->query.attributes & NS_QUERYATTR_RECURSING) != 0)
    108   1.1  christos /*% Want Recursion? */
    109   1.9  christos #define WANTRECURSION(c) \
    110   1.9  christos 	(((c)->query.attributes & NS_QUERYATTR_WANTRECURSION) != 0)
    111   1.1  christos /*% Is TCP? */
    112   1.9  christos #define TCP(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
    113   1.1  christos 
    114   1.1  christos /*% Want DNSSEC? */
    115   1.9  christos #define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
    116   1.1  christos /*% Want WANTAD? */
    117   1.9  christos #define WANTAD(c) (((c)->attributes & NS_CLIENTATTR_WANTAD) != 0)
    118   1.1  christos /*% Client presented a valid COOKIE. */
    119   1.9  christos #define HAVECOOKIE(c) (((c)->attributes & NS_CLIENTATTR_HAVECOOKIE) != 0)
    120   1.1  christos /*% Client presented a COOKIE. */
    121   1.9  christos #define WANTCOOKIE(c) (((c)->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0)
    122   1.1  christos /*% Client presented a CLIENT-SUBNET option. */
    123   1.9  christos #define HAVEECS(c) (((c)->attributes & NS_CLIENTATTR_HAVEECS) != 0)
    124   1.1  christos /*% No authority? */
    125   1.9  christos #define NOAUTHORITY(c) (((c)->query.attributes & NS_QUERYATTR_NOAUTHORITY) != 0)
    126   1.1  christos /*% No additional? */
    127   1.9  christos #define NOADDITIONAL(c) \
    128   1.9  christos 	(((c)->query.attributes & NS_QUERYATTR_NOADDITIONAL) != 0)
    129   1.1  christos /*% Secure? */
    130   1.9  christos #define SECURE(c) (((c)->query.attributes & NS_QUERYATTR_SECURE) != 0)
    131   1.1  christos /*% DNS64 A lookup? */
    132   1.9  christos #define DNS64(c) (((c)->query.attributes & NS_QUERYATTR_DNS64) != 0)
    133   1.1  christos 
    134   1.9  christos #define DNS64EXCLUDE(c) \
    135   1.9  christos 	(((c)->query.attributes & NS_QUERYATTR_DNS64EXCLUDE) != 0)
    136   1.1  christos 
    137   1.9  christos #define REDIRECT(c) (((c)->query.attributes & NS_QUERYATTR_REDIRECT) != 0)
    138   1.1  christos 
    139  1.11  christos /*% Was the query already answered due to stale-answer-client-timeout? */
    140  1.11  christos #define QUERY_ANSWERED(q) (((q)->attributes & NS_QUERYATTR_ANSWERED) != 0)
    141  1.11  christos 
    142  1.11  christos /*% Does the query only wants to check for stale RRset? */
    143  1.11  christos #define QUERY_STALEONLY(q) (((q)->dboptions & DNS_DBFIND_STALEONLY) != 0)
    144  1.11  christos 
    145   1.1  christos /*% Does the rdataset 'r' have an attached 'No QNAME Proof'? */
    146   1.9  christos #define NOQNAME(r) (((r)->attributes & DNS_RDATASETATTR_NOQNAME) != 0)
    147   1.1  christos 
    148   1.4  christos /*% Does the rdataset 'r' contain a stale answer? */
    149   1.9  christos #define STALE(r) (((r)->attributes & DNS_RDATASETATTR_STALE) != 0)
    150   1.1  christos 
    151  1.11  christos /*% Does the rdataset 'r' is stale and within stale-refresh-time? */
    152  1.11  christos #define STALE_WINDOW(r) (((r)->attributes & DNS_RDATASETATTR_STALE_WINDOW) != 0)
    153  1.11  christos 
    154   1.1  christos #ifdef WANT_QUERYTRACE
    155   1.1  christos static inline void
    156   1.1  christos client_trace(ns_client_t *client, int level, const char *message) {
    157   1.1  christos 	if (client != NULL && client->query.qname != NULL) {
    158   1.1  christos 		if (isc_log_wouldlog(ns_lctx, level)) {
    159   1.1  christos 			char qbuf[DNS_NAME_FORMATSIZE];
    160   1.1  christos 			char tbuf[DNS_RDATATYPE_FORMATSIZE];
    161   1.9  christos 			dns_name_format(client->query.qname, qbuf,
    162   1.9  christos 					sizeof(qbuf));
    163   1.9  christos 			dns_rdatatype_format(client->query.qtype, tbuf,
    164   1.9  christos 					     sizeof(tbuf));
    165   1.9  christos 			isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT,
    166   1.1  christos 				      NS_LOGMODULE_QUERY, level,
    167   1.1  christos 				      "query client=%p thread=0x%lx "
    168   1.1  christos 				      "(%s/%s): %s",
    169   1.9  christos 				      client, (unsigned long)isc_thread_self(),
    170   1.1  christos 				      qbuf, tbuf, message);
    171   1.1  christos 		}
    172   1.9  christos 	} else {
    173   1.9  christos 		isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT,
    174   1.1  christos 			      NS_LOGMODULE_QUERY, level,
    175   1.1  christos 			      "query client=%p thread=0x%lx "
    176   1.1  christos 			      "(<unknown-query>): %s",
    177   1.9  christos 			      client, (unsigned long)isc_thread_self(),
    178   1.1  christos 			      message);
    179   1.1  christos 	}
    180   1.1  christos }
    181   1.9  christos #define CTRACE(l, m)  client_trace(client, l, m)
    182   1.9  christos #define CCTRACE(l, m) client_trace(qctx->client, l, m)
    183   1.9  christos #else /* ifdef WANT_QUERYTRACE */
    184   1.9  christos #define CTRACE(l, m)  ((void)m)
    185   1.9  christos #define CCTRACE(l, m) ((void)m)
    186   1.1  christos #endif /* WANT_QUERYTRACE */
    187   1.1  christos 
    188  1.11  christos #define DNS_GETDB_NOEXACT    0x01U
    189  1.11  christos #define DNS_GETDB_NOLOG	     0x02U
    190  1.11  christos #define DNS_GETDB_PARTIAL    0x04U
    191  1.11  christos #define DNS_GETDB_IGNOREACL  0x08U
    192  1.11  christos #define DNS_GETDB_STALEFIRST 0X0CU
    193   1.1  christos 
    194   1.9  christos #define PENDINGOK(x) (((x)&DNS_DBFIND_PENDINGOK) != 0)
    195   1.1  christos 
    196   1.1  christos #define SFCACHE_CDFLAG 0x1
    197   1.1  christos 
    198   1.1  christos /*
    199   1.1  christos  * These have the same semantics as:
    200   1.1  christos  *
    201   1.1  christos  * 	foo_attach(b, a);
    202   1.1  christos  *	foo_detach(&a);
    203   1.1  christos  *
    204   1.1  christos  * without the locking and magic testing.
    205   1.1  christos  *
    206   1.1  christos  * We use SAVE and RESTORE as that shows the operation being performed.
    207   1.1  christos  */
    208   1.9  christos #define SAVE(a, b)                 \
    209   1.9  christos 	do {                       \
    210   1.9  christos 		INSIST(a == NULL); \
    211   1.9  christos 		a = b;             \
    212   1.9  christos 		b = NULL;          \
    213   1.9  christos 	} while (/*CONSTCOND*/0)
    214   1.1  christos #define RESTORE(a, b) SAVE(a, b)
    215   1.1  christos 
    216   1.3  christos static bool
    217   1.1  christos validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
    218   1.1  christos 	 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
    219   1.1  christos 
    220   1.1  christos static void
    221   1.1  christos query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
    222   1.1  christos 		       dns_dbversion_t *version, ns_client_t *client,
    223   1.1  christos 		       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
    224   1.9  christos 		       dns_name_t *fname, bool exact, dns_name_t *found);
    225   1.1  christos 
    226   1.1  christos static inline void
    227   1.1  christos log_queryerror(ns_client_t *client, isc_result_t result, int line, int level);
    228   1.1  christos 
    229   1.1  christos static void
    230   1.1  christos rpz_st_clear(ns_client_t *client);
    231   1.1  christos 
    232   1.3  christos static bool
    233   1.1  christos rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult,
    234   1.1  christos 	      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
    235   1.1  christos 
    236   1.1  christos static void
    237   1.1  christos log_noexistnodata(void *val, int level, const char *fmt, ...)
    238   1.1  christos 	ISC_FORMAT_PRINTF(3, 4);
    239   1.1  christos 
    240   1.3  christos /*
    241   1.3  christos  * Return the hooktable in use with 'qctx', or if there isn't one
    242   1.3  christos  * set, return the default hooktable.
    243   1.3  christos  */
    244   1.3  christos static inline ns_hooktable_t *
    245   1.3  christos get_hooktab(query_ctx_t *qctx) {
    246   1.9  christos 	if (qctx == NULL || qctx->view == NULL || qctx->view->hooktable == NULL)
    247   1.3  christos 	{
    248   1.3  christos 		return (ns__hook_table);
    249   1.3  christos 	}
    250   1.1  christos 
    251   1.3  christos 	return (qctx->view->hooktable);
    252   1.3  christos }
    253   1.1  christos 
    254   1.3  christos /*
    255   1.3  christos  * Call the specified hook function in every configured module that implements
    256   1.3  christos  * that function. If any hook function returns NS_HOOK_RETURN, we
    257   1.3  christos  * set 'result' and terminate processing by jumping to the 'cleanup' tag.
    258   1.3  christos  *
    259   1.3  christos  * (Note that a hook function may set the 'result' to ISC_R_SUCCESS but
    260   1.3  christos  * still terminate processing within the calling function. That's why this
    261   1.3  christos  * is a macro instead of an inline function; it needs to be able to use
    262   1.3  christos  * 'goto cleanup' regardless of the return value.)
    263   1.3  christos  */
    264   1.9  christos #define CALL_HOOK(_id, _qctx)                                       \
    265   1.9  christos 	do {                                                        \
    266   1.9  christos 		isc_result_t _res;                                  \
    267   1.9  christos 		ns_hooktable_t *_tab = get_hooktab(_qctx);          \
    268   1.9  christos 		ns_hook_t *_hook;                                   \
    269   1.9  christos 		_hook = ISC_LIST_HEAD((*_tab)[_id]);                \
    270   1.9  christos 		while (_hook != NULL) {                             \
    271   1.9  christos 			ns_hook_action_t _func = _hook->action;     \
    272   1.9  christos 			void *_data = _hook->action_data;           \
    273   1.9  christos 			INSIST(_func != NULL);                      \
    274   1.9  christos 			switch (_func(_qctx, _data, &_res)) {       \
    275   1.9  christos 			case NS_HOOK_CONTINUE:                      \
    276   1.9  christos 				_hook = ISC_LIST_NEXT(_hook, link); \
    277   1.9  christos 				break;                              \
    278   1.9  christos 			case NS_HOOK_RETURN:                        \
    279   1.9  christos 				result = _res;                      \
    280   1.9  christos 				goto cleanup;                       \
    281   1.9  christos 			default:                                    \
    282   1.9  christos 				INSIST(0);                          \
    283   1.9  christos 			}                                           \
    284   1.9  christos 		}                                                   \
    285   1.3  christos 	} while (false)
    286   1.1  christos 
    287   1.3  christos /*
    288   1.3  christos  * Call the specified hook function in every configured module that
    289   1.3  christos  * implements that function. All modules are called; hook function return
    290   1.3  christos  * codes are ignored. This is intended for use with initialization and
    291   1.3  christos  * destruction calls which *must* run in every configured module.
    292   1.3  christos  *
    293   1.3  christos  * (This could be implemented as an inline void function, but is left as a
    294   1.3  christos  * macro for symmetry with CALL_HOOK above.)
    295   1.3  christos  */
    296   1.9  christos #define CALL_HOOK_NORETURN(_id, _qctx)                          \
    297   1.9  christos 	do {                                                    \
    298   1.9  christos 		isc_result_t _res;                              \
    299   1.9  christos 		ns_hooktable_t *_tab = get_hooktab(_qctx);      \
    300   1.9  christos 		ns_hook_t *_hook;                               \
    301   1.9  christos 		_hook = ISC_LIST_HEAD((*_tab)[_id]);            \
    302   1.9  christos 		while (_hook != NULL) {                         \
    303   1.9  christos 			ns_hook_action_t _func = _hook->action; \
    304   1.9  christos 			void *_data = _hook->action_data;       \
    305   1.9  christos 			INSIST(_func != NULL);                  \
    306   1.9  christos 			_func(_qctx, _data, &_res);             \
    307   1.9  christos 			_hook = ISC_LIST_NEXT(_hook, link);     \
    308   1.9  christos 		}                                               \
    309   1.3  christos 	} while (false)
    310   1.1  christos 
    311   1.1  christos /*
    312   1.1  christos  * The functions defined below implement the query logic that previously lived
    313   1.1  christos  * in the single very complex function query_find().  The query_ctx_t structure
    314   1.1  christos  * defined in <ns/query.h> maintains state from function to function.  The call
    315   1.1  christos  * flow for the general query processing algorithm is described below:
    316   1.1  christos  *
    317   1.1  christos  * 1. Set up query context and other resources for a client
    318   1.1  christos  *    query (query_setup())
    319   1.1  christos  *
    320   1.1  christos  * 2. Start the search (ns__query_start())
    321   1.1  christos  *
    322   1.1  christos  * 3. Identify authoritative data sources which may have an answer;
    323   1.1  christos  *    search them (query_lookup()). If an answer is found, go to 7.
    324   1.1  christos  *
    325   1.1  christos  * 4. If recursion or cache access are allowed, search the cache
    326   1.1  christos  *    (query_lookup() again, using the cache database) to find a better
    327   1.1  christos  *    answer. If an answer is found, go to 7.
    328   1.1  christos  *
    329   1.3  christos  * 5. If recursion is allowed, begin recursion (ns_query_recurse()).
    330   1.1  christos  *    Go to 15 to clean up this phase of the query. When recursion
    331   1.1  christos  *    is complete, processing will resume at 6.
    332   1.1  christos  *
    333   1.1  christos  * 6. Resume from recursion; set up query context for resumed processing.
    334   1.1  christos  *
    335   1.1  christos  * 7. Determine what sort of answer we've found (query_gotanswer())
    336   1.1  christos  *    and call other functions accordingly:
    337   1.1  christos  *      - not found (auth or cache), go to 8
    338   1.1  christos  *      - delegation, go to 9
    339   1.1  christos  *      - no such domain (auth), go to 10
    340   1.1  christos  *      - empty answer (auth), go to 11
    341   1.1  christos  *      - negative response (cache), go to 12
    342   1.1  christos  *      - answer found, go to 13
    343   1.1  christos  *
    344   1.1  christos  * 8. The answer was not found in the database (query_notfound().
    345   1.1  christos  *    Set up a referral and go to 9.
    346   1.1  christos  *
    347   1.3  christos  * 9. Handle a delegation response (query_delegation()). If we need
    348   1.3  christos  *    to and are allowed to recurse (query_delegation_recurse()), go to 5,
    349   1.3  christos  *    otherwise go to 15 to clean up and return the delegation to the client.
    350   1.1  christos  *
    351   1.1  christos  * 10. No such domain (query_nxdomain()). Attempt redirection; if
    352   1.1  christos  *     unsuccessful, add authority section records (query_addsoa(),
    353   1.1  christos  *     query_addauth()), then go to 15 to return NXDOMAIN to client.
    354   1.1  christos  *
    355   1.1  christos  * 11. Empty answer (query_nodata()). Add authority section records
    356   1.1  christos  *     (query_addsoa(), query_addauth()) and signatures if authoritative
    357   1.1  christos  *     (query_sign_nodata()) then go to 15 and return
    358   1.1  christos  *     NOERROR/ANCOUNT=0 to client.
    359   1.1  christos  *
    360   1.1  christos  * 12. No such domain or empty answer returned from cache (query_ncache()).
    361   1.1  christos  *     Set response code appropriately, go to 11.
    362   1.1  christos  *
    363   1.1  christos  * 13. Prepare a response (query_prepresponse()) and then fill it
    364   1.1  christos  *     appropriately (query_respond(), or for type ANY,
    365   1.1  christos  *     query_respond_any()).
    366   1.1  christos  *
    367   1.1  christos  * 14. If a restart is needed due to CNAME/DNAME chaining, go to 2.
    368   1.1  christos  *
    369   1.1  christos  * 15. Clean up resources. If recursing, stop and wait for the event
    370   1.1  christos  *     handler to be called back (step 6).  If an answer is ready,
    371   1.1  christos  *     return it to the client.
    372   1.1  christos  *
    373   1.1  christos  * (XXX: This description omits several special cases including
    374   1.3  christos  * DNS64, RPZ, RRL, and the SERVFAIL cache. It also doesn't discuss
    375   1.3  christos  * plugins.)
    376   1.1  christos  */
    377   1.1  christos 
    378   1.1  christos static void
    379   1.1  christos query_trace(query_ctx_t *qctx);
    380   1.1  christos 
    381   1.1  christos static void
    382  1.11  christos qctx_init(ns_client_t *client, dns_fetchevent_t **eventp, dns_rdatatype_t qtype,
    383   1.9  christos 	  query_ctx_t *qctx);
    384   1.1  christos 
    385   1.1  christos static isc_result_t
    386   1.1  christos query_setup(ns_client_t *client, dns_rdatatype_t qtype);
    387   1.1  christos 
    388   1.1  christos static isc_result_t
    389   1.1  christos query_lookup(query_ctx_t *qctx);
    390   1.1  christos 
    391   1.1  christos static void
    392   1.1  christos fetch_callback(isc_task_t *task, isc_event_t *event);
    393   1.1  christos 
    394   1.1  christos static void
    395   1.1  christos recparam_update(ns_query_recparam_t *param, dns_rdatatype_t qtype,
    396   1.1  christos 		const dns_name_t *qname, const dns_name_t *qdomain);
    397   1.1  christos 
    398   1.1  christos static isc_result_t
    399   1.1  christos query_resume(query_ctx_t *qctx);
    400   1.1  christos 
    401   1.1  christos static isc_result_t
    402   1.1  christos query_checkrrl(query_ctx_t *qctx, isc_result_t result);
    403   1.1  christos 
    404   1.1  christos static isc_result_t
    405   1.1  christos query_checkrpz(query_ctx_t *qctx, isc_result_t result);
    406   1.1  christos 
    407   1.1  christos static isc_result_t
    408   1.1  christos query_rpzcname(query_ctx_t *qctx, dns_name_t *cname);
    409   1.1  christos 
    410   1.1  christos static isc_result_t
    411   1.1  christos query_gotanswer(query_ctx_t *qctx, isc_result_t result);
    412   1.1  christos 
    413   1.1  christos static void
    414   1.1  christos query_addnoqnameproof(query_ctx_t *qctx);
    415   1.1  christos 
    416   1.1  christos static isc_result_t
    417   1.1  christos query_respond_any(query_ctx_t *qctx);
    418   1.1  christos 
    419   1.1  christos static isc_result_t
    420   1.1  christos query_respond(query_ctx_t *qctx);
    421   1.1  christos 
    422   1.1  christos static isc_result_t
    423   1.1  christos query_dns64(query_ctx_t *qctx);
    424   1.1  christos 
    425   1.1  christos static void
    426   1.1  christos query_filter64(query_ctx_t *qctx);
    427   1.1  christos 
    428   1.1  christos static isc_result_t
    429   1.1  christos query_notfound(query_ctx_t *qctx);
    430   1.1  christos 
    431   1.1  christos static isc_result_t
    432   1.1  christos query_zone_delegation(query_ctx_t *qctx);
    433   1.1  christos 
    434   1.1  christos static isc_result_t
    435   1.1  christos query_delegation(query_ctx_t *qctx);
    436   1.1  christos 
    437   1.3  christos static isc_result_t
    438   1.3  christos query_delegation_recurse(query_ctx_t *qctx);
    439   1.3  christos 
    440   1.1  christos static void
    441   1.1  christos query_addds(query_ctx_t *qctx);
    442   1.1  christos 
    443   1.1  christos static isc_result_t
    444   1.1  christos query_nodata(query_ctx_t *qctx, isc_result_t result);
    445   1.1  christos 
    446   1.1  christos static isc_result_t
    447   1.1  christos query_sign_nodata(query_ctx_t *qctx);
    448   1.1  christos 
    449   1.1  christos static void
    450   1.1  christos query_addnxrrsetnsec(query_ctx_t *qctx);
    451   1.1  christos 
    452   1.1  christos static isc_result_t
    453   1.3  christos query_nxdomain(query_ctx_t *qctx, bool empty_wild);
    454   1.1  christos 
    455   1.1  christos static isc_result_t
    456   1.1  christos query_redirect(query_ctx_t *qctx);
    457   1.1  christos 
    458   1.1  christos static isc_result_t
    459   1.1  christos query_ncache(query_ctx_t *qctx, isc_result_t result);
    460   1.1  christos 
    461   1.1  christos static isc_result_t
    462   1.1  christos query_coveringnsec(query_ctx_t *qctx);
    463   1.1  christos 
    464   1.1  christos static isc_result_t
    465   1.3  christos query_zerottl_refetch(query_ctx_t *qctx);
    466   1.3  christos 
    467   1.3  christos static isc_result_t
    468   1.1  christos query_cname(query_ctx_t *qctx);
    469   1.1  christos 
    470   1.1  christos static isc_result_t
    471   1.1  christos query_dname(query_ctx_t *qctx);
    472   1.1  christos 
    473   1.1  christos static isc_result_t
    474   1.1  christos query_addcname(query_ctx_t *qctx, dns_trust_t trust, dns_ttl_t ttl);
    475   1.1  christos 
    476   1.1  christos static isc_result_t
    477   1.1  christos query_prepresponse(query_ctx_t *qctx);
    478   1.1  christos 
    479   1.1  christos static isc_result_t
    480   1.1  christos query_addsoa(query_ctx_t *qctx, unsigned int override_ttl,
    481   1.1  christos 	     dns_section_t section);
    482   1.1  christos 
    483   1.1  christos static isc_result_t
    484   1.1  christos query_addns(query_ctx_t *qctx);
    485   1.1  christos 
    486   1.1  christos static void
    487   1.1  christos query_addbestns(query_ctx_t *qctx);
    488   1.1  christos 
    489   1.1  christos static void
    490   1.3  christos query_addwildcardproof(query_ctx_t *qctx, bool ispositive, bool nodata);
    491   1.1  christos 
    492   1.1  christos static void
    493   1.1  christos query_addauth(query_ctx_t *qctx);
    494   1.1  christos 
    495   1.3  christos /*
    496   1.1  christos  * Increment query statistics counters.
    497   1.1  christos  */
    498   1.1  christos static inline void
    499   1.1  christos inc_stats(ns_client_t *client, isc_statscounter_t counter) {
    500   1.1  christos 	dns_zone_t *zone = client->query.authzone;
    501   1.1  christos 	dns_rdatatype_t qtype;
    502   1.1  christos 	dns_rdataset_t *rdataset;
    503   1.1  christos 	isc_stats_t *zonestats;
    504   1.1  christos 	dns_stats_t *querystats = NULL;
    505   1.1  christos 
    506   1.1  christos 	ns_stats_increment(client->sctx->nsstats, counter);
    507   1.1  christos 
    508   1.9  christos 	if (zone == NULL) {
    509   1.1  christos 		return;
    510   1.9  christos 	}
    511   1.1  christos 
    512   1.1  christos 	/* Do regular response type stats */
    513   1.1  christos 	zonestats = dns_zone_getrequeststats(zone);
    514   1.1  christos 
    515   1.9  christos 	if (zonestats != NULL) {
    516   1.1  christos 		isc_stats_increment(zonestats, counter);
    517   1.9  christos 	}
    518   1.1  christos 
    519   1.1  christos 	/* Do query type statistics
    520   1.1  christos 	 *
    521   1.1  christos 	 * We only increment per-type if we're using the authoritative
    522   1.1  christos 	 * answer counter, preventing double-counting.
    523   1.1  christos 	 */
    524   1.1  christos 	if (counter == ns_statscounter_authans) {
    525   1.1  christos 		querystats = dns_zone_getrcvquerystats(zone);
    526   1.1  christos 		if (querystats != NULL) {
    527   1.1  christos 			rdataset = ISC_LIST_HEAD(client->query.qname->list);
    528   1.1  christos 			if (rdataset != NULL) {
    529   1.1  christos 				qtype = rdataset->type;
    530   1.1  christos 				dns_rdatatypestats_increment(querystats, qtype);
    531   1.1  christos 			}
    532   1.1  christos 		}
    533   1.1  christos 	}
    534   1.1  christos }
    535   1.1  christos 
    536   1.1  christos static void
    537   1.1  christos query_send(ns_client_t *client) {
    538   1.1  christos 	isc_statscounter_t counter;
    539   1.1  christos 
    540   1.9  christos 	if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0) {
    541   1.1  christos 		inc_stats(client, ns_statscounter_nonauthans);
    542   1.9  christos 	} else {
    543   1.1  christos 		inc_stats(client, ns_statscounter_authans);
    544   1.9  christos 	}
    545   1.1  christos 
    546   1.1  christos 	if (client->message->rcode == dns_rcode_noerror) {
    547   1.1  christos 		dns_section_t answer = DNS_SECTION_ANSWER;
    548   1.1  christos 		if (ISC_LIST_EMPTY(client->message->sections[answer])) {
    549   1.9  christos 			if (client->query.isreferral) {
    550   1.1  christos 				counter = ns_statscounter_referral;
    551   1.9  christos 			} else {
    552   1.1  christos 				counter = ns_statscounter_nxrrset;
    553   1.9  christos 			}
    554   1.9  christos 		} else {
    555   1.1  christos 			counter = ns_statscounter_success;
    556   1.9  christos 		}
    557   1.9  christos 	} else if (client->message->rcode == dns_rcode_nxdomain) {
    558   1.1  christos 		counter = ns_statscounter_nxdomain;
    559   1.9  christos 	} else if (client->message->rcode == dns_rcode_badcookie) {
    560   1.1  christos 		counter = ns_statscounter_badcookie;
    561   1.9  christos 	} else { /* We end up here in case of YXDOMAIN, and maybe others */
    562   1.1  christos 		counter = ns_statscounter_failure;
    563   1.9  christos 	}
    564   1.1  christos 
    565   1.1  christos 	inc_stats(client, counter);
    566   1.1  christos 	ns_client_send(client);
    567  1.11  christos 
    568  1.11  christos 	if (!QUERY_STALEONLY(&client->query)) {
    569  1.11  christos 		isc_nmhandle_detach(&client->reqhandle);
    570  1.11  christos 	}
    571   1.1  christos }
    572   1.1  christos 
    573   1.1  christos static void
    574   1.1  christos query_error(ns_client_t *client, isc_result_t result, int line) {
    575   1.1  christos 	int loglevel = ISC_LOG_DEBUG(3);
    576   1.1  christos 
    577   1.3  christos 	switch (dns_result_torcode(result)) {
    578   1.3  christos 	case dns_rcode_servfail:
    579   1.1  christos 		loglevel = ISC_LOG_DEBUG(1);
    580   1.1  christos 		inc_stats(client, ns_statscounter_servfail);
    581   1.1  christos 		break;
    582   1.3  christos 	case dns_rcode_formerr:
    583   1.1  christos 		inc_stats(client, ns_statscounter_formerr);
    584   1.1  christos 		break;
    585   1.1  christos 	default:
    586   1.1  christos 		inc_stats(client, ns_statscounter_failure);
    587   1.1  christos 		break;
    588   1.1  christos 	}
    589   1.1  christos 
    590   1.9  christos 	if ((client->sctx->options & NS_SERVER_LOGQUERIES) != 0) {
    591   1.1  christos 		loglevel = ISC_LOG_INFO;
    592   1.9  christos 	}
    593   1.1  christos 
    594   1.1  christos 	log_queryerror(client, result, line, loglevel);
    595   1.1  christos 
    596   1.1  christos 	ns_client_error(client, result);
    597  1.11  christos 
    598  1.11  christos 	if (!QUERY_STALEONLY(&client->query)) {
    599  1.11  christos 		isc_nmhandle_detach(&client->reqhandle);
    600  1.11  christos 	}
    601   1.1  christos }
    602   1.1  christos 
    603   1.1  christos static void
    604   1.1  christos query_next(ns_client_t *client, isc_result_t result) {
    605   1.9  christos 	if (result == DNS_R_DUPLICATE) {
    606   1.1  christos 		inc_stats(client, ns_statscounter_duplicate);
    607   1.9  christos 	} else if (result == DNS_R_DROP) {
    608   1.1  christos 		inc_stats(client, ns_statscounter_dropped);
    609   1.9  christos 	} else {
    610   1.1  christos 		inc_stats(client, ns_statscounter_failure);
    611   1.9  christos 	}
    612   1.9  christos 	ns_client_drop(client, result);
    613  1.11  christos 
    614  1.11  christos 	if (!QUERY_STALEONLY(&client->query)) {
    615  1.11  christos 		isc_nmhandle_detach(&client->reqhandle);
    616  1.11  christos 	}
    617   1.1  christos }
    618   1.1  christos 
    619   1.1  christos static inline void
    620   1.3  christos query_freefreeversions(ns_client_t *client, bool everything) {
    621   1.1  christos 	ns_dbversion_t *dbversion, *dbversion_next;
    622   1.1  christos 	unsigned int i;
    623   1.1  christos 
    624   1.1  christos 	for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
    625   1.9  christos 	     dbversion != NULL; dbversion = dbversion_next, i++)
    626   1.1  christos 	{
    627   1.1  christos 		dbversion_next = ISC_LIST_NEXT(dbversion, link);
    628   1.1  christos 		/*
    629   1.1  christos 		 * If we're not freeing everything, we keep the first three
    630   1.1  christos 		 * dbversions structures around.
    631   1.1  christos 		 */
    632   1.1  christos 		if (i > 3 || everything) {
    633   1.1  christos 			ISC_LIST_UNLINK(client->query.freeversions, dbversion,
    634   1.1  christos 					link);
    635   1.1  christos 			isc_mem_put(client->mctx, dbversion,
    636   1.1  christos 				    sizeof(*dbversion));
    637   1.1  christos 		}
    638   1.1  christos 	}
    639   1.1  christos }
    640   1.1  christos 
    641   1.1  christos void
    642   1.1  christos ns_query_cancel(ns_client_t *client) {
    643   1.1  christos 	REQUIRE(NS_CLIENT_VALID(client));
    644   1.1  christos 
    645   1.1  christos 	LOCK(&client->query.fetchlock);
    646   1.1  christos 	if (client->query.fetch != NULL) {
    647   1.1  christos 		dns_resolver_cancelfetch(client->query.fetch);
    648   1.1  christos 
    649   1.1  christos 		client->query.fetch = NULL;
    650   1.1  christos 	}
    651   1.1  christos 	UNLOCK(&client->query.fetchlock);
    652   1.1  christos }
    653   1.1  christos 
    654   1.1  christos static inline void
    655   1.3  christos query_reset(ns_client_t *client, bool everything) {
    656   1.1  christos 	isc_buffer_t *dbuf, *dbuf_next;
    657   1.1  christos 	ns_dbversion_t *dbversion, *dbversion_next;
    658   1.1  christos 
    659   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_reset");
    660   1.1  christos 
    661   1.1  christos 	/*%
    662   1.1  christos 	 * Reset the query state of a client to its default state.
    663   1.1  christos 	 */
    664   1.1  christos 
    665   1.1  christos 	/*
    666   1.1  christos 	 * Cancel the fetch if it's running.
    667   1.1  christos 	 */
    668   1.1  christos 	ns_query_cancel(client);
    669   1.1  christos 
    670   1.1  christos 	/*
    671   1.1  christos 	 * Cleanup any active versions.
    672   1.1  christos 	 */
    673   1.1  christos 	for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
    674   1.9  christos 	     dbversion != NULL; dbversion = dbversion_next)
    675   1.9  christos 	{
    676   1.1  christos 		dbversion_next = ISC_LIST_NEXT(dbversion, link);
    677   1.9  christos 		dns_db_closeversion(dbversion->db, &dbversion->version, false);
    678   1.1  christos 		dns_db_detach(&dbversion->db);
    679   1.9  christos 		ISC_LIST_INITANDAPPEND(client->query.freeversions, dbversion,
    680   1.9  christos 				       link);
    681   1.1  christos 	}
    682   1.1  christos 	ISC_LIST_INIT(client->query.activeversions);
    683   1.1  christos 
    684   1.9  christos 	if (client->query.authdb != NULL) {
    685   1.1  christos 		dns_db_detach(&client->query.authdb);
    686   1.9  christos 	}
    687   1.9  christos 	if (client->query.authzone != NULL) {
    688   1.1  christos 		dns_zone_detach(&client->query.authzone);
    689   1.9  christos 	}
    690   1.1  christos 
    691   1.9  christos 	if (client->query.dns64_aaaa != NULL) {
    692   1.3  christos 		ns_client_putrdataset(client, &client->query.dns64_aaaa);
    693   1.9  christos 	}
    694   1.9  christos 	if (client->query.dns64_sigaaaa != NULL) {
    695   1.3  christos 		ns_client_putrdataset(client, &client->query.dns64_sigaaaa);
    696   1.9  christos 	}
    697   1.1  christos 	if (client->query.dns64_aaaaok != NULL) {
    698   1.1  christos 		isc_mem_put(client->mctx, client->query.dns64_aaaaok,
    699   1.9  christos 			    client->query.dns64_aaaaoklen * sizeof(bool));
    700   1.9  christos 		client->query.dns64_aaaaok = NULL;
    701   1.9  christos 		client->query.dns64_aaaaoklen = 0;
    702   1.1  christos 	}
    703   1.1  christos 
    704   1.3  christos 	ns_client_putrdataset(client, &client->query.redirect.rdataset);
    705   1.3  christos 	ns_client_putrdataset(client, &client->query.redirect.sigrdataset);
    706   1.1  christos 	if (client->query.redirect.db != NULL) {
    707   1.9  christos 		if (client->query.redirect.node != NULL) {
    708   1.1  christos 			dns_db_detachnode(client->query.redirect.db,
    709   1.1  christos 					  &client->query.redirect.node);
    710   1.9  christos 		}
    711   1.1  christos 		dns_db_detach(&client->query.redirect.db);
    712   1.1  christos 	}
    713   1.9  christos 	if (client->query.redirect.zone != NULL) {
    714   1.1  christos 		dns_zone_detach(&client->query.redirect.zone);
    715   1.9  christos 	}
    716   1.1  christos 
    717   1.1  christos 	query_freefreeversions(client, everything);
    718   1.1  christos 
    719   1.9  christos 	for (dbuf = ISC_LIST_HEAD(client->query.namebufs); dbuf != NULL;
    720   1.9  christos 	     dbuf = dbuf_next)
    721   1.9  christos 	{
    722   1.1  christos 		dbuf_next = ISC_LIST_NEXT(dbuf, link);
    723   1.1  christos 		if (dbuf_next != NULL || everything) {
    724   1.1  christos 			ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
    725   1.1  christos 			isc_buffer_free(&dbuf);
    726   1.1  christos 		}
    727   1.1  christos 	}
    728   1.1  christos 
    729   1.1  christos 	if (client->query.restarts > 0) {
    730   1.1  christos 		/*
    731   1.1  christos 		 * client->query.qname was dynamically allocated.
    732   1.1  christos 		 */
    733   1.9  christos 		dns_message_puttempname(client->message, &client->query.qname);
    734   1.1  christos 	}
    735   1.1  christos 	client->query.qname = NULL;
    736   1.1  christos 	client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
    737   1.9  christos 				    NS_QUERYATTR_CACHEOK | NS_QUERYATTR_SECURE);
    738   1.1  christos 	client->query.restarts = 0;
    739   1.3  christos 	client->query.timerset = false;
    740   1.1  christos 	if (client->query.rpz_st != NULL) {
    741   1.1  christos 		rpz_st_clear(client);
    742   1.1  christos 		if (everything) {
    743   1.1  christos 			INSIST(client->query.rpz_st->rpsdb == NULL);
    744   1.1  christos 			isc_mem_put(client->mctx, client->query.rpz_st,
    745   1.1  christos 				    sizeof(*client->query.rpz_st));
    746   1.1  christos 			client->query.rpz_st = NULL;
    747   1.1  christos 		}
    748   1.1  christos 	}
    749   1.1  christos 	client->query.origqname = NULL;
    750   1.1  christos 	client->query.dboptions = 0;
    751   1.1  christos 	client->query.fetchoptions = 0;
    752   1.1  christos 	client->query.gluedb = NULL;
    753   1.3  christos 	client->query.authdbset = false;
    754   1.3  christos 	client->query.isreferral = false;
    755   1.1  christos 	client->query.dns64_options = 0;
    756   1.3  christos 	client->query.dns64_ttl = UINT32_MAX;
    757   1.3  christos 	recparam_update(&client->query.recparam, 0, NULL, NULL);
    758   1.1  christos 	client->query.root_key_sentinel_keyid = 0;
    759   1.3  christos 	client->query.root_key_sentinel_is_ta = false;
    760   1.3  christos 	client->query.root_key_sentinel_not_ta = false;
    761   1.1  christos }
    762   1.1  christos 
    763   1.1  christos static void
    764   1.9  christos query_cleanup(ns_client_t *client) {
    765   1.3  christos 	query_reset(client, false);
    766   1.1  christos }
    767   1.1  christos 
    768   1.1  christos void
    769   1.1  christos ns_query_free(ns_client_t *client) {
    770   1.1  christos 	REQUIRE(NS_CLIENT_VALID(client));
    771   1.1  christos 
    772   1.3  christos 	query_reset(client, true);
    773   1.1  christos }
    774   1.1  christos 
    775   1.1  christos isc_result_t
    776   1.1  christos ns_query_init(ns_client_t *client) {
    777   1.1  christos 	isc_result_t result;
    778   1.1  christos 
    779   1.1  christos 	REQUIRE(NS_CLIENT_VALID(client));
    780   1.1  christos 
    781   1.1  christos 	ISC_LIST_INIT(client->query.namebufs);
    782   1.1  christos 	ISC_LIST_INIT(client->query.activeversions);
    783   1.1  christos 	ISC_LIST_INIT(client->query.freeversions);
    784   1.1  christos 	client->query.restarts = 0;
    785   1.3  christos 	client->query.timerset = false;
    786   1.1  christos 	client->query.rpz_st = NULL;
    787   1.1  christos 	client->query.qname = NULL;
    788   1.1  christos 	/*
    789   1.1  christos 	 * This mutex is destroyed when the client is destroyed in
    790   1.1  christos 	 * exit_check().
    791   1.1  christos 	 */
    792   1.3  christos 	isc_mutex_init(&client->query.fetchlock);
    793   1.3  christos 
    794   1.1  christos 	client->query.fetch = NULL;
    795   1.1  christos 	client->query.prefetch = NULL;
    796   1.1  christos 	client->query.authdb = NULL;
    797   1.1  christos 	client->query.authzone = NULL;
    798   1.3  christos 	client->query.authdbset = false;
    799   1.3  christos 	client->query.isreferral = false;
    800   1.1  christos 	client->query.dns64_aaaa = NULL;
    801   1.1  christos 	client->query.dns64_sigaaaa = NULL;
    802   1.1  christos 	client->query.dns64_aaaaok = NULL;
    803   1.1  christos 	client->query.dns64_aaaaoklen = 0;
    804   1.1  christos 	client->query.redirect.db = NULL;
    805   1.1  christos 	client->query.redirect.node = NULL;
    806   1.1  christos 	client->query.redirect.zone = NULL;
    807   1.1  christos 	client->query.redirect.qtype = dns_rdatatype_none;
    808   1.1  christos 	client->query.redirect.result = ISC_R_SUCCESS;
    809   1.1  christos 	client->query.redirect.rdataset = NULL;
    810   1.1  christos 	client->query.redirect.sigrdataset = NULL;
    811   1.3  christos 	client->query.redirect.authoritative = false;
    812   1.3  christos 	client->query.redirect.is_zone = false;
    813   1.1  christos 	client->query.redirect.fname =
    814   1.1  christos 		dns_fixedname_initname(&client->query.redirect.fixed);
    815   1.3  christos 	query_reset(client, false);
    816   1.3  christos 	result = ns_client_newdbversion(client, 3);
    817   1.1  christos 	if (result != ISC_R_SUCCESS) {
    818   1.3  christos 		isc_mutex_destroy(&client->query.fetchlock);
    819   1.1  christos 		return (result);
    820   1.1  christos 	}
    821   1.3  christos 	result = ns_client_newnamebuf(client);
    822   1.1  christos 	if (result != ISC_R_SUCCESS) {
    823   1.3  christos 		query_freefreeversions(client, true);
    824   1.3  christos 		isc_mutex_destroy(&client->query.fetchlock);
    825   1.1  christos 	}
    826   1.1  christos 
    827   1.1  christos 	return (result);
    828   1.1  christos }
    829   1.1  christos 
    830   1.3  christos /*%
    831   1.3  christos  * Check if 'client' is allowed to query the cache of its associated view.
    832   1.3  christos  * Unless 'options' has DNS_GETDB_NOLOG set, log the result of cache ACL
    833   1.3  christos  * evaluation using the appropriate level, along with 'name' and 'qtype'.
    834   1.3  christos  *
    835   1.3  christos  * The cache ACL is only evaluated once for each client and then the result is
    836   1.3  christos  * cached: if NS_QUERYATTR_CACHEACLOKVALID is set in client->query.attributes,
    837   1.3  christos  * cache ACL evaluation has already been performed.  The evaluation result is
    838   1.3  christos  * also stored in client->query.attributes: if NS_QUERYATTR_CACHEACLOK is set,
    839   1.3  christos  * the client is allowed cache access.
    840   1.3  christos  *
    841   1.3  christos  * Returns:
    842   1.3  christos  *
    843   1.3  christos  *\li	#ISC_R_SUCCESS	'client' is allowed to access cache
    844   1.3  christos  *\li	#DNS_R_REFUSED	'client' is not allowed to access cache
    845   1.3  christos  */
    846   1.3  christos static isc_result_t
    847   1.3  christos query_checkcacheaccess(ns_client_t *client, const dns_name_t *name,
    848   1.9  christos 		       dns_rdatatype_t qtype, unsigned int options) {
    849   1.3  christos 	isc_result_t result;
    850   1.3  christos 
    851   1.3  christos 	if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) == 0) {
    852   1.3  christos 		/*
    853   1.3  christos 		 * The view's cache ACLs have not yet been evaluated.
    854   1.3  christos 		 * Do it now. Both allow-query-cache and
    855   1.3  christos 		 * allow-query-cache-on must be satsified.
    856   1.3  christos 		 */
    857   1.3  christos 		bool log = ((options & DNS_GETDB_NOLOG) == 0);
    858   1.3  christos 		char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
    859   1.1  christos 
    860   1.3  christos 		result = ns_client_checkaclsilent(client, NULL,
    861   1.9  christos 						  client->view->cacheacl, true);
    862   1.3  christos 		if (result == ISC_R_SUCCESS) {
    863   1.9  christos 			result = ns_client_checkaclsilent(
    864   1.9  christos 				client, &client->destaddr,
    865   1.9  christos 				client->view->cacheonacl, true);
    866   1.9  christos 		}
    867   1.3  christos 		if (result == ISC_R_SUCCESS) {
    868   1.3  christos 			/*
    869   1.3  christos 			 * We were allowed by the "allow-query-cache" ACL.
    870   1.3  christos 			 */
    871   1.3  christos 			client->query.attributes |= NS_QUERYATTR_CACHEACLOK;
    872   1.9  christos 			if (log && isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(3)))
    873   1.3  christos 			{
    874   1.3  christos 				ns_client_aclmsg("query (cache)", name, qtype,
    875   1.3  christos 						 client->view->rdclass, msg,
    876   1.3  christos 						 sizeof(msg));
    877   1.3  christos 				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
    878   1.3  christos 					      NS_LOGMODULE_QUERY,
    879   1.3  christos 					      ISC_LOG_DEBUG(3), "%s approved",
    880   1.3  christos 					      msg);
    881   1.3  christos 			}
    882   1.3  christos 		} else if (log) {
    883   1.7  christos 			pfilter_notify(result, client, "checkcacheaccess");
    884   1.7  christos 
    885   1.3  christos 			/*
    886   1.3  christos 			 * We were denied by the "allow-query-cache" ACL.
    887   1.3  christos 			 * There is no need to clear NS_QUERYATTR_CACHEACLOK
    888   1.3  christos 			 * since it is cleared by query_reset(), before query
    889   1.3  christos 			 * processing starts.
    890   1.3  christos 			 */
    891   1.3  christos 			ns_client_aclmsg("query (cache)", name, qtype,
    892   1.3  christos 					 client->view->rdclass, msg,
    893   1.3  christos 					 sizeof(msg));
    894   1.3  christos 			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
    895   1.3  christos 				      NS_LOGMODULE_QUERY, ISC_LOG_INFO,
    896   1.3  christos 				      "%s denied", msg);
    897   1.3  christos 		}
    898   1.1  christos 
    899   1.1  christos 		/*
    900   1.3  christos 		 * Evaluation has been finished; make sure we will just consult
    901   1.3  christos 		 * NS_QUERYATTR_CACHEACLOK for this client from now on.
    902   1.1  christos 		 */
    903   1.3  christos 		client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID;
    904   1.1  christos 	}
    905   1.1  christos 
    906   1.9  christos 	return ((client->query.attributes & NS_QUERYATTR_CACHEACLOK) != 0
    907   1.9  christos 			? ISC_R_SUCCESS
    908   1.9  christos 			: DNS_R_REFUSED);
    909   1.1  christos }
    910   1.1  christos 
    911   1.1  christos static inline isc_result_t
    912   1.1  christos query_validatezonedb(ns_client_t *client, const dns_name_t *name,
    913   1.1  christos 		     dns_rdatatype_t qtype, unsigned int options,
    914   1.1  christos 		     dns_zone_t *zone, dns_db_t *db,
    915   1.9  christos 		     dns_dbversion_t **versionp) {
    916   1.1  christos 	isc_result_t result;
    917   1.1  christos 	dns_acl_t *queryacl, *queryonacl;
    918   1.1  christos 	ns_dbversion_t *dbversion;
    919   1.1  christos 
    920   1.1  christos 	REQUIRE(zone != NULL);
    921   1.1  christos 	REQUIRE(db != NULL);
    922   1.1  christos 
    923   1.1  christos 	/*
    924   1.3  christos 	 * Mirror zone data is treated as cache data.
    925   1.3  christos 	 */
    926   1.3  christos 	if (dns_zone_gettype(zone) == dns_zone_mirror) {
    927   1.3  christos 		return (query_checkcacheaccess(client, name, qtype, options));
    928   1.3  christos 	}
    929   1.3  christos 
    930   1.3  christos 	/*
    931   1.1  christos 	 * This limits our searching to the zone where the first name
    932   1.1  christos 	 * (the query target) was looked for.  This prevents following
    933   1.1  christos 	 * CNAMES or DNAMES into other zones and prevents returning
    934   1.1  christos 	 * additional data from other zones. This does not apply if we're
    935   1.1  christos 	 * answering a query where recursion is requested and allowed.
    936   1.1  christos 	 */
    937   1.1  christos 	if (client->query.rpz_st == NULL &&
    938   1.1  christos 	    !(WANTRECURSION(client) && RECURSIONOK(client)) &&
    939   1.1  christos 	    client->query.authdbset && db != client->query.authdb)
    940   1.1  christos 	{
    941   1.1  christos 		return (DNS_R_REFUSED);
    942   1.1  christos 	}
    943   1.1  christos 
    944   1.1  christos 	/*
    945   1.1  christos 	 * Non recursive query to a static-stub zone is prohibited; its
    946   1.1  christos 	 * zone content is not public data, but a part of local configuration
    947   1.1  christos 	 * and should not be disclosed.
    948   1.1  christos 	 */
    949   1.1  christos 	if (dns_zone_gettype(zone) == dns_zone_staticstub &&
    950   1.1  christos 	    !RECURSIONOK(client)) {
    951   1.1  christos 		return (DNS_R_REFUSED);
    952   1.1  christos 	}
    953   1.1  christos 
    954   1.1  christos 	/*
    955   1.1  christos 	 * If the zone has an ACL, we'll check it, otherwise
    956   1.1  christos 	 * we use the view's "allow-query" ACL.  Each ACL is only checked
    957   1.1  christos 	 * once per query.
    958   1.1  christos 	 *
    959   1.1  christos 	 * Also, get the database version to use.
    960   1.1  christos 	 */
    961   1.1  christos 
    962   1.1  christos 	/*
    963   1.1  christos 	 * Get the current version of this database.
    964   1.1  christos 	 */
    965   1.3  christos 	dbversion = ns_client_findversion(client, db);
    966   1.1  christos 	if (dbversion == NULL) {
    967   1.1  christos 		CTRACE(ISC_LOG_ERROR, "unable to get db version");
    968   1.1  christos 		return (DNS_R_SERVFAIL);
    969   1.1  christos 	}
    970   1.1  christos 
    971   1.9  christos 	if ((options & DNS_GETDB_IGNOREACL) != 0) {
    972   1.1  christos 		goto approved;
    973   1.9  christos 	}
    974   1.1  christos 	if (dbversion->acl_checked) {
    975   1.9  christos 		if (!dbversion->queryok) {
    976   1.1  christos 			return (DNS_R_REFUSED);
    977   1.9  christos 		}
    978   1.1  christos 		goto approved;
    979   1.1  christos 	}
    980   1.1  christos 
    981   1.1  christos 	queryacl = dns_zone_getqueryacl(zone);
    982   1.1  christos 	if (queryacl == NULL) {
    983   1.1  christos 		queryacl = client->view->queryacl;
    984   1.9  christos 		if ((client->query.attributes & NS_QUERYATTR_QUERYOKVALID) != 0)
    985   1.9  christos 		{
    986   1.1  christos 			/*
    987   1.1  christos 			 * We've evaluated the view's queryacl already.  If
    988   1.1  christos 			 * NS_QUERYATTR_QUERYOK is set, then the client is
    989   1.1  christos 			 * allowed to make queries, otherwise the query should
    990   1.1  christos 			 * be refused.
    991   1.1  christos 			 */
    992   1.3  christos 			dbversion->acl_checked = true;
    993   1.9  christos 			if ((client->query.attributes & NS_QUERYATTR_QUERYOK) ==
    994   1.9  christos 			    0) {
    995   1.3  christos 				dbversion->queryok = false;
    996   1.1  christos 				return (DNS_R_REFUSED);
    997   1.1  christos 			}
    998   1.3  christos 			dbversion->queryok = true;
    999   1.1  christos 			goto approved;
   1000   1.1  christos 		}
   1001   1.1  christos 	}
   1002   1.1  christos 
   1003   1.3  christos 	result = ns_client_checkaclsilent(client, NULL, queryacl, true);
   1004   1.1  christos 	if ((options & DNS_GETDB_NOLOG) == 0) {
   1005   1.1  christos 		char msg[NS_CLIENT_ACLMSGSIZE("query")];
   1006   1.1  christos 		if (result == ISC_R_SUCCESS) {
   1007   1.1  christos 			if (isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(3))) {
   1008   1.1  christos 				ns_client_aclmsg("query", name, qtype,
   1009   1.9  christos 						 client->view->rdclass, msg,
   1010   1.9  christos 						 sizeof(msg));
   1011   1.9  christos 				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
   1012   1.1  christos 					      NS_LOGMODULE_QUERY,
   1013   1.9  christos 					      ISC_LOG_DEBUG(3), "%s approved",
   1014   1.9  christos 					      msg);
   1015   1.1  christos 			}
   1016   1.1  christos 		} else {
   1017   1.7  christos 			pfilter_notify(result, client, "validatezonedb");
   1018   1.1  christos 			ns_client_aclmsg("query", name, qtype,
   1019   1.9  christos 					 client->view->rdclass, msg,
   1020   1.9  christos 					 sizeof(msg));
   1021   1.1  christos 			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
   1022   1.1  christos 				      NS_LOGMODULE_QUERY, ISC_LOG_INFO,
   1023   1.1  christos 				      "%s denied", msg);
   1024   1.1  christos 		}
   1025   1.1  christos 	}
   1026   1.1  christos 
   1027   1.1  christos 	if (queryacl == client->view->queryacl) {
   1028   1.1  christos 		if (result == ISC_R_SUCCESS) {
   1029   1.1  christos 			/*
   1030   1.1  christos 			 * We were allowed by the default
   1031   1.1  christos 			 * "allow-query" ACL.  Remember this so we
   1032   1.1  christos 			 * don't have to check again.
   1033   1.1  christos 			 */
   1034   1.1  christos 			client->query.attributes |= NS_QUERYATTR_QUERYOK;
   1035   1.1  christos 		}
   1036   1.1  christos 		/*
   1037   1.1  christos 		 * We've now evaluated the view's query ACL, and
   1038   1.1  christos 		 * the NS_QUERYATTR_QUERYOK attribute is now valid.
   1039   1.1  christos 		 */
   1040   1.1  christos 		client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
   1041   1.1  christos 	}
   1042   1.1  christos 
   1043   1.1  christos 	/* If and only if we've gotten this far, check allow-query-on too */
   1044   1.1  christos 	if (result == ISC_R_SUCCESS) {
   1045   1.1  christos 		queryonacl = dns_zone_getqueryonacl(zone);
   1046   1.9  christos 		if (queryonacl == NULL) {
   1047   1.1  christos 			queryonacl = client->view->queryonacl;
   1048   1.9  christos 		}
   1049   1.1  christos 
   1050   1.1  christos 		result = ns_client_checkaclsilent(client, &client->destaddr,
   1051   1.3  christos 						  queryonacl, true);
   1052   1.9  christos 		if ((options & DNS_GETDB_NOLOG) == 0 && result != ISC_R_SUCCESS)
   1053   1.9  christos 		{
   1054   1.1  christos 			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
   1055   1.1  christos 				      NS_LOGMODULE_QUERY, ISC_LOG_INFO,
   1056   1.1  christos 				      "query-on denied");
   1057   1.9  christos 		}
   1058   1.1  christos 	}
   1059   1.1  christos 
   1060   1.3  christos 	dbversion->acl_checked = true;
   1061   1.1  christos 	if (result != ISC_R_SUCCESS) {
   1062   1.3  christos 		dbversion->queryok = false;
   1063   1.1  christos 		return (DNS_R_REFUSED);
   1064   1.1  christos 	}
   1065   1.3  christos 	dbversion->queryok = true;
   1066   1.1  christos 
   1067   1.9  christos approved:
   1068   1.1  christos 	/* Transfer ownership, if necessary. */
   1069   1.9  christos 	if (versionp != NULL) {
   1070   1.1  christos 		*versionp = dbversion->version;
   1071   1.9  christos 	}
   1072   1.1  christos 	return (ISC_R_SUCCESS);
   1073   1.1  christos }
   1074   1.1  christos 
   1075   1.1  christos static inline isc_result_t
   1076   1.1  christos query_getzonedb(ns_client_t *client, const dns_name_t *name,
   1077   1.9  christos 		dns_rdatatype_t qtype, unsigned int options, dns_zone_t **zonep,
   1078   1.9  christos 		dns_db_t **dbp, dns_dbversion_t **versionp) {
   1079   1.1  christos 	isc_result_t result;
   1080   1.1  christos 	unsigned int ztoptions;
   1081   1.1  christos 	dns_zone_t *zone = NULL;
   1082   1.1  christos 	dns_db_t *db = NULL;
   1083   1.3  christos 	bool partial = false;
   1084   1.1  christos 
   1085   1.1  christos 	REQUIRE(zonep != NULL && *zonep == NULL);
   1086   1.1  christos 	REQUIRE(dbp != NULL && *dbp == NULL);
   1087   1.1  christos 
   1088   1.1  christos 	/*%
   1089   1.1  christos 	 * Find a zone database to answer the query.
   1090   1.1  christos 	 */
   1091   1.3  christos 	ztoptions = DNS_ZTFIND_MIRROR;
   1092   1.3  christos 	if ((options & DNS_GETDB_NOEXACT) != 0) {
   1093   1.3  christos 		ztoptions |= DNS_ZTFIND_NOEXACT;
   1094   1.3  christos 	}
   1095   1.1  christos 
   1096   1.1  christos 	result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
   1097   1.1  christos 			     &zone);
   1098   1.1  christos 
   1099   1.9  christos 	if (result == DNS_R_PARTIALMATCH) {
   1100   1.3  christos 		partial = true;
   1101   1.9  christos 	}
   1102   1.9  christos 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
   1103   1.1  christos 		result = dns_zone_getdb(zone, &db);
   1104   1.9  christos 	}
   1105   1.1  christos 
   1106   1.9  christos 	if (result != ISC_R_SUCCESS) {
   1107   1.1  christos 		goto fail;
   1108   1.9  christos 	}
   1109   1.1  christos 
   1110   1.1  christos 	result = query_validatezonedb(client, name, qtype, options, zone, db,
   1111   1.1  christos 				      versionp);
   1112   1.1  christos 
   1113   1.9  christos 	if (result != ISC_R_SUCCESS) {
   1114   1.1  christos 		goto fail;
   1115   1.9  christos 	}
   1116   1.1  christos 
   1117   1.1  christos 	/* Transfer ownership. */
   1118   1.1  christos 	*zonep = zone;
   1119   1.1  christos 	*dbp = db;
   1120   1.1  christos 
   1121   1.9  christos 	if (partial && (options & DNS_GETDB_PARTIAL) != 0) {
   1122   1.1  christos 		return (DNS_R_PARTIALMATCH);
   1123   1.9  christos 	}
   1124   1.1  christos 	return (ISC_R_SUCCESS);
   1125   1.1  christos 
   1126   1.9  christos fail:
   1127   1.9  christos 	if (zone != NULL) {
   1128   1.1  christos 		dns_zone_detach(&zone);
   1129   1.9  christos 	}
   1130   1.9  christos 	if (db != NULL) {
   1131   1.1  christos 		dns_db_detach(&db);
   1132   1.9  christos 	}
   1133   1.1  christos 
   1134   1.1  christos 	return (result);
   1135   1.1  christos }
   1136   1.1  christos 
   1137   1.1  christos static void
   1138   1.9  christos rpz_log_rewrite(ns_client_t *client, bool disabled, dns_rpz_policy_t policy,
   1139   1.9  christos 		dns_rpz_type_t type, dns_zone_t *p_zone, dns_name_t *p_name,
   1140   1.9  christos 		dns_name_t *cname, dns_rpz_num_t rpz_num) {
   1141   1.3  christos 	char cname_buf[DNS_NAME_FORMATSIZE] = { 0 };
   1142   1.3  christos 	char p_name_buf[DNS_NAME_FORMATSIZE];
   1143   1.1  christos 	char qname_buf[DNS_NAME_FORMATSIZE];
   1144   1.3  christos 	char classbuf[DNS_RDATACLASS_FORMATSIZE];
   1145   1.3  christos 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   1146   1.1  christos 	const char *s1 = cname_buf, *s2 = cname_buf;
   1147   1.3  christos 	dns_rdataset_t *rdataset;
   1148   1.1  christos 	dns_rpz_st_t *st;
   1149   1.3  christos 	isc_stats_t *zonestats;
   1150   1.1  christos 
   1151   1.1  christos 	/*
   1152   1.1  christos 	 * Count enabled rewrites in the global counter.
   1153   1.1  christos 	 * Count both enabled and disabled rewrites for each zone.
   1154   1.1  christos 	 */
   1155   1.1  christos 	if (!disabled && policy != DNS_RPZ_POLICY_PASSTHRU) {
   1156   1.1  christos 		ns_stats_increment(client->sctx->nsstats,
   1157   1.1  christos 				   ns_statscounter_rpz_rewrites);
   1158   1.1  christos 	}
   1159   1.1  christos 	if (p_zone != NULL) {
   1160   1.1  christos 		zonestats = dns_zone_getrequeststats(p_zone);
   1161   1.9  christos 		if (zonestats != NULL) {
   1162   1.1  christos 			isc_stats_increment(zonestats,
   1163   1.1  christos 					    ns_statscounter_rpz_rewrites);
   1164   1.9  christos 		}
   1165   1.1  christos 	}
   1166   1.1  christos 
   1167   1.9  christos 	if (!isc_log_wouldlog(ns_lctx, DNS_RPZ_INFO_LEVEL)) {
   1168   1.1  christos 		return;
   1169   1.9  christos 	}
   1170   1.1  christos 
   1171   1.1  christos 	st = client->query.rpz_st;
   1172   1.9  christos 	if ((st->popt.no_log & DNS_RPZ_ZBIT(rpz_num)) != 0) {
   1173   1.1  christos 		return;
   1174   1.9  christos 	}
   1175   1.1  christos 
   1176   1.1  christos 	dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf));
   1177   1.1  christos 	dns_name_format(p_name, p_name_buf, sizeof(p_name_buf));
   1178   1.1  christos 	if (cname != NULL) {
   1179   1.1  christos 		s1 = " (CNAME to: ";
   1180   1.1  christos 		dns_name_format(cname, cname_buf, sizeof(cname_buf));
   1181   1.1  christos 		s2 = ")";
   1182   1.1  christos 	}
   1183   1.1  christos 
   1184   1.3  christos 	/*
   1185   1.3  christos 	 *  Log Qclass and Qtype in addition to existing
   1186   1.3  christos 	 *  fields.
   1187   1.3  christos 	 */
   1188   1.3  christos 	rdataset = ISC_LIST_HEAD(client->query.origqname->list);
   1189   1.3  christos 	INSIST(rdataset != NULL);
   1190   1.3  christos 	dns_rdataclass_format(rdataset->rdclass, classbuf, sizeof(classbuf));
   1191   1.3  christos 	dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
   1192   1.3  christos 
   1193   1.1  christos 	ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY,
   1194   1.3  christos 		      DNS_RPZ_INFO_LEVEL,
   1195   1.3  christos 		      "%srpz %s %s rewrite %s/%s/%s via %s%s%s%s",
   1196   1.9  christos 		      disabled ? "disabled " : "", dns_rpz_type2str(type),
   1197   1.9  christos 		      dns_rpz_policy2str(policy), qname_buf, typebuf, classbuf,
   1198   1.3  christos 		      p_name_buf, s1, cname_buf, s2);
   1199   1.1  christos }
   1200   1.1  christos 
   1201   1.1  christos static void
   1202   1.1  christos rpz_log_fail_helper(ns_client_t *client, int level, dns_name_t *p_name,
   1203   1.1  christos 		    dns_rpz_type_t rpz_type1, dns_rpz_type_t rpz_type2,
   1204   1.9  christos 		    const char *str, isc_result_t result) {
   1205   1.1  christos 	char qnamebuf[DNS_NAME_FORMATSIZE];
   1206   1.1  christos 	char p_namebuf[DNS_NAME_FORMATSIZE];
   1207   1.1  christos 	const char *failed, *via, *slash, *str_blank;
   1208   1.1  christos 	const char *rpztypestr1;
   1209   1.1  christos 	const char *rpztypestr2;
   1210   1.1  christos 
   1211   1.9  christos 	if (!isc_log_wouldlog(ns_lctx, level)) {
   1212   1.1  christos 		return;
   1213   1.9  christos 	}
   1214   1.1  christos 
   1215   1.1  christos 	/*
   1216   1.1  christos 	 * bin/tests/system/rpz/tests.sh looks for "rpz.*failed" for problems.
   1217   1.1  christos 	 */
   1218   1.9  christos 	if (level <= DNS_RPZ_DEBUG_LEVEL1) {
   1219   1.3  christos 		failed = " failed: ";
   1220   1.9  christos 	} else {
   1221   1.1  christos 		failed = ": ";
   1222   1.9  christos 	}
   1223   1.1  christos 
   1224   1.1  christos 	rpztypestr1 = dns_rpz_type2str(rpz_type1);
   1225   1.1  christos 	if (rpz_type2 != DNS_RPZ_TYPE_BAD) {
   1226   1.1  christos 		slash = "/";
   1227   1.1  christos 		rpztypestr2 = dns_rpz_type2str(rpz_type2);
   1228   1.1  christos 	} else {
   1229   1.1  christos 		slash = "";
   1230   1.1  christos 		rpztypestr2 = "";
   1231   1.1  christos 	}
   1232   1.1  christos 
   1233   1.1  christos 	str_blank = (*str != ' ' && *str != '\0') ? " " : "";
   1234   1.1  christos 
   1235   1.1  christos 	dns_name_format(client->query.qname, qnamebuf, sizeof(qnamebuf));
   1236   1.1  christos 
   1237   1.1  christos 	if (p_name != NULL) {
   1238   1.1  christos 		via = " via ";
   1239   1.1  christos 		dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
   1240   1.1  christos 	} else {
   1241   1.1  christos 		via = "";
   1242   1.1  christos 		p_namebuf[0] = '\0';
   1243   1.1  christos 	}
   1244   1.1  christos 
   1245   1.9  christos 	ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY,
   1246   1.9  christos 		      level, "rpz %s%s%s rewrite %s%s%s%s%s%s%s", rpztypestr1,
   1247   1.9  christos 		      slash, rpztypestr2, qnamebuf, via, p_namebuf, str_blank,
   1248   1.1  christos 		      str, failed, isc_result_totext(result));
   1249   1.1  christos }
   1250   1.1  christos 
   1251   1.1  christos static void
   1252   1.1  christos rpz_log_fail(ns_client_t *client, int level, dns_name_t *p_name,
   1253   1.9  christos 	     dns_rpz_type_t rpz_type, const char *str, isc_result_t result) {
   1254   1.9  christos 	rpz_log_fail_helper(client, level, p_name, rpz_type, DNS_RPZ_TYPE_BAD,
   1255   1.9  christos 			    str, result);
   1256   1.1  christos }
   1257   1.1  christos 
   1258   1.1  christos /*
   1259   1.1  christos  * Get a policy rewrite zone database.
   1260   1.1  christos  */
   1261   1.1  christos static isc_result_t
   1262   1.1  christos rpz_getdb(ns_client_t *client, dns_name_t *p_name, dns_rpz_type_t rpz_type,
   1263   1.9  christos 	  dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp) {
   1264   1.1  christos 	char qnamebuf[DNS_NAME_FORMATSIZE];
   1265   1.1  christos 	char p_namebuf[DNS_NAME_FORMATSIZE];
   1266   1.1  christos 	dns_dbversion_t *rpz_version = NULL;
   1267   1.1  christos 	isc_result_t result;
   1268   1.1  christos 
   1269   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_getdb");
   1270   1.1  christos 
   1271   1.1  christos 	result = query_getzonedb(client, p_name, dns_rdatatype_any,
   1272   1.1  christos 				 DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version);
   1273   1.1  christos 	if (result == ISC_R_SUCCESS) {
   1274   1.1  christos 		dns_rpz_st_t *st = client->query.rpz_st;
   1275   1.1  christos 
   1276   1.1  christos 		/*
   1277   1.1  christos 		 * It isn't meaningful to log this message when
   1278   1.1  christos 		 * logging is disabled for some policy zones.
   1279   1.1  christos 		 */
   1280   1.1  christos 		if (st->popt.no_log == 0 &&
   1281   1.9  christos 		    isc_log_wouldlog(ns_lctx, DNS_RPZ_DEBUG_LEVEL2)) {
   1282   1.1  christos 			dns_name_format(client->query.qname, qnamebuf,
   1283   1.1  christos 					sizeof(qnamebuf));
   1284   1.1  christos 			dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
   1285   1.1  christos 			ns_client_log(client, DNS_LOGCATEGORY_RPZ,
   1286   1.1  christos 				      NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2,
   1287   1.1  christos 				      "try rpz %s rewrite %s via %s",
   1288   1.9  christos 				      dns_rpz_type2str(rpz_type), qnamebuf,
   1289   1.9  christos 				      p_namebuf);
   1290   1.1  christos 		}
   1291   1.1  christos 		*versionp = rpz_version;
   1292   1.1  christos 		return (ISC_R_SUCCESS);
   1293   1.1  christos 	}
   1294   1.1  christos 	rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type,
   1295   1.3  christos 		     "query_getzonedb()", result);
   1296   1.1  christos 	return (result);
   1297   1.1  christos }
   1298   1.1  christos 
   1299   1.3  christos /*%
   1300   1.3  christos  * Find a cache database to answer the query.  This may fail with DNS_R_REFUSED
   1301   1.3  christos  * if the client is not allowed to use the cache.
   1302   1.3  christos  */
   1303   1.1  christos static inline isc_result_t
   1304   1.1  christos query_getcachedb(ns_client_t *client, const dns_name_t *name,
   1305   1.9  christos 		 dns_rdatatype_t qtype, dns_db_t **dbp, unsigned int options) {
   1306   1.1  christos 	isc_result_t result;
   1307   1.1  christos 	dns_db_t *db = NULL;
   1308   1.1  christos 
   1309   1.1  christos 	REQUIRE(dbp != NULL && *dbp == NULL);
   1310   1.1  christos 
   1311   1.3  christos 	if (!USECACHE(client)) {
   1312   1.1  christos 		return (DNS_R_REFUSED);
   1313   1.1  christos 	}
   1314   1.1  christos 
   1315   1.3  christos 	dns_db_attach(client->view->cachedb, &db);
   1316   1.1  christos 
   1317   1.3  christos 	result = query_checkcacheaccess(client, name, qtype, options);
   1318   1.3  christos 	if (result != ISC_R_SUCCESS) {
   1319   1.3  christos 		dns_db_detach(&db);
   1320   1.1  christos 	}
   1321   1.1  christos 
   1322   1.3  christos 	/*
   1323   1.3  christos 	 * If query_checkcacheaccess() succeeded, transfer ownership of 'db'.
   1324   1.3  christos 	 * Otherwise, 'db' will be NULL due to the dns_db_detach() call above.
   1325   1.3  christos 	 */
   1326   1.1  christos 	*dbp = db;
   1327   1.1  christos 
   1328   1.3  christos 	return (result);
   1329   1.3  christos }
   1330   1.1  christos 
   1331   1.3  christos static inline isc_result_t
   1332   1.3  christos query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
   1333   1.1  christos 	    unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
   1334   1.9  christos 	    dns_dbversion_t **versionp, bool *is_zonep) {
   1335   1.1  christos 	isc_result_t result;
   1336   1.1  christos 	isc_result_t tresult;
   1337   1.1  christos 	unsigned int namelabels;
   1338   1.1  christos 	unsigned int zonelabels;
   1339   1.1  christos 	dns_zone_t *zone = NULL;
   1340   1.1  christos 
   1341   1.1  christos 	REQUIRE(zonep != NULL && *zonep == NULL);
   1342   1.1  christos 
   1343   1.1  christos 	/* Calculate how many labels are in name. */
   1344   1.1  christos 	namelabels = dns_name_countlabels(name);
   1345   1.1  christos 	zonelabels = 0;
   1346   1.1  christos 
   1347   1.1  christos 	/* Try to find name in bind's standard database. */
   1348   1.9  christos 	result = query_getzonedb(client, name, qtype, options, &zone, dbp,
   1349   1.9  christos 				 versionp);
   1350   1.1  christos 
   1351   1.1  christos 	/* See how many labels are in the zone's name.	  */
   1352   1.5  christos 	if (result == ISC_R_SUCCESS && zone != NULL) {
   1353   1.1  christos 		zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));
   1354   1.5  christos 	}
   1355   1.1  christos 
   1356   1.1  christos 	/*
   1357   1.1  christos 	 * If # zone labels < # name labels, try to find an even better match
   1358   1.1  christos 	 * Only try if DLZ drivers are loaded for this view
   1359   1.1  christos 	 */
   1360   1.1  christos 	if (ISC_UNLIKELY(zonelabels < namelabels &&
   1361   1.1  christos 			 !ISC_LIST_EMPTY(client->view->dlz_searched)))
   1362   1.1  christos 	{
   1363   1.1  christos 		dns_clientinfomethods_t cm;
   1364   1.1  christos 		dns_clientinfo_t ci;
   1365   1.1  christos 		dns_db_t *tdbp;
   1366   1.1  christos 
   1367   1.1  christos 		dns_clientinfomethods_init(&cm, ns_client_sourceip);
   1368   1.1  christos 		dns_clientinfo_init(&ci, client, NULL);
   1369   1.1  christos 
   1370   1.1  christos 		tdbp = NULL;
   1371   1.9  christos 		tresult = dns_view_searchdlz(client->view, name, zonelabels,
   1372   1.9  christos 					     &cm, &ci, &tdbp);
   1373   1.9  christos 		/* If we successful, we found a better match. */
   1374   1.1  christos 		if (tresult == ISC_R_SUCCESS) {
   1375   1.1  christos 			ns_dbversion_t *dbversion;
   1376   1.1  christos 
   1377   1.1  christos 			/*
   1378   1.1  christos 			 * If the previous search returned a zone, detach it.
   1379   1.1  christos 			 */
   1380   1.9  christos 			if (zone != NULL) {
   1381   1.1  christos 				dns_zone_detach(&zone);
   1382   1.9  christos 			}
   1383   1.1  christos 
   1384   1.1  christos 			/*
   1385   1.1  christos 			 * If the previous search returned a database,
   1386   1.1  christos 			 * detach it.
   1387   1.1  christos 			 */
   1388   1.9  christos 			if (*dbp != NULL) {
   1389   1.1  christos 				dns_db_detach(dbp);
   1390   1.9  christos 			}
   1391   1.1  christos 
   1392   1.1  christos 			/*
   1393   1.1  christos 			 * If the previous search returned a version, clear it.
   1394   1.1  christos 			 */
   1395   1.1  christos 			*versionp = NULL;
   1396   1.1  christos 
   1397   1.3  christos 			dbversion = ns_client_findversion(client, tdbp);
   1398   1.1  christos 			if (dbversion == NULL) {
   1399   1.1  christos 				tresult = ISC_R_NOMEMORY;
   1400   1.1  christos 			} else {
   1401   1.1  christos 				/*
   1402   1.1  christos 				 * Be sure to return our database.
   1403   1.1  christos 				 */
   1404   1.1  christos 				*dbp = tdbp;
   1405   1.1  christos 				*versionp = dbversion->version;
   1406   1.1  christos 			}
   1407   1.1  christos 
   1408   1.1  christos 			/*
   1409   1.1  christos 			 * We return a null zone, No stats for DLZ zones.
   1410   1.1  christos 			 */
   1411   1.1  christos 			zone = NULL;
   1412   1.1  christos 			result = tresult;
   1413   1.1  christos 		}
   1414   1.1  christos 	}
   1415   1.1  christos 
   1416   1.1  christos 	/* If successful, Transfer ownership of zone. */
   1417   1.1  christos 	if (result == ISC_R_SUCCESS) {
   1418   1.1  christos 		*zonep = zone;
   1419   1.1  christos 		/*
   1420   1.1  christos 		 * If neither attempt above succeeded, return the cache instead
   1421   1.1  christos 		 */
   1422   1.3  christos 		*is_zonep = true;
   1423   1.5  christos 	} else {
   1424   1.5  christos 		if (result == ISC_R_NOTFOUND) {
   1425   1.5  christos 			result = query_getcachedb(client, name, qtype, dbp,
   1426   1.5  christos 						  options);
   1427   1.5  christos 		}
   1428   1.3  christos 		*is_zonep = false;
   1429   1.1  christos 	}
   1430   1.1  christos 	return (result);
   1431   1.1  christos }
   1432   1.1  christos 
   1433   1.3  christos static inline bool
   1434   1.9  christos query_isduplicate(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
   1435   1.9  christos 		  dns_name_t **mnamep) {
   1436   1.1  christos 	dns_section_t section;
   1437   1.1  christos 	dns_name_t *mname = NULL;
   1438   1.1  christos 	isc_result_t result;
   1439   1.1  christos 
   1440   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate");
   1441   1.1  christos 
   1442   1.9  christos 	for (section = DNS_SECTION_ANSWER; section <= DNS_SECTION_ADDITIONAL;
   1443   1.1  christos 	     section++) {
   1444   1.9  christos 		result = dns_message_findname(client->message, section, name,
   1445   1.9  christos 					      type, 0, &mname, NULL);
   1446   1.1  christos 		if (result == ISC_R_SUCCESS) {
   1447   1.1  christos 			/*
   1448   1.1  christos 			 * We've already got this RRset in the response.
   1449   1.1  christos 			 */
   1450   1.9  christos 			CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: true: "
   1451   1.9  christos 						 "done");
   1452   1.3  christos 			return (true);
   1453   1.1  christos 		} else if (result == DNS_R_NXRRSET) {
   1454   1.1  christos 			/*
   1455   1.1  christos 			 * The name exists, but the rdataset does not.
   1456   1.1  christos 			 */
   1457   1.9  christos 			if (section == DNS_SECTION_ADDITIONAL) {
   1458   1.1  christos 				break;
   1459   1.9  christos 			}
   1460   1.9  christos 		} else {
   1461   1.1  christos 			RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
   1462   1.9  christos 		}
   1463   1.1  christos 		mname = NULL;
   1464   1.1  christos 	}
   1465   1.1  christos 
   1466   1.9  christos 	if (mnamep != NULL) {
   1467   1.1  christos 		*mnamep = mname;
   1468   1.9  christos 	}
   1469   1.1  christos 
   1470   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: false: done");
   1471   1.3  christos 	return (false);
   1472   1.1  christos }
   1473   1.1  christos 
   1474   1.6  christos /*
   1475   1.6  christos  * Look up data for given 'name' and 'type' in given 'version' of 'db' for
   1476   1.6  christos  * 'client'. Called from query_additionalauth().
   1477   1.6  christos  *
   1478   1.6  christos  * If the lookup is successful:
   1479   1.6  christos  *
   1480   1.6  christos  *   - store the node containing the result at 'nodep',
   1481   1.6  christos  *
   1482   1.6  christos  *   - store the owner name of the returned node in 'fname',
   1483   1.6  christos  *
   1484   1.6  christos  *   - if 'type' is not ANY, dns_db_findext() will put the exact rdataset being
   1485   1.6  christos  *     looked for in 'rdataset' and its signatures (if any) in 'sigrdataset',
   1486   1.6  christos  *
   1487   1.6  christos  *   - if 'type' is ANY, dns_db_findext() will leave 'rdataset' and
   1488   1.6  christos  *     'sigrdataset' disassociated and the returned node will be iterated in
   1489   1.6  christos  *     query_additional_cb().
   1490   1.6  christos  *
   1491   1.6  christos  * If the lookup is not successful:
   1492   1.6  christos  *
   1493   1.6  christos  *   - 'nodep' will not be written to,
   1494   1.6  christos  *   - 'fname' may still be modified as it is passed to dns_db_findext(),
   1495   1.6  christos  *   - 'rdataset' and 'sigrdataset' will remain disassociated.
   1496   1.6  christos  */
   1497   1.6  christos static isc_result_t
   1498   1.6  christos query_additionalauthfind(dns_db_t *db, dns_dbversion_t *version,
   1499   1.6  christos 			 const dns_name_t *name, dns_rdatatype_t type,
   1500   1.6  christos 			 ns_client_t *client, dns_dbnode_t **nodep,
   1501   1.6  christos 			 dns_name_t *fname, dns_rdataset_t *rdataset,
   1502   1.9  christos 			 dns_rdataset_t *sigrdataset) {
   1503   1.6  christos 	dns_clientinfomethods_t cm;
   1504   1.6  christos 	dns_dbnode_t *node = NULL;
   1505   1.6  christos 	dns_clientinfo_t ci;
   1506   1.6  christos 	isc_result_t result;
   1507   1.6  christos 
   1508   1.6  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   1509   1.6  christos 	dns_clientinfo_init(&ci, client, NULL);
   1510   1.6  christos 
   1511   1.6  christos 	/*
   1512   1.6  christos 	 * Since we are looking for authoritative data, we do not set
   1513   1.6  christos 	 * the GLUEOK flag.  Glue will be looked for later, but not
   1514   1.6  christos 	 * necessarily in the same database.
   1515   1.6  christos 	 */
   1516   1.6  christos 	result = dns_db_findext(db, name, version, type,
   1517   1.6  christos 				client->query.dboptions, client->now, &node,
   1518   1.6  christos 				fname, &cm, &ci, rdataset, sigrdataset);
   1519   1.6  christos 	if (result != ISC_R_SUCCESS) {
   1520   1.6  christos 		if (dns_rdataset_isassociated(rdataset)) {
   1521   1.6  christos 			dns_rdataset_disassociate(rdataset);
   1522   1.6  christos 		}
   1523   1.6  christos 
   1524   1.6  christos 		if (sigrdataset != NULL &&
   1525   1.9  christos 		    dns_rdataset_isassociated(sigrdataset)) {
   1526   1.6  christos 			dns_rdataset_disassociate(sigrdataset);
   1527   1.6  christos 		}
   1528   1.6  christos 
   1529   1.6  christos 		if (node != NULL) {
   1530   1.6  christos 			dns_db_detachnode(db, &node);
   1531   1.6  christos 		}
   1532   1.6  christos 
   1533   1.6  christos 		return (result);
   1534   1.6  christos 	}
   1535   1.6  christos 
   1536   1.6  christos 	/*
   1537   1.6  christos 	 * Do not return signatures if the zone is not fully signed.
   1538   1.6  christos 	 */
   1539   1.6  christos 	if (sigrdataset != NULL && !dns_db_issecure(db) &&
   1540   1.6  christos 	    dns_rdataset_isassociated(sigrdataset))
   1541   1.6  christos 	{
   1542   1.6  christos 		dns_rdataset_disassociate(sigrdataset);
   1543   1.6  christos 	}
   1544   1.6  christos 
   1545   1.6  christos 	*nodep = node;
   1546   1.6  christos 
   1547   1.6  christos 	return (ISC_R_SUCCESS);
   1548   1.6  christos }
   1549   1.6  christos 
   1550   1.6  christos /*
   1551   1.6  christos  * For query context 'qctx', try finding authoritative additional data for
   1552   1.6  christos  * given 'name' and 'type'. Called from query_additional_cb().
   1553   1.6  christos  *
   1554   1.6  christos  * If successful:
   1555   1.6  christos  *
   1556   1.6  christos  *   - store pointers to the database and node which contain the result in
   1557   1.6  christos  *     'dbp' and 'nodep', respectively,
   1558   1.6  christos  *
   1559   1.6  christos  *   - store the owner name of the returned node in 'fname',
   1560   1.6  christos  *
   1561   1.6  christos  *   - potentially bind 'rdataset' and 'sigrdataset', as explained in the
   1562   1.6  christos  *     comment for query_additionalauthfind().
   1563   1.6  christos  *
   1564   1.6  christos  * If unsuccessful:
   1565   1.6  christos  *
   1566   1.6  christos  *   - 'dbp' and 'nodep' will not be written to,
   1567   1.6  christos  *   - 'fname' may still be modified as it is passed to dns_db_findext(),
   1568   1.6  christos  *   - 'rdataset' and 'sigrdataset' will remain disassociated.
   1569   1.6  christos  */
   1570   1.6  christos static isc_result_t
   1571   1.6  christos query_additionalauth(query_ctx_t *qctx, const dns_name_t *name,
   1572   1.9  christos 		     dns_rdatatype_t type, dns_db_t **dbp, dns_dbnode_t **nodep,
   1573   1.9  christos 		     dns_name_t *fname, dns_rdataset_t *rdataset,
   1574   1.9  christos 		     dns_rdataset_t *sigrdataset) {
   1575   1.6  christos 	ns_client_t *client = qctx->client;
   1576   1.6  christos 	ns_dbversion_t *dbversion = NULL;
   1577   1.6  christos 	dns_dbversion_t *version = NULL;
   1578   1.6  christos 	dns_dbnode_t *node = NULL;
   1579   1.6  christos 	dns_zone_t *zone = NULL;
   1580   1.6  christos 	dns_db_t *db = NULL;
   1581   1.6  christos 	isc_result_t result;
   1582   1.6  christos 
   1583   1.6  christos 	/*
   1584   1.6  christos 	 * First, look within the same zone database for authoritative
   1585   1.6  christos 	 * additional data.
   1586   1.6  christos 	 */
   1587   1.6  christos 	if (!client->query.authdbset || client->query.authdb == NULL) {
   1588   1.6  christos 		return (ISC_R_NOTFOUND);
   1589   1.6  christos 	}
   1590   1.6  christos 
   1591   1.6  christos 	dbversion = ns_client_findversion(client, client->query.authdb);
   1592   1.6  christos 	if (dbversion == NULL) {
   1593   1.6  christos 		return (ISC_R_NOTFOUND);
   1594   1.6  christos 	}
   1595   1.6  christos 
   1596   1.6  christos 	dns_db_attach(client->query.authdb, &db);
   1597   1.6  christos 	version = dbversion->version;
   1598   1.6  christos 
   1599   1.6  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: same zone");
   1600   1.6  christos 
   1601   1.6  christos 	result = query_additionalauthfind(db, version, name, type, client,
   1602   1.6  christos 					  &node, fname, rdataset, sigrdataset);
   1603   1.6  christos 	if (result != ISC_R_SUCCESS &&
   1604   1.6  christos 	    qctx->view->minimalresponses == dns_minimal_no &&
   1605   1.6  christos 	    RECURSIONOK(client))
   1606   1.6  christos 	{
   1607   1.6  christos 		/*
   1608   1.6  christos 		 * If we aren't doing response minimization and recursion is
   1609   1.6  christos 		 * allowed, we can try and see if any other zone matches.
   1610   1.6  christos 		 */
   1611   1.6  christos 		version = NULL;
   1612   1.6  christos 		dns_db_detach(&db);
   1613   1.6  christos 		result = query_getzonedb(client, name, type, DNS_GETDB_NOLOG,
   1614   1.6  christos 					 &zone, &db, &version);
   1615   1.6  christos 		if (result != ISC_R_SUCCESS) {
   1616   1.6  christos 			return (result);
   1617   1.6  christos 		}
   1618   1.6  christos 		dns_zone_detach(&zone);
   1619   1.6  christos 
   1620   1.6  christos 		CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: other zone");
   1621   1.6  christos 
   1622   1.6  christos 		result = query_additionalauthfind(db, version, name, type,
   1623   1.6  christos 						  client, &node, fname,
   1624   1.6  christos 						  rdataset, sigrdataset);
   1625   1.6  christos 	}
   1626   1.6  christos 
   1627   1.6  christos 	if (result != ISC_R_SUCCESS) {
   1628   1.6  christos 		dns_db_detach(&db);
   1629   1.6  christos 	} else {
   1630   1.6  christos 		*nodep = node;
   1631   1.6  christos 		node = NULL;
   1632   1.6  christos 
   1633   1.6  christos 		*dbp = db;
   1634   1.6  christos 		db = NULL;
   1635   1.6  christos 	}
   1636   1.6  christos 
   1637   1.6  christos 	return (result);
   1638   1.6  christos }
   1639   1.6  christos 
   1640   1.1  christos static isc_result_t
   1641   1.3  christos query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) {
   1642   1.3  christos 	query_ctx_t *qctx = arg;
   1643   1.3  christos 	ns_client_t *client = qctx->client;
   1644   1.3  christos 	isc_result_t result, eresult = ISC_R_SUCCESS;
   1645   1.3  christos 	dns_dbnode_t *node = NULL;
   1646   1.3  christos 	dns_db_t *db = NULL;
   1647   1.3  christos 	dns_name_t *fname = NULL, *mname = NULL;
   1648   1.3  christos 	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
   1649   1.3  christos 	dns_rdataset_t *trdataset = NULL;
   1650   1.3  christos 	isc_buffer_t *dbuf = NULL;
   1651   1.1  christos 	isc_buffer_t b;
   1652   1.3  christos 	ns_dbversion_t *dbversion = NULL;
   1653   1.3  christos 	dns_dbversion_t *version = NULL;
   1654   1.3  christos 	bool added_something = false, need_addname = false;
   1655   1.1  christos 	dns_rdatatype_t type;
   1656   1.1  christos 	dns_clientinfomethods_t cm;
   1657   1.1  christos 	dns_clientinfo_t ci;
   1658   1.3  christos 	dns_rdatasetadditional_t additionaltype =
   1659   1.3  christos 		dns_rdatasetadditional_fromauth;
   1660   1.1  christos 
   1661   1.1  christos 	REQUIRE(NS_CLIENT_VALID(client));
   1662   1.1  christos 	REQUIRE(qtype != dns_rdatatype_any);
   1663   1.1  christos 
   1664   1.3  christos 	if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype)) {
   1665   1.1  christos 		return (ISC_R_SUCCESS);
   1666   1.3  christos 	}
   1667   1.1  christos 
   1668   1.3  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb");
   1669   1.1  christos 
   1670   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   1671   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   1672   1.1  christos 
   1673   1.1  christos 	/*
   1674   1.1  christos 	 * We treat type A additional section processing as if it
   1675   1.1  christos 	 * were "any address type" additional section processing.
   1676   1.1  christos 	 * To avoid multiple lookups, we do an 'any' database
   1677   1.1  christos 	 * lookup and iterate over the node.
   1678   1.1  christos 	 */
   1679   1.3  christos 	if (qtype == dns_rdatatype_a) {
   1680   1.1  christos 		type = dns_rdatatype_any;
   1681   1.3  christos 	} else {
   1682   1.1  christos 		type = qtype;
   1683   1.3  christos 	}
   1684   1.1  christos 
   1685   1.1  christos 	/*
   1686   1.1  christos 	 * Get some resources.
   1687   1.1  christos 	 */
   1688   1.3  christos 	dbuf = ns_client_getnamebuf(client);
   1689   1.3  christos 	if (dbuf == NULL) {
   1690   1.1  christos 		goto cleanup;
   1691   1.3  christos 	}
   1692   1.3  christos 	fname = ns_client_newname(client, dbuf, &b);
   1693   1.3  christos 	rdataset = ns_client_newrdataset(client);
   1694   1.3  christos 	if (fname == NULL || rdataset == NULL) {
   1695   1.1  christos 		goto cleanup;
   1696   1.3  christos 	}
   1697   1.1  christos 	if (WANTDNSSEC(client)) {
   1698   1.3  christos 		sigrdataset = ns_client_newrdataset(client);
   1699   1.3  christos 		if (sigrdataset == NULL) {
   1700   1.1  christos 			goto cleanup;
   1701   1.3  christos 		}
   1702   1.1  christos 	}
   1703   1.1  christos 
   1704   1.1  christos 	/*
   1705   1.1  christos 	 * If we want only minimal responses and are here, then it must
   1706   1.1  christos 	 * be for glue.
   1707   1.1  christos 	 */
   1708  1.11  christos 	if (qctx->view->minimalresponses == dns_minimal_yes &&
   1709  1.11  christos 	    client->query.qtype != dns_rdatatype_ns)
   1710  1.11  christos 	{
   1711   1.1  christos 		goto try_glue;
   1712   1.3  christos 	}
   1713   1.1  christos 
   1714   1.1  christos 	/*
   1715   1.6  christos 	 * First, look for authoritative additional data.
   1716   1.1  christos 	 */
   1717   1.6  christos 	result = query_additionalauth(qctx, name, type, &db, &node, fname,
   1718   1.6  christos 				      rdataset, sigrdataset);
   1719   1.1  christos 	if (result == ISC_R_SUCCESS) {
   1720   1.1  christos 		goto found;
   1721   1.1  christos 	}
   1722   1.1  christos 
   1723   1.1  christos 	/*
   1724   1.1  christos 	 * No authoritative data was found.  The cache is our next best bet.
   1725   1.1  christos 	 */
   1726   1.3  christos 	if (!qctx->view->recursion) {
   1727   1.1  christos 		goto try_glue;
   1728   1.3  christos 	}
   1729   1.1  christos 
   1730   1.1  christos 	additionaltype = dns_rdatasetadditional_fromcache;
   1731   1.1  christos 	result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
   1732   1.1  christos 	if (result != ISC_R_SUCCESS) {
   1733   1.1  christos 		/*
   1734   1.1  christos 		 * Most likely the client isn't allowed to query the cache.
   1735   1.1  christos 		 */
   1736   1.1  christos 		goto try_glue;
   1737   1.1  christos 	}
   1738   1.1  christos 	/*
   1739   1.1  christos 	 * Attempt to validate glue.
   1740   1.1  christos 	 */
   1741   1.1  christos 	if (sigrdataset == NULL) {
   1742   1.3  christos 		sigrdataset = ns_client_newrdataset(client);
   1743   1.3  christos 		if (sigrdataset == NULL) {
   1744   1.1  christos 			goto cleanup;
   1745   1.3  christos 		}
   1746   1.1  christos 	}
   1747   1.1  christos 
   1748   1.1  christos 	version = NULL;
   1749   1.1  christos 	result = dns_db_findext(db, name, version, type,
   1750   1.9  christos 				client->query.dboptions | DNS_DBFIND_GLUEOK |
   1751   1.9  christos 					DNS_DBFIND_ADDITIONALOK,
   1752   1.9  christos 				client->now, &node, fname, &cm, &ci, rdataset,
   1753   1.9  christos 				sigrdataset);
   1754   1.1  christos 
   1755   1.3  christos 	dns_cache_updatestats(qctx->view->cache, result);
   1756   1.3  christos 	if (!WANTDNSSEC(client)) {
   1757   1.3  christos 		ns_client_putrdataset(client, &sigrdataset);
   1758   1.3  christos 	}
   1759   1.9  christos 	if (result == ISC_R_SUCCESS) {
   1760   1.1  christos 		goto found;
   1761   1.9  christos 	}
   1762   1.1  christos 
   1763   1.3  christos 	if (dns_rdataset_isassociated(rdataset)) {
   1764   1.1  christos 		dns_rdataset_disassociate(rdataset);
   1765   1.3  christos 	}
   1766   1.3  christos 	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
   1767   1.1  christos 		dns_rdataset_disassociate(sigrdataset);
   1768   1.3  christos 	}
   1769   1.3  christos 	if (node != NULL) {
   1770   1.1  christos 		dns_db_detachnode(db, &node);
   1771   1.3  christos 	}
   1772   1.1  christos 	dns_db_detach(&db);
   1773   1.1  christos 
   1774   1.9  christos try_glue:
   1775   1.1  christos 	/*
   1776   1.1  christos 	 * No cached data was found.  Glue is our last chance.
   1777   1.1  christos 	 * RFC1035 sayeth:
   1778   1.1  christos 	 *
   1779   1.1  christos 	 *	NS records cause both the usual additional section
   1780   1.1  christos 	 *	processing to locate a type A record, and, when used
   1781   1.1  christos 	 *	in a referral, a special search of the zone in which
   1782   1.1  christos 	 *	they reside for glue information.
   1783   1.1  christos 	 *
   1784   1.1  christos 	 * This is the "special search".  Note that we must search
   1785   1.1  christos 	 * the zone where the NS record resides, not the zone it
   1786   1.1  christos 	 * points to, and that we only do the search in the delegation
   1787   1.1  christos 	 * case (identified by client->query.gluedb being set).
   1788   1.1  christos 	 */
   1789   1.1  christos 
   1790   1.3  christos 	if (client->query.gluedb == NULL) {
   1791   1.1  christos 		goto cleanup;
   1792   1.3  christos 	}
   1793   1.1  christos 
   1794   1.1  christos 	/*
   1795   1.1  christos 	 * Don't poison caches using the bailiwick protection model.
   1796   1.1  christos 	 */
   1797   1.3  christos 	if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) {
   1798   1.1  christos 		goto cleanup;
   1799   1.3  christos 	}
   1800   1.1  christos 
   1801   1.3  christos 	dbversion = ns_client_findversion(client, client->query.gluedb);
   1802   1.3  christos 	if (dbversion == NULL) {
   1803   1.1  christos 		goto cleanup;
   1804   1.3  christos 	}
   1805   1.1  christos 
   1806   1.1  christos 	dns_db_attach(client->query.gluedb, &db);
   1807   1.1  christos 	version = dbversion->version;
   1808   1.1  christos 	additionaltype = dns_rdatasetadditional_fromglue;
   1809   1.1  christos 	result = dns_db_findext(db, name, version, type,
   1810   1.1  christos 				client->query.dboptions | DNS_DBFIND_GLUEOK,
   1811   1.9  christos 				client->now, &node, fname, &cm, &ci, rdataset,
   1812   1.9  christos 				sigrdataset);
   1813   1.9  christos 	if (result != ISC_R_SUCCESS && result != DNS_R_ZONECUT &&
   1814   1.9  christos 	    result != DNS_R_GLUE) {
   1815   1.1  christos 		goto cleanup;
   1816   1.3  christos 	}
   1817   1.1  christos 
   1818   1.9  christos found:
   1819   1.1  christos 	/*
   1820   1.1  christos 	 * We have found a potential additional data rdataset, or
   1821   1.1  christos 	 * at least a node to iterate over.
   1822   1.1  christos 	 */
   1823   1.3  christos 	ns_client_keepname(client, fname, dbuf);
   1824   1.1  christos 
   1825   1.1  christos 	/*
   1826   1.1  christos 	 * If we have an rdataset, add it to the additional data
   1827   1.1  christos 	 * section.
   1828   1.1  christos 	 */
   1829   1.1  christos 	mname = NULL;
   1830   1.1  christos 	if (dns_rdataset_isassociated(rdataset) &&
   1831   1.3  christos 	    !query_isduplicate(client, fname, type, &mname))
   1832   1.3  christos 	{
   1833   1.1  christos 		if (mname != NULL) {
   1834   1.1  christos 			INSIST(mname != fname);
   1835   1.3  christos 			ns_client_releasename(client, &fname);
   1836   1.1  christos 			fname = mname;
   1837   1.3  christos 		} else {
   1838   1.3  christos 			need_addname = true;
   1839   1.3  christos 		}
   1840   1.1  christos 		ISC_LIST_APPEND(fname->list, rdataset, link);
   1841   1.1  christos 		trdataset = rdataset;
   1842   1.1  christos 		rdataset = NULL;
   1843   1.3  christos 		added_something = true;
   1844   1.1  christos 		/*
   1845   1.1  christos 		 * Note: we only add SIGs if we've added the type they cover,
   1846   1.1  christos 		 * so we do not need to check if the SIG rdataset is already
   1847   1.1  christos 		 * in the response.
   1848   1.1  christos 		 */
   1849   1.1  christos 		if (sigrdataset != NULL &&
   1850   1.9  christos 		    dns_rdataset_isassociated(sigrdataset)) {
   1851   1.1  christos 			ISC_LIST_APPEND(fname->list, sigrdataset, link);
   1852   1.1  christos 			sigrdataset = NULL;
   1853   1.1  christos 		}
   1854   1.1  christos 	}
   1855   1.1  christos 
   1856   1.1  christos 	if (qtype == dns_rdatatype_a) {
   1857   1.1  christos 		/*
   1858   1.1  christos 		 * We now go looking for A and AAAA records, along with
   1859   1.1  christos 		 * their signatures.
   1860   1.1  christos 		 *
   1861   1.1  christos 		 * XXXRTH  This code could be more efficient.
   1862   1.1  christos 		 */
   1863   1.1  christos 		if (rdataset != NULL) {
   1864   1.3  christos 			if (dns_rdataset_isassociated(rdataset)) {
   1865   1.1  christos 				dns_rdataset_disassociate(rdataset);
   1866   1.3  christos 			}
   1867   1.1  christos 		} else {
   1868   1.3  christos 			rdataset = ns_client_newrdataset(client);
   1869   1.3  christos 			if (rdataset == NULL) {
   1870   1.1  christos 				goto addname;
   1871   1.3  christos 			}
   1872   1.1  christos 		}
   1873   1.1  christos 		if (sigrdataset != NULL) {
   1874   1.3  christos 			if (dns_rdataset_isassociated(sigrdataset)) {
   1875   1.1  christos 				dns_rdataset_disassociate(sigrdataset);
   1876   1.3  christos 			}
   1877   1.1  christos 		} else if (WANTDNSSEC(client)) {
   1878   1.3  christos 			sigrdataset = ns_client_newrdataset(client);
   1879   1.3  christos 			if (sigrdataset == NULL) {
   1880   1.1  christos 				goto addname;
   1881   1.3  christos 			}
   1882   1.1  christos 		}
   1883   1.3  christos 		if (query_isduplicate(client, fname, dns_rdatatype_a, NULL)) {
   1884   1.1  christos 			goto aaaa_lookup;
   1885   1.3  christos 		}
   1886   1.9  christos 		result = dns_db_findrdataset(db, node, version, dns_rdatatype_a,
   1887   1.9  christos 					     0, client->now, rdataset,
   1888   1.9  christos 					     sigrdataset);
   1889   1.1  christos 		if (result == DNS_R_NCACHENXDOMAIN) {
   1890   1.1  christos 			goto addname;
   1891   1.1  christos 		} else if (result == DNS_R_NCACHENXRRSET) {
   1892   1.1  christos 			dns_rdataset_disassociate(rdataset);
   1893   1.1  christos 			if (sigrdataset != NULL &&
   1894   1.9  christos 			    dns_rdataset_isassociated(sigrdataset)) {
   1895   1.1  christos 				dns_rdataset_disassociate(sigrdataset);
   1896   1.3  christos 			}
   1897   1.1  christos 		} else if (result == ISC_R_SUCCESS) {
   1898   1.3  christos 			bool invalid = false;
   1899   1.1  christos 			mname = NULL;
   1900   1.1  christos 			if (additionaltype ==
   1901   1.9  christos 				    dns_rdatasetadditional_fromcache &&
   1902   1.1  christos 			    (DNS_TRUST_PENDING(rdataset->trust) ||
   1903   1.1  christos 			     DNS_TRUST_GLUE(rdataset->trust)))
   1904   1.1  christos 			{
   1905   1.1  christos 				/* validate() may change rdataset->trust */
   1906   1.9  christos 				invalid = !validate(client, db, fname, rdataset,
   1907   1.9  christos 						    sigrdataset);
   1908   1.1  christos 			}
   1909   1.1  christos 			if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
   1910   1.1  christos 				dns_rdataset_disassociate(rdataset);
   1911   1.1  christos 				if (sigrdataset != NULL &&
   1912   1.9  christos 				    dns_rdataset_isassociated(sigrdataset)) {
   1913   1.1  christos 					dns_rdataset_disassociate(sigrdataset);
   1914   1.3  christos 				}
   1915   1.1  christos 			} else if (!query_isduplicate(client, fname,
   1916   1.9  christos 						      dns_rdatatype_a, &mname))
   1917   1.9  christos 			{
   1918   1.1  christos 				if (mname != fname) {
   1919   1.1  christos 					if (mname != NULL) {
   1920   1.3  christos 						ns_client_releasename(client,
   1921   1.3  christos 								      &fname);
   1922   1.1  christos 						fname = mname;
   1923   1.3  christos 					} else {
   1924   1.3  christos 						need_addname = true;
   1925   1.3  christos 					}
   1926   1.1  christos 				}
   1927   1.1  christos 				ISC_LIST_APPEND(fname->list, rdataset, link);
   1928   1.3  christos 				added_something = true;
   1929   1.1  christos 				if (sigrdataset != NULL &&
   1930   1.9  christos 				    dns_rdataset_isassociated(sigrdataset)) {
   1931   1.1  christos 					ISC_LIST_APPEND(fname->list,
   1932   1.1  christos 							sigrdataset, link);
   1933   1.1  christos 					sigrdataset =
   1934   1.3  christos 						ns_client_newrdataset(client);
   1935   1.1  christos 				}
   1936   1.3  christos 				rdataset = ns_client_newrdataset(client);
   1937   1.3  christos 				if (rdataset == NULL) {
   1938   1.1  christos 					goto addname;
   1939   1.3  christos 				}
   1940   1.3  christos 				if (WANTDNSSEC(client) && sigrdataset == NULL) {
   1941   1.1  christos 					goto addname;
   1942   1.3  christos 				}
   1943   1.1  christos 			} else {
   1944   1.1  christos 				dns_rdataset_disassociate(rdataset);
   1945   1.1  christos 				if (sigrdataset != NULL &&
   1946   1.9  christos 				    dns_rdataset_isassociated(sigrdataset)) {
   1947   1.1  christos 					dns_rdataset_disassociate(sigrdataset);
   1948   1.3  christos 				}
   1949   1.1  christos 			}
   1950   1.1  christos 		}
   1951   1.9  christos 	aaaa_lookup:
   1952   1.1  christos 		if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
   1953   1.3  christos 		{
   1954   1.1  christos 			goto addname;
   1955   1.3  christos 		}
   1956   1.1  christos 		result = dns_db_findrdataset(db, node, version,
   1957   1.9  christos 					     dns_rdatatype_aaaa, 0, client->now,
   1958   1.1  christos 					     rdataset, sigrdataset);
   1959   1.1  christos 		if (result == DNS_R_NCACHENXDOMAIN) {
   1960   1.1  christos 			goto addname;
   1961   1.1  christos 		} else if (result == DNS_R_NCACHENXRRSET) {
   1962   1.1  christos 			dns_rdataset_disassociate(rdataset);
   1963   1.1  christos 			if (sigrdataset != NULL &&
   1964   1.9  christos 			    dns_rdataset_isassociated(sigrdataset)) {
   1965   1.1  christos 				dns_rdataset_disassociate(sigrdataset);
   1966   1.3  christos 			}
   1967   1.1  christos 		} else if (result == ISC_R_SUCCESS) {
   1968   1.3  christos 			bool invalid = false;
   1969   1.1  christos 			mname = NULL;
   1970   1.3  christos 
   1971   1.1  christos 			if (additionaltype ==
   1972   1.9  christos 				    dns_rdatasetadditional_fromcache &&
   1973   1.1  christos 			    (DNS_TRUST_PENDING(rdataset->trust) ||
   1974   1.1  christos 			     DNS_TRUST_GLUE(rdataset->trust)))
   1975   1.1  christos 			{
   1976   1.1  christos 				/* validate() may change rdataset->trust */
   1977   1.9  christos 				invalid = !validate(client, db, fname, rdataset,
   1978   1.9  christos 						    sigrdataset);
   1979   1.1  christos 			}
   1980   1.1  christos 
   1981   1.1  christos 			if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
   1982   1.1  christos 				dns_rdataset_disassociate(rdataset);
   1983   1.1  christos 				if (sigrdataset != NULL &&
   1984   1.9  christos 				    dns_rdataset_isassociated(sigrdataset)) {
   1985   1.1  christos 					dns_rdataset_disassociate(sigrdataset);
   1986   1.3  christos 				}
   1987   1.1  christos 			} else if (!query_isduplicate(client, fname,
   1988   1.9  christos 						      dns_rdatatype_aaaa,
   1989   1.9  christos 						      &mname)) {
   1990   1.1  christos 				if (mname != fname) {
   1991   1.1  christos 					if (mname != NULL) {
   1992   1.3  christos 						ns_client_releasename(client,
   1993   1.3  christos 								      &fname);
   1994   1.1  christos 						fname = mname;
   1995   1.3  christos 					} else {
   1996   1.3  christos 						need_addname = true;
   1997   1.3  christos 					}
   1998   1.1  christos 				}
   1999   1.1  christos 				ISC_LIST_APPEND(fname->list, rdataset, link);
   2000   1.3  christos 				added_something = true;
   2001   1.1  christos 				if (sigrdataset != NULL &&
   2002   1.9  christos 				    dns_rdataset_isassociated(sigrdataset)) {
   2003   1.1  christos 					ISC_LIST_APPEND(fname->list,
   2004   1.1  christos 							sigrdataset, link);
   2005   1.1  christos 					sigrdataset = NULL;
   2006   1.1  christos 				}
   2007   1.1  christos 				rdataset = NULL;
   2008   1.1  christos 			}
   2009   1.1  christos 		}
   2010   1.1  christos 	}
   2011   1.1  christos 
   2012   1.9  christos addname:
   2013   1.3  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: addname");
   2014   1.1  christos 	/*
   2015   1.1  christos 	 * If we haven't added anything, then we're done.
   2016   1.1  christos 	 */
   2017   1.3  christos 	if (!added_something) {
   2018   1.1  christos 		goto cleanup;
   2019   1.3  christos 	}
   2020   1.1  christos 
   2021   1.1  christos 	/*
   2022   1.1  christos 	 * We may have added our rdatasets to an existing name, if so, then
   2023   1.3  christos 	 * need_addname will be false.  Whether we used an existing name
   2024   1.1  christos 	 * or a new one, we must set fname to NULL to prevent cleanup.
   2025   1.1  christos 	 */
   2026   1.3  christos 	if (need_addname) {
   2027   1.1  christos 		dns_message_addname(client->message, fname,
   2028   1.1  christos 				    DNS_SECTION_ADDITIONAL);
   2029   1.3  christos 	}
   2030   1.1  christos 	fname = NULL;
   2031   1.1  christos 
   2032   1.1  christos 	/*
   2033   1.1  christos 	 * In a few cases, we want to add additional data for additional
   2034   1.1  christos 	 * data.  It's simpler to just deal with special cases here than
   2035   1.1  christos 	 * to try to create a general purpose mechanism and allow the
   2036   1.1  christos 	 * rdata implementations to do it themselves.
   2037   1.1  christos 	 *
   2038   1.1  christos 	 * This involves recursion, but the depth is limited.  The
   2039   1.1  christos 	 * most complex case is adding a SRV rdataset, which involves
   2040   1.1  christos 	 * recursing to add address records, which in turn can cause
   2041   1.1  christos 	 * recursion to add KEYs.
   2042   1.1  christos 	 */
   2043   1.1  christos 	if (type == dns_rdatatype_srv && trdataset != NULL) {
   2044   1.1  christos 		/*
   2045   1.1  christos 		 * If we're adding SRV records to the additional data
   2046   1.1  christos 		 * section, it's helpful if we add the SRV additional data
   2047   1.1  christos 		 * as well.
   2048   1.1  christos 		 */
   2049   1.9  christos 		eresult = dns_rdataset_additionaldata(
   2050   1.9  christos 			trdataset, query_additional_cb, qctx);
   2051   1.1  christos 	}
   2052   1.1  christos 
   2053   1.9  christos cleanup:
   2054   1.3  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: cleanup");
   2055   1.3  christos 	ns_client_putrdataset(client, &rdataset);
   2056   1.3  christos 	if (sigrdataset != NULL) {
   2057   1.3  christos 		ns_client_putrdataset(client, &sigrdataset);
   2058   1.3  christos 	}
   2059   1.3  christos 	if (fname != NULL) {
   2060   1.3  christos 		ns_client_releasename(client, &fname);
   2061   1.3  christos 	}
   2062   1.3  christos 	if (node != NULL) {
   2063   1.1  christos 		dns_db_detachnode(db, &node);
   2064   1.3  christos 	}
   2065   1.3  christos 	if (db != NULL) {
   2066   1.1  christos 		dns_db_detach(&db);
   2067   1.3  christos 	}
   2068   1.1  christos 
   2069   1.3  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: done");
   2070   1.1  christos 	return (eresult);
   2071   1.1  christos }
   2072   1.1  christos 
   2073   1.3  christos /*
   2074   1.3  christos  * Add 'rdataset' to 'name'.
   2075   1.3  christos  */
   2076   1.3  christos static inline void
   2077   1.3  christos query_addtoname(dns_name_t *name, dns_rdataset_t *rdataset) {
   2078   1.3  christos 	ISC_LIST_APPEND(name->list, rdataset, link);
   2079   1.3  christos }
   2080   1.3  christos 
   2081   1.3  christos /*
   2082   1.3  christos  * Set the ordering for 'rdataset'.
   2083   1.3  christos  */
   2084   1.1  christos static void
   2085   1.3  christos query_setorder(query_ctx_t *qctx, dns_name_t *name, dns_rdataset_t *rdataset) {
   2086   1.3  christos 	ns_client_t *client = qctx->client;
   2087   1.3  christos 	dns_order_t *order = client->view->order;
   2088   1.1  christos 
   2089   1.3  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_setorder");
   2090   1.1  christos 
   2091   1.3  christos 	UNUSED(client);
   2092   1.1  christos 
   2093   1.3  christos 	if (order != NULL) {
   2094   1.9  christos 		rdataset->attributes |= dns_order_find(
   2095   1.9  christos 			order, name, rdataset->type, rdataset->rdclass);
   2096   1.3  christos 	}
   2097   1.1  christos 	rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
   2098   1.9  christos }
   2099   1.3  christos 
   2100   1.3  christos /*
   2101   1.3  christos  * Handle glue and fetch any other needed additional data for 'rdataset'.
   2102   1.3  christos  */
   2103   1.3  christos static void
   2104   1.3  christos query_additional(query_ctx_t *qctx, dns_rdataset_t *rdataset) {
   2105   1.3  christos 	ns_client_t *client = qctx->client;
   2106   1.3  christos 	isc_result_t result;
   2107   1.3  christos 
   2108   1.3  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_additional");
   2109   1.1  christos 
   2110   1.3  christos 	if (NOADDITIONAL(client)) {
   2111   1.1  christos 		return;
   2112   1.3  christos 	}
   2113   1.1  christos 
   2114   1.1  christos 	/*
   2115   1.1  christos 	 * Try to process glue directly.
   2116   1.1  christos 	 */
   2117   1.3  christos 	if (qctx->view->use_glue_cache &&
   2118   1.1  christos 	    (rdataset->type == dns_rdatatype_ns) &&
   2119   1.1  christos 	    (client->query.gluedb != NULL) &&
   2120   1.1  christos 	    dns_db_iszone(client->query.gluedb))
   2121   1.1  christos 	{
   2122   1.1  christos 		ns_dbversion_t *dbversion;
   2123   1.1  christos 
   2124   1.3  christos 		dbversion = ns_client_findversion(client, client->query.gluedb);
   2125   1.3  christos 		if (dbversion == NULL) {
   2126   1.1  christos 			goto regular;
   2127   1.1  christos 		}
   2128   1.1  christos 
   2129   1.1  christos 		result = dns_rdataset_addglue(rdataset, dbversion->version,
   2130   1.3  christos 					      client->message);
   2131   1.3  christos 		if (result == ISC_R_SUCCESS) {
   2132   1.1  christos 			return;
   2133   1.3  christos 		}
   2134   1.1  christos 	}
   2135   1.1  christos 
   2136   1.9  christos regular:
   2137   1.1  christos 	/*
   2138   1.3  christos 	 * Add other additional data if needed.
   2139   1.1  christos 	 * We don't care if dns_rdataset_additionaldata() fails.
   2140   1.1  christos 	 */
   2141   1.3  christos 	(void)dns_rdataset_additionaldata(rdataset, query_additional_cb, qctx);
   2142   1.3  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_additional: done");
   2143   1.1  christos }
   2144   1.1  christos 
   2145   1.1  christos static void
   2146   1.3  christos query_addrrset(query_ctx_t *qctx, dns_name_t **namep,
   2147   1.1  christos 	       dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
   2148   1.9  christos 	       isc_buffer_t *dbuf, dns_section_t section) {
   2149   1.3  christos 	isc_result_t result;
   2150   1.3  christos 	ns_client_t *client = qctx->client;
   2151   1.1  christos 	dns_name_t *name = *namep, *mname = NULL;
   2152   1.1  christos 	dns_rdataset_t *rdataset = *rdatasetp, *mrdataset = NULL;
   2153   1.1  christos 	dns_rdataset_t *sigrdataset = NULL;
   2154   1.1  christos 
   2155   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addrrset");
   2156   1.1  christos 
   2157   1.3  christos 	REQUIRE(name != NULL);
   2158   1.3  christos 
   2159   1.3  christos 	if (sigrdatasetp != NULL) {
   2160   1.1  christos 		sigrdataset = *sigrdatasetp;
   2161   1.3  christos 	}
   2162   1.1  christos 
   2163   1.1  christos 	/*%
   2164   1.1  christos 	 * To the current response for 'client', add the answer RRset
   2165   1.1  christos 	 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
   2166   1.1  christos 	 * owner name '*namep', to section 'section', unless they are
   2167   1.1  christos 	 * already there.  Also add any pertinent additional data.
   2168   1.1  christos 	 *
   2169   1.1  christos 	 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
   2170   1.1  christos 	 * stored in 'dbuf'.  In this case, query_addrrset() guarantees that
   2171   1.1  christos 	 * when it returns the name will either have been kept or released.
   2172   1.1  christos 	 */
   2173   1.9  christos 	result = dns_message_findname(client->message, section, name,
   2174   1.9  christos 				      rdataset->type, rdataset->covers, &mname,
   2175   1.9  christos 				      &mrdataset);
   2176   1.1  christos 	if (result == ISC_R_SUCCESS) {
   2177   1.1  christos 		/*
   2178   1.1  christos 		 * We've already got an RRset of the given name and type.
   2179   1.1  christos 		 */
   2180   1.9  christos 		CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: dns_message_findname "
   2181   1.9  christos 					 "succeeded: done");
   2182   1.3  christos 		if (dbuf != NULL) {
   2183   1.3  christos 			ns_client_releasename(client, namep);
   2184   1.3  christos 		}
   2185   1.3  christos 		if ((rdataset->attributes & DNS_RDATASETATTR_REQUIRED) != 0) {
   2186   1.1  christos 			mrdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
   2187   1.3  christos 		}
   2188   1.1  christos 		return;
   2189   1.1  christos 	} else if (result == DNS_R_NXDOMAIN) {
   2190   1.1  christos 		/*
   2191   1.1  christos 		 * The name doesn't exist.
   2192   1.1  christos 		 */
   2193   1.3  christos 		if (dbuf != NULL) {
   2194   1.3  christos 			ns_client_keepname(client, name, dbuf);
   2195   1.3  christos 		}
   2196   1.1  christos 		dns_message_addname(client->message, name, section);
   2197   1.1  christos 		*namep = NULL;
   2198   1.1  christos 		mname = name;
   2199   1.1  christos 	} else {
   2200   1.1  christos 		RUNTIME_CHECK(result == DNS_R_NXRRSET);
   2201   1.3  christos 		if (dbuf != NULL) {
   2202   1.3  christos 			ns_client_releasename(client, namep);
   2203   1.3  christos 		}
   2204   1.1  christos 	}
   2205   1.1  christos 
   2206   1.1  christos 	if (rdataset->trust != dns_trust_secure &&
   2207   1.9  christos 	    (section == DNS_SECTION_ANSWER || section == DNS_SECTION_AUTHORITY))
   2208   1.3  christos 	{
   2209   1.1  christos 		client->query.attributes &= ~NS_QUERYATTR_SECURE;
   2210   1.3  christos 	}
   2211   1.3  christos 
   2212   1.3  christos 	/*
   2213   1.3  christos 	 * Update message name, set rdataset order, and do additional
   2214   1.3  christos 	 * section processing if needed.
   2215   1.3  christos 	 */
   2216   1.3  christos 	query_addtoname(mname, rdataset);
   2217   1.3  christos 	query_setorder(qctx, mname, rdataset);
   2218   1.3  christos 	query_additional(qctx, rdataset);
   2219   1.1  christos 
   2220   1.1  christos 	/*
   2221   1.1  christos 	 * Note: we only add SIGs if we've added the type they cover, so
   2222   1.1  christos 	 * we do not need to check if the SIG rdataset is already in the
   2223   1.1  christos 	 * response.
   2224   1.1  christos 	 */
   2225   1.1  christos 	*rdatasetp = NULL;
   2226   1.1  christos 	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
   2227   1.1  christos 		/*
   2228   1.1  christos 		 * We have a signature.  Add it to the response.
   2229   1.1  christos 		 */
   2230   1.1  christos 		ISC_LIST_APPEND(mname->list, sigrdataset, link);
   2231   1.1  christos 		*sigrdatasetp = NULL;
   2232   1.1  christos 	}
   2233   1.1  christos 
   2234   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: done");
   2235   1.1  christos }
   2236   1.1  christos 
   2237   1.1  christos /*
   2238   1.1  christos  * Mark the RRsets as secure.  Update the cache (db) to reflect the
   2239   1.1  christos  * change in trust level.
   2240   1.1  christos  */
   2241   1.1  christos static void
   2242   1.1  christos mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
   2243   1.1  christos 	    dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset,
   2244   1.9  christos 	    dns_rdataset_t *sigrdataset) {
   2245   1.1  christos 	isc_result_t result;
   2246   1.1  christos 	dns_dbnode_t *node = NULL;
   2247   1.1  christos 	dns_clientinfomethods_t cm;
   2248   1.1  christos 	dns_clientinfo_t ci;
   2249   1.1  christos 	isc_stdtime_t now;
   2250   1.1  christos 
   2251   1.1  christos 	rdataset->trust = dns_trust_secure;
   2252   1.1  christos 	sigrdataset->trust = dns_trust_secure;
   2253   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   2254   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   2255   1.1  christos 
   2256   1.1  christos 	/*
   2257   1.1  christos 	 * Save the updated secure state.  Ignore failures.
   2258   1.1  christos 	 */
   2259   1.3  christos 	result = dns_db_findnodeext(db, name, true, &cm, &ci, &node);
   2260   1.9  christos 	if (result != ISC_R_SUCCESS) {
   2261   1.1  christos 		return;
   2262   1.9  christos 	}
   2263   1.1  christos 
   2264   1.1  christos 	isc_stdtime_get(&now);
   2265   1.1  christos 	dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now,
   2266   1.1  christos 			     client->view->acceptexpired);
   2267   1.1  christos 
   2268   1.9  christos 	(void)dns_db_addrdataset(db, node, NULL, client->now, rdataset, 0,
   2269   1.9  christos 				 NULL);
   2270   1.9  christos 	(void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset, 0,
   2271   1.9  christos 				 NULL);
   2272   1.1  christos 	dns_db_detachnode(db, &node);
   2273   1.1  christos }
   2274   1.1  christos 
   2275   1.1  christos /*
   2276   1.1  christos  * Find the secure key that corresponds to rrsig.
   2277   1.1  christos  * Note: 'keyrdataset' maintains state between successive calls,
   2278   1.1  christos  * there may be multiple keys with the same keyid.
   2279   1.3  christos  * Return false if we have exhausted all the possible keys.
   2280   1.1  christos  */
   2281   1.3  christos static bool
   2282   1.1  christos get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
   2283   1.9  christos 	dns_rdataset_t *keyrdataset, dst_key_t **keyp) {
   2284   1.1  christos 	isc_result_t result;
   2285   1.1  christos 	dns_dbnode_t *node = NULL;
   2286   1.3  christos 	bool secure = false;
   2287   1.1  christos 	dns_clientinfomethods_t cm;
   2288   1.1  christos 	dns_clientinfo_t ci;
   2289   1.1  christos 
   2290   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   2291   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   2292   1.1  christos 
   2293   1.1  christos 	if (!dns_rdataset_isassociated(keyrdataset)) {
   2294   1.9  christos 		result = dns_db_findnodeext(db, &rrsig->signer, false, &cm, &ci,
   2295   1.9  christos 					    &node);
   2296   1.9  christos 		if (result != ISC_R_SUCCESS) {
   2297   1.3  christos 			return (false);
   2298   1.9  christos 		}
   2299   1.1  christos 
   2300   1.1  christos 		result = dns_db_findrdataset(db, node, NULL,
   2301   1.1  christos 					     dns_rdatatype_dnskey, 0,
   2302   1.1  christos 					     client->now, keyrdataset, NULL);
   2303   1.1  christos 		dns_db_detachnode(db, &node);
   2304   1.9  christos 		if (result != ISC_R_SUCCESS) {
   2305   1.3  christos 			return (false);
   2306   1.9  christos 		}
   2307   1.1  christos 
   2308   1.9  christos 		if (keyrdataset->trust != dns_trust_secure) {
   2309   1.3  christos 			return (false);
   2310   1.9  christos 		}
   2311   1.1  christos 
   2312   1.1  christos 		result = dns_rdataset_first(keyrdataset);
   2313   1.9  christos 	} else {
   2314   1.1  christos 		result = dns_rdataset_next(keyrdataset);
   2315   1.9  christos 	}
   2316   1.1  christos 
   2317   1.9  christos 	for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset))
   2318   1.9  christos 	{
   2319   1.1  christos 		dns_rdata_t rdata = DNS_RDATA_INIT;
   2320   1.1  christos 		isc_buffer_t b;
   2321   1.1  christos 
   2322   1.1  christos 		dns_rdataset_current(keyrdataset, &rdata);
   2323   1.1  christos 		isc_buffer_init(&b, rdata.data, rdata.length);
   2324   1.1  christos 		isc_buffer_add(&b, rdata.length);
   2325   1.1  christos 		result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
   2326   1.1  christos 					 client->mctx, keyp);
   2327   1.9  christos 		if (result != ISC_R_SUCCESS) {
   2328   1.1  christos 			continue;
   2329   1.9  christos 		}
   2330   1.1  christos 		if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
   2331   1.1  christos 		    rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
   2332   1.9  christos 		    dst_key_iszonekey(*keyp))
   2333   1.9  christos 		{
   2334   1.3  christos 			secure = true;
   2335   1.1  christos 			break;
   2336   1.1  christos 		}
   2337   1.1  christos 		dst_key_free(keyp);
   2338   1.1  christos 	}
   2339   1.1  christos 	return (secure);
   2340   1.1  christos }
   2341   1.1  christos 
   2342   1.3  christos static bool
   2343   1.1  christos verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,
   2344   1.9  christos        dns_rdata_t *rdata, ns_client_t *client) {
   2345   1.1  christos 	isc_result_t result;
   2346   1.1  christos 	dns_fixedname_t fixed;
   2347   1.3  christos 	bool ignore = false;
   2348   1.1  christos 
   2349   1.1  christos 	dns_fixedname_init(&fixed);
   2350   1.1  christos 
   2351   1.1  christos again:
   2352   1.3  christos 	result = dns_dnssec_verify(name, rdataset, key, ignore,
   2353   1.9  christos 				   client->view->maxbits, client->mctx, rdata,
   2354   1.9  christos 				   NULL);
   2355   1.1  christos 	if (result == DNS_R_SIGEXPIRED && client->view->acceptexpired) {
   2356   1.3  christos 		ignore = true;
   2357   1.1  christos 		goto again;
   2358   1.1  christos 	}
   2359   1.9  christos 	if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
   2360   1.3  christos 		return (true);
   2361   1.9  christos 	}
   2362   1.3  christos 	return (false);
   2363   1.1  christos }
   2364   1.1  christos 
   2365   1.1  christos /*
   2366   1.1  christos  * Validate the rdataset if possible with available records.
   2367   1.1  christos  */
   2368   1.3  christos static bool
   2369   1.1  christos validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
   2370   1.9  christos 	 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
   2371   1.1  christos 	isc_result_t result;
   2372   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   2373   1.1  christos 	dns_rdata_rrsig_t rrsig;
   2374   1.1  christos 	dst_key_t *key = NULL;
   2375   1.1  christos 	dns_rdataset_t keyrdataset;
   2376   1.1  christos 
   2377   1.9  christos 	if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)) {
   2378   1.3  christos 		return (false);
   2379   1.9  christos 	}
   2380   1.1  christos 
   2381   1.9  christos 	for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS;
   2382   1.9  christos 	     result = dns_rdataset_next(sigrdataset))
   2383   1.9  christos 	{
   2384   1.1  christos 		dns_rdata_reset(&rdata);
   2385   1.1  christos 		dns_rdataset_current(sigrdataset, &rdata);
   2386   1.1  christos 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   2387   1.3  christos 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   2388   1.1  christos 		if (!dns_resolver_algorithm_supported(client->view->resolver,
   2389   1.1  christos 						      name, rrsig.algorithm))
   2390   1.9  christos 		{
   2391   1.1  christos 			continue;
   2392   1.9  christos 		}
   2393   1.9  christos 		if (!dns_name_issubdomain(name, &rrsig.signer)) {
   2394   1.1  christos 			continue;
   2395   1.9  christos 		}
   2396   1.1  christos 		dns_rdataset_init(&keyrdataset);
   2397   1.1  christos 		do {
   2398   1.9  christos 			if (!get_key(client, db, &rrsig, &keyrdataset, &key)) {
   2399   1.1  christos 				break;
   2400   1.9  christos 			}
   2401   1.1  christos 			if (verify(key, name, rdataset, &rdata, client)) {
   2402   1.1  christos 				dst_key_free(&key);
   2403   1.1  christos 				dns_rdataset_disassociate(&keyrdataset);
   2404   1.9  christos 				mark_secure(client, db, name, &rrsig, rdataset,
   2405   1.9  christos 					    sigrdataset);
   2406   1.3  christos 				return (true);
   2407   1.1  christos 			}
   2408   1.1  christos 			dst_key_free(&key);
   2409   1.1  christos 		} while (1);
   2410   1.9  christos 		if (dns_rdataset_isassociated(&keyrdataset)) {
   2411   1.1  christos 			dns_rdataset_disassociate(&keyrdataset);
   2412   1.9  christos 		}
   2413   1.1  christos 	}
   2414   1.3  christos 	return (false);
   2415   1.1  christos }
   2416   1.1  christos 
   2417   1.1  christos static void
   2418   1.1  christos fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) {
   2419   1.9  christos 	if (*rdataset == NULL) {
   2420   1.3  christos 		*rdataset = ns_client_newrdataset(client);
   2421   1.9  christos 	} else if (dns_rdataset_isassociated(*rdataset)) {
   2422   1.1  christos 		dns_rdataset_disassociate(*rdataset);
   2423   1.9  christos 	}
   2424   1.1  christos }
   2425   1.1  christos 
   2426   1.1  christos static void
   2427   1.1  christos fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf,
   2428   1.9  christos 	 isc_buffer_t *nbuf) {
   2429   1.1  christos 	if (*fname == NULL) {
   2430   1.3  christos 		*dbuf = ns_client_getnamebuf(client);
   2431   1.9  christos 		if (*dbuf == NULL) {
   2432   1.1  christos 			return;
   2433   1.9  christos 		}
   2434   1.3  christos 		*fname = ns_client_newname(client, *dbuf, nbuf);
   2435   1.1  christos 	}
   2436   1.1  christos }
   2437   1.1  christos 
   2438   1.1  christos static void
   2439   1.1  christos free_devent(ns_client_t *client, isc_event_t **eventp,
   2440   1.9  christos 	    dns_fetchevent_t **deventp) {
   2441   1.1  christos 	dns_fetchevent_t *devent = *deventp;
   2442   1.1  christos 
   2443   1.9  christos 	REQUIRE((void *)(*eventp) == (void *)(*deventp));
   2444   1.9  christos 
   2445   1.9  christos 	CTRACE(ISC_LOG_DEBUG(3), "free_devent");
   2446   1.1  christos 
   2447   1.3  christos 	if (devent->fetch != NULL) {
   2448   1.1  christos 		dns_resolver_destroyfetch(&devent->fetch);
   2449   1.3  christos 	}
   2450   1.3  christos 	if (devent->node != NULL) {
   2451   1.1  christos 		dns_db_detachnode(devent->db, &devent->node);
   2452   1.3  christos 	}
   2453   1.3  christos 	if (devent->db != NULL) {
   2454   1.1  christos 		dns_db_detach(&devent->db);
   2455   1.3  christos 	}
   2456   1.3  christos 	if (devent->rdataset != NULL) {
   2457   1.3  christos 		ns_client_putrdataset(client, &devent->rdataset);
   2458   1.3  christos 	}
   2459   1.3  christos 	if (devent->sigrdataset != NULL) {
   2460   1.3  christos 		ns_client_putrdataset(client, &devent->sigrdataset);
   2461   1.3  christos 	}
   2462   1.9  christos 
   2463   1.1  christos 	/*
   2464   1.1  christos 	 * If the two pointers are the same then leave the setting of
   2465   1.1  christos 	 * (*deventp) to NULL to isc_event_free.
   2466   1.1  christos 	 */
   2467   1.9  christos 	if ((void *)eventp != (void *)deventp) {
   2468   1.1  christos 		(*deventp) = NULL;
   2469   1.9  christos 	}
   2470   1.1  christos 	isc_event_free(eventp);
   2471   1.1  christos }
   2472   1.1  christos 
   2473   1.1  christos static void
   2474   1.1  christos prefetch_done(isc_task_t *task, isc_event_t *event) {
   2475   1.1  christos 	dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
   2476   1.1  christos 	ns_client_t *client;
   2477   1.1  christos 
   2478   1.1  christos 	UNUSED(task);
   2479   1.1  christos 
   2480   1.1  christos 	REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
   2481   1.1  christos 	client = devent->ev_arg;
   2482   1.1  christos 	REQUIRE(NS_CLIENT_VALID(client));
   2483   1.1  christos 	REQUIRE(task == client->task);
   2484   1.1  christos 
   2485   1.9  christos 	CTRACE(ISC_LOG_DEBUG(3), "prefetch_done");
   2486   1.9  christos 
   2487   1.1  christos 	LOCK(&client->query.fetchlock);
   2488   1.1  christos 	if (client->query.prefetch != NULL) {
   2489   1.1  christos 		INSIST(devent->fetch == client->query.prefetch);
   2490   1.1  christos 		client->query.prefetch = NULL;
   2491   1.1  christos 	}
   2492   1.1  christos 	UNLOCK(&client->query.fetchlock);
   2493   1.9  christos 
   2494   1.9  christos 	/*
   2495   1.9  christos 	 * We're done prefetching, detach from quota.
   2496   1.9  christos 	 */
   2497   1.9  christos 	if (client->recursionquota != NULL) {
   2498   1.9  christos 		isc_quota_detach(&client->recursionquota);
   2499   1.9  christos 	}
   2500   1.9  christos 
   2501   1.1  christos 	free_devent(client, &event, &devent);
   2502  1.11  christos 	isc_nmhandle_detach(&client->prefetchhandle);
   2503   1.1  christos }
   2504   1.1  christos 
   2505   1.1  christos static void
   2506   1.1  christos query_prefetch(ns_client_t *client, dns_name_t *qname,
   2507   1.9  christos 	       dns_rdataset_t *rdataset) {
   2508   1.1  christos 	isc_result_t result;
   2509   1.1  christos 	isc_sockaddr_t *peeraddr;
   2510   1.1  christos 	dns_rdataset_t *tmprdataset;
   2511   1.1  christos 	unsigned int options;
   2512   1.1  christos 
   2513   1.9  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_prefetch");
   2514   1.9  christos 
   2515   1.1  christos 	if (client->query.prefetch != NULL ||
   2516   1.1  christos 	    client->view->prefetch_trigger == 0U ||
   2517   1.1  christos 	    rdataset->ttl > client->view->prefetch_trigger ||
   2518   1.1  christos 	    (rdataset->attributes & DNS_RDATASETATTR_PREFETCH) == 0)
   2519   1.9  christos 	{
   2520   1.1  christos 		return;
   2521   1.9  christos 	}
   2522   1.1  christos 
   2523   1.1  christos 	if (client->recursionquota == NULL) {
   2524   1.1  christos 		result = isc_quota_attach(&client->sctx->recursionquota,
   2525   1.1  christos 					  &client->recursionquota);
   2526   1.9  christos 		if (result == ISC_R_SOFTQUOTA) {
   2527   1.9  christos 			isc_quota_detach(&client->recursionquota);
   2528   1.6  christos 		}
   2529   1.6  christos 		if (result != ISC_R_SUCCESS) {
   2530   1.1  christos 			return;
   2531   1.6  christos 		}
   2532   1.1  christos 	}
   2533   1.1  christos 
   2534   1.3  christos 	tmprdataset = ns_client_newrdataset(client);
   2535   1.9  christos 	if (tmprdataset == NULL) {
   2536   1.1  christos 		return;
   2537   1.9  christos 	}
   2538   1.9  christos 
   2539   1.9  christos 	if (!TCP(client)) {
   2540   1.1  christos 		peeraddr = &client->peeraddr;
   2541   1.9  christos 	} else {
   2542   1.1  christos 		peeraddr = NULL;
   2543   1.9  christos 	}
   2544   1.9  christos 
   2545  1.11  christos 	isc_nmhandle_attach(client->handle, &client->prefetchhandle);
   2546   1.1  christos 	options = client->query.fetchoptions | DNS_FETCHOPT_PREFETCH;
   2547   1.9  christos 	result = dns_resolver_createfetch(
   2548   1.9  christos 		client->view->resolver, qname, rdataset->type, NULL, NULL, NULL,
   2549   1.9  christos 		peeraddr, client->message->id, options, 0, NULL, client->task,
   2550   1.9  christos 		prefetch_done, client, tmprdataset, NULL,
   2551   1.9  christos 		&client->query.prefetch);
   2552   1.1  christos 	if (result != ISC_R_SUCCESS) {
   2553   1.3  christos 		ns_client_putrdataset(client, &tmprdataset);
   2554  1.11  christos 		isc_nmhandle_detach(&client->prefetchhandle);
   2555   1.1  christos 	}
   2556   1.9  christos 
   2557   1.1  christos 	dns_rdataset_clearprefetch(rdataset);
   2558   1.9  christos 	ns_stats_increment(client->sctx->nsstats, ns_statscounter_prefetch);
   2559   1.1  christos }
   2560   1.1  christos 
   2561   1.1  christos static inline void
   2562   1.1  christos rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
   2563   1.9  christos 	  dns_rdataset_t **rdatasetp) {
   2564   1.1  christos 	if (nodep != NULL && *nodep != NULL) {
   2565   1.1  christos 		REQUIRE(dbp != NULL && *dbp != NULL);
   2566   1.1  christos 		dns_db_detachnode(*dbp, nodep);
   2567   1.1  christos 	}
   2568   1.9  christos 	if (dbp != NULL && *dbp != NULL) {
   2569   1.1  christos 		dns_db_detach(dbp);
   2570   1.9  christos 	}
   2571   1.9  christos 	if (zonep != NULL && *zonep != NULL) {
   2572   1.1  christos 		dns_zone_detach(zonep);
   2573   1.9  christos 	}
   2574   1.1  christos 	if (rdatasetp != NULL && *rdatasetp != NULL &&
   2575   1.1  christos 	    dns_rdataset_isassociated(*rdatasetp))
   2576   1.9  christos 	{
   2577   1.1  christos 		dns_rdataset_disassociate(*rdatasetp);
   2578   1.9  christos 	}
   2579   1.1  christos }
   2580   1.1  christos 
   2581   1.1  christos static inline void
   2582   1.1  christos rpz_match_clear(dns_rpz_st_t *st) {
   2583   1.1  christos 	rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
   2584   1.1  christos 	st->m.version = NULL;
   2585   1.1  christos }
   2586   1.1  christos 
   2587   1.1  christos static inline isc_result_t
   2588   1.1  christos rpz_ready(ns_client_t *client, dns_rdataset_t **rdatasetp) {
   2589   1.1  christos 	REQUIRE(rdatasetp != NULL);
   2590   1.1  christos 
   2591   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_ready");
   2592   1.1  christos 
   2593   1.1  christos 	if (*rdatasetp == NULL) {
   2594   1.3  christos 		*rdatasetp = ns_client_newrdataset(client);
   2595   1.1  christos 		if (*rdatasetp == NULL) {
   2596   1.9  christos 			CTRACE(ISC_LOG_ERROR, "rpz_ready: "
   2597   1.9  christos 					      "ns_client_newrdataset failed");
   2598   1.1  christos 			return (DNS_R_SERVFAIL);
   2599   1.1  christos 		}
   2600   1.1  christos 	} else if (dns_rdataset_isassociated(*rdatasetp)) {
   2601   1.1  christos 		dns_rdataset_disassociate(*rdatasetp);
   2602   1.1  christos 	}
   2603   1.1  christos 	return (ISC_R_SUCCESS);
   2604   1.1  christos }
   2605   1.1  christos 
   2606   1.1  christos static void
   2607   1.1  christos rpz_st_clear(ns_client_t *client) {
   2608   1.1  christos 	dns_rpz_st_t *st = client->query.rpz_st;
   2609   1.1  christos 
   2610   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_st_clear");
   2611   1.1  christos 
   2612   1.1  christos 	if (st->m.rdataset != NULL) {
   2613   1.3  christos 		ns_client_putrdataset(client, &st->m.rdataset);
   2614   1.1  christos 	}
   2615   1.1  christos 	rpz_match_clear(st);
   2616   1.1  christos 
   2617   1.1  christos 	rpz_clean(NULL, &st->r.db, NULL, NULL);
   2618   1.1  christos 	if (st->r.ns_rdataset != NULL) {
   2619   1.3  christos 		ns_client_putrdataset(client, &st->r.ns_rdataset);
   2620   1.1  christos 	}
   2621   1.1  christos 	if (st->r.r_rdataset != NULL) {
   2622   1.3  christos 		ns_client_putrdataset(client, &st->r.r_rdataset);
   2623   1.1  christos 	}
   2624   1.1  christos 
   2625   1.1  christos 	rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL);
   2626   1.1  christos 	if (st->q.rdataset != NULL) {
   2627   1.3  christos 		ns_client_putrdataset(client, &st->q.rdataset);
   2628   1.1  christos 	}
   2629   1.1  christos 	if (st->q.sigrdataset != NULL) {
   2630   1.3  christos 		ns_client_putrdataset(client, &st->q.sigrdataset);
   2631   1.1  christos 	}
   2632   1.1  christos 	st->state = 0;
   2633   1.1  christos 	st->m.type = DNS_RPZ_TYPE_BAD;
   2634   1.1  christos 	st->m.policy = DNS_RPZ_POLICY_MISS;
   2635   1.1  christos 	if (st->rpsdb != NULL) {
   2636   1.1  christos 		dns_db_detach(&st->rpsdb);
   2637   1.1  christos 	}
   2638   1.1  christos }
   2639   1.1  christos 
   2640   1.1  christos static dns_rpz_zbits_t
   2641   1.9  christos rpz_get_zbits(ns_client_t *client, dns_rdatatype_t ip_type,
   2642   1.9  christos 	      dns_rpz_type_t rpz_type) {
   2643   1.1  christos 	dns_rpz_st_t *st;
   2644   1.3  christos 	dns_rpz_zbits_t zbits = 0;
   2645   1.1  christos 
   2646   1.1  christos 	REQUIRE(client != NULL);
   2647   1.1  christos 	REQUIRE(client->query.rpz_st != NULL);
   2648   1.1  christos 
   2649   1.1  christos 	st = client->query.rpz_st;
   2650   1.1  christos 
   2651   1.1  christos #ifdef USE_DNSRPS
   2652   1.1  christos 	if (st->popt.dnsrps_enabled) {
   2653   1.1  christos 		if (st->rpsdb == NULL ||
   2654   1.1  christos 		    librpz->have_trig(dns_dnsrps_type2trig(rpz_type),
   2655   1.1  christos 				      ip_type == dns_rdatatype_aaaa,
   2656   1.1  christos 				      ((rpsdb_t *)st->rpsdb)->rsp))
   2657   1.1  christos 		{
   2658   1.1  christos 			return (DNS_RPZ_ALL_ZBITS);
   2659   1.1  christos 		}
   2660   1.1  christos 		return (0);
   2661   1.1  christos 	}
   2662   1.9  christos #endif /* ifdef USE_DNSRPS */
   2663   1.1  christos 
   2664   1.1  christos 	switch (rpz_type) {
   2665   1.1  christos 	case DNS_RPZ_TYPE_CLIENT_IP:
   2666   1.1  christos 		zbits = st->have.client_ip;
   2667   1.1  christos 		break;
   2668   1.1  christos 	case DNS_RPZ_TYPE_QNAME:
   2669   1.1  christos 		zbits = st->have.qname;
   2670   1.1  christos 		break;
   2671   1.1  christos 	case DNS_RPZ_TYPE_IP:
   2672   1.1  christos 		if (ip_type == dns_rdatatype_a) {
   2673   1.1  christos 			zbits = st->have.ipv4;
   2674   1.1  christos 		} else if (ip_type == dns_rdatatype_aaaa) {
   2675   1.1  christos 			zbits = st->have.ipv6;
   2676   1.1  christos 		} else {
   2677   1.1  christos 			zbits = st->have.ip;
   2678   1.1  christos 		}
   2679   1.1  christos 		break;
   2680   1.1  christos 	case DNS_RPZ_TYPE_NSDNAME:
   2681   1.1  christos 		zbits = st->have.nsdname;
   2682   1.1  christos 		break;
   2683   1.1  christos 	case DNS_RPZ_TYPE_NSIP:
   2684   1.1  christos 		if (ip_type == dns_rdatatype_a) {
   2685   1.1  christos 			zbits = st->have.nsipv4;
   2686   1.1  christos 		} else if (ip_type == dns_rdatatype_aaaa) {
   2687   1.1  christos 			zbits = st->have.nsipv6;
   2688   1.1  christos 		} else {
   2689   1.1  christos 			zbits = st->have.nsip;
   2690   1.1  christos 		}
   2691   1.1  christos 		break;
   2692   1.1  christos 	default:
   2693   1.1  christos 		INSIST(0);
   2694   1.3  christos 		ISC_UNREACHABLE();
   2695   1.1  christos 	}
   2696   1.1  christos 
   2697   1.1  christos 	/*
   2698   1.1  christos 	 * Choose
   2699   1.1  christos 	 *	the earliest configured policy zone (rpz->num)
   2700   1.1  christos 	 *	QNAME over IP over NSDNAME over NSIP (rpz_type)
   2701   1.1  christos 	 *	the smallest name,
   2702   1.1  christos 	 *	the longest IP address prefix,
   2703   1.1  christos 	 *	the lexically smallest address.
   2704   1.1  christos 	 */
   2705   1.1  christos 	if (st->m.policy != DNS_RPZ_POLICY_MISS) {
   2706   1.1  christos 		if (st->m.type >= rpz_type) {
   2707   1.1  christos 			zbits &= DNS_RPZ_ZMASK(st->m.rpz->num);
   2708   1.9  christos 		} else {
   2709   1.1  christos 			zbits &= DNS_RPZ_ZMASK(st->m.rpz->num) >> 1;
   2710   1.1  christos 		}
   2711   1.1  christos 	}
   2712   1.1  christos 
   2713   1.1  christos 	/*
   2714   1.1  christos 	 * If the client wants recursion, allow only compatible policies.
   2715   1.1  christos 	 */
   2716   1.9  christos 	if (!RECURSIONOK(client)) {
   2717   1.1  christos 		zbits &= st->popt.no_rd_ok;
   2718   1.9  christos 	}
   2719   1.1  christos 
   2720   1.1  christos 	return (zbits);
   2721   1.1  christos }
   2722   1.1  christos 
   2723   1.1  christos static void
   2724   1.1  christos query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) {
   2725   1.1  christos 	isc_result_t result;
   2726   1.1  christos 	isc_sockaddr_t *peeraddr;
   2727   1.1  christos 	dns_rdataset_t *tmprdataset;
   2728   1.1  christos 	unsigned int options;
   2729   1.1  christos 
   2730   1.9  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_rpzfetch");
   2731   1.9  christos 
   2732   1.9  christos 	if (client->query.prefetch != NULL) {
   2733   1.1  christos 		return;
   2734   1.9  christos 	}
   2735   1.1  christos 
   2736   1.1  christos 	if (client->recursionquota == NULL) {
   2737   1.1  christos 		result = isc_quota_attach(&client->sctx->recursionquota,
   2738   1.1  christos 					  &client->recursionquota);
   2739   1.9  christos 		if (result == ISC_R_SOFTQUOTA) {
   2740   1.9  christos 			isc_quota_detach(&client->recursionquota);
   2741   1.6  christos 		}
   2742   1.6  christos 		if (result != ISC_R_SUCCESS) {
   2743   1.1  christos 			return;
   2744   1.6  christos 		}
   2745   1.1  christos 	}
   2746   1.1  christos 
   2747   1.3  christos 	tmprdataset = ns_client_newrdataset(client);
   2748   1.9  christos 	if (tmprdataset == NULL) {
   2749   1.1  christos 		return;
   2750   1.9  christos 	}
   2751   1.9  christos 
   2752   1.9  christos 	if (!TCP(client)) {
   2753   1.1  christos 		peeraddr = &client->peeraddr;
   2754   1.9  christos 	} else {
   2755   1.1  christos 		peeraddr = NULL;
   2756   1.9  christos 	}
   2757   1.9  christos 
   2758   1.1  christos 	options = client->query.fetchoptions;
   2759  1.11  christos 	isc_nmhandle_attach(client->handle, &client->prefetchhandle);
   2760   1.9  christos 	result = dns_resolver_createfetch(
   2761   1.9  christos 		client->view->resolver, qname, type, NULL, NULL, NULL, peeraddr,
   2762   1.9  christos 		client->message->id, options, 0, NULL, client->task,
   2763   1.9  christos 		prefetch_done, client, tmprdataset, NULL,
   2764   1.9  christos 		&client->query.prefetch);
   2765   1.1  christos 	if (result != ISC_R_SUCCESS) {
   2766   1.3  christos 		ns_client_putrdataset(client, &tmprdataset);
   2767  1.11  christos 		isc_nmhandle_detach(&client->prefetchhandle);
   2768   1.1  christos 	}
   2769   1.1  christos }
   2770   1.1  christos 
   2771   1.1  christos /*
   2772   1.1  christos  * Get an NS, A, or AAAA rrset related to the response for the client
   2773   1.1  christos  * to check the contents of that rrset for hits by eligible policy zones.
   2774   1.1  christos  */
   2775   1.1  christos static isc_result_t
   2776   1.1  christos rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
   2777   1.1  christos 	       dns_rpz_type_t rpz_type, dns_db_t **dbp,
   2778   1.1  christos 	       dns_dbversion_t *version, dns_rdataset_t **rdatasetp,
   2779   1.9  christos 	       bool resuming) {
   2780   1.1  christos 	dns_rpz_st_t *st;
   2781   1.3  christos 	bool is_zone;
   2782   1.1  christos 	dns_dbnode_t *node;
   2783   1.1  christos 	dns_fixedname_t fixed;
   2784   1.1  christos 	dns_name_t *found;
   2785   1.1  christos 	isc_result_t result;
   2786   1.1  christos 	dns_clientinfomethods_t cm;
   2787   1.1  christos 	dns_clientinfo_t ci;
   2788   1.1  christos 
   2789   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_rrset_find");
   2790   1.1  christos 
   2791   1.1  christos 	st = client->query.rpz_st;
   2792   1.1  christos 	if ((st->state & DNS_RPZ_RECURSING) != 0) {
   2793   1.1  christos 		INSIST(st->r.r_type == type);
   2794   1.1  christos 		INSIST(dns_name_equal(name, st->r_name));
   2795   1.1  christos 		INSIST(*rdatasetp == NULL ||
   2796   1.1  christos 		       !dns_rdataset_isassociated(*rdatasetp));
   2797   1.1  christos 		st->state &= ~DNS_RPZ_RECURSING;
   2798   1.1  christos 		RESTORE(*dbp, st->r.db);
   2799   1.3  christos 		if (*rdatasetp != NULL) {
   2800   1.3  christos 			ns_client_putrdataset(client, rdatasetp);
   2801   1.3  christos 		}
   2802   1.1  christos 		RESTORE(*rdatasetp, st->r.r_rdataset);
   2803   1.1  christos 		result = st->r.r_result;
   2804   1.1  christos 		if (result == DNS_R_DELEGATION) {
   2805   1.1  christos 			CTRACE(ISC_LOG_ERROR, "RPZ recursing");
   2806   1.1  christos 			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
   2807   1.3  christos 				     rpz_type, "rpz_rrset_find(1)", result);
   2808   1.1  christos 			st->m.policy = DNS_RPZ_POLICY_ERROR;
   2809   1.1  christos 			result = DNS_R_SERVFAIL;
   2810   1.1  christos 		}
   2811   1.1  christos 		return (result);
   2812   1.1  christos 	}
   2813   1.1  christos 
   2814   1.1  christos 	result = rpz_ready(client, rdatasetp);
   2815   1.1  christos 	if (result != ISC_R_SUCCESS) {
   2816   1.1  christos 		st->m.policy = DNS_RPZ_POLICY_ERROR;
   2817   1.1  christos 		return (result);
   2818   1.1  christos 	}
   2819   1.1  christos 	if (*dbp != NULL) {
   2820   1.3  christos 		is_zone = false;
   2821   1.1  christos 	} else {
   2822   1.1  christos 		dns_zone_t *zone;
   2823   1.1  christos 
   2824   1.1  christos 		version = NULL;
   2825   1.1  christos 		zone = NULL;
   2826   1.1  christos 		result = query_getdb(client, name, type, 0, &zone, dbp,
   2827   1.1  christos 				     &version, &is_zone);
   2828   1.1  christos 		if (result != ISC_R_SUCCESS) {
   2829   1.1  christos 			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
   2830   1.3  christos 				     rpz_type, "rpz_rrset_find(2)", result);
   2831   1.1  christos 			st->m.policy = DNS_RPZ_POLICY_ERROR;
   2832   1.9  christos 			if (zone != NULL) {
   2833   1.1  christos 				dns_zone_detach(&zone);
   2834   1.9  christos 			}
   2835   1.1  christos 			return (result);
   2836   1.1  christos 		}
   2837   1.9  christos 		if (zone != NULL) {
   2838   1.1  christos 			dns_zone_detach(&zone);
   2839   1.9  christos 		}
   2840   1.1  christos 	}
   2841   1.1  christos 
   2842   1.1  christos 	node = NULL;
   2843   1.1  christos 	found = dns_fixedname_initname(&fixed);
   2844   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   2845   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   2846   1.1  christos 	result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK,
   2847   1.9  christos 				client->now, &node, found, &cm, &ci, *rdatasetp,
   2848   1.9  christos 				NULL);
   2849   1.1  christos 	if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) {
   2850   1.1  christos 		/*
   2851   1.1  christos 		 * Try the cache if we're authoritative for an
   2852   1.1  christos 		 * ancestor but not the domain itself.
   2853   1.1  christos 		 */
   2854   1.1  christos 		rpz_clean(NULL, dbp, &node, rdatasetp);
   2855   1.1  christos 		version = NULL;
   2856   1.1  christos 		dns_db_attach(client->view->cachedb, dbp);
   2857   1.9  christos 		result = dns_db_findext(*dbp, name, version, type, 0,
   2858   1.9  christos 					client->now, &node, found, &cm, &ci,
   2859   1.9  christos 					*rdatasetp, NULL);
   2860   1.1  christos 	}
   2861   1.1  christos 	rpz_clean(NULL, dbp, &node, NULL);
   2862   1.1  christos 	if (result == DNS_R_DELEGATION) {
   2863   1.1  christos 		rpz_clean(NULL, NULL, NULL, rdatasetp);
   2864   1.1  christos 		/*
   2865   1.1  christos 		 * Recurse for NS rrset or A or AAAA rrset for an NS.
   2866   1.1  christos 		 * Do not recurse for addresses for the query name.
   2867   1.1  christos 		 */
   2868   1.1  christos 		if (rpz_type == DNS_RPZ_TYPE_IP) {
   2869   1.1  christos 			result = DNS_R_NXRRSET;
   2870   1.1  christos 		} else if (!client->view->rpzs->p.nsip_wait_recurse) {
   2871   1.1  christos 			query_rpzfetch(client, name, type);
   2872   1.1  christos 			result = DNS_R_NXRRSET;
   2873   1.1  christos 		} else {
   2874   1.8  christos 			dns_name_copynf(name, st->r_name);
   2875   1.3  christos 			result = ns_query_recurse(client, type, st->r_name,
   2876   1.3  christos 						  NULL, NULL, resuming);
   2877   1.1  christos 			if (result == ISC_R_SUCCESS) {
   2878   1.1  christos 				st->state |= DNS_RPZ_RECURSING;
   2879   1.1  christos 				result = DNS_R_DELEGATION;
   2880   1.1  christos 			}
   2881   1.1  christos 		}
   2882   1.1  christos 	}
   2883   1.1  christos 	return (result);
   2884   1.1  christos }
   2885   1.1  christos 
   2886   1.1  christos /*
   2887   1.1  christos  * Compute a policy owner name, p_name, in a policy zone given the needed
   2888   1.1  christos  * policy type and the trigger name.
   2889   1.1  christos  */
   2890   1.1  christos static isc_result_t
   2891   1.9  christos rpz_get_p_name(ns_client_t *client, dns_name_t *p_name, dns_rpz_zone_t *rpz,
   2892   1.9  christos 	       dns_rpz_type_t rpz_type, dns_name_t *trig_name) {
   2893   1.1  christos 	dns_offsets_t prefix_offsets;
   2894   1.1  christos 	dns_name_t prefix, *suffix;
   2895   1.1  christos 	unsigned int first, labels;
   2896   1.1  christos 	isc_result_t result;
   2897   1.1  christos 
   2898   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_get_p_name");
   2899   1.1  christos 
   2900   1.1  christos 	/*
   2901   1.1  christos 	 * The policy owner name consists of a suffix depending on the type
   2902   1.1  christos 	 * and policy zone and a prefix that is the longest possible string
   2903   1.1  christos 	 * from the trigger name that keesp the resulting policy owner name
   2904   1.1  christos 	 * from being too long.
   2905   1.1  christos 	 */
   2906   1.1  christos 	switch (rpz_type) {
   2907   1.1  christos 	case DNS_RPZ_TYPE_CLIENT_IP:
   2908   1.1  christos 		suffix = &rpz->client_ip;
   2909   1.1  christos 		break;
   2910   1.1  christos 	case DNS_RPZ_TYPE_QNAME:
   2911   1.1  christos 		suffix = &rpz->origin;
   2912   1.1  christos 		break;
   2913   1.1  christos 	case DNS_RPZ_TYPE_IP:
   2914   1.1  christos 		suffix = &rpz->ip;
   2915   1.1  christos 		break;
   2916   1.1  christos 	case DNS_RPZ_TYPE_NSDNAME:
   2917   1.1  christos 		suffix = &rpz->nsdname;
   2918   1.1  christos 		break;
   2919   1.1  christos 	case DNS_RPZ_TYPE_NSIP:
   2920   1.1  christos 		suffix = &rpz->nsip;
   2921   1.1  christos 		break;
   2922   1.1  christos 	default:
   2923   1.1  christos 		INSIST(0);
   2924   1.3  christos 		ISC_UNREACHABLE();
   2925   1.1  christos 	}
   2926   1.1  christos 
   2927   1.1  christos 	/*
   2928   1.1  christos 	 * Start with relative version of the full trigger name,
   2929   1.1  christos 	 * and trim enough allow the addition of the suffix.
   2930   1.1  christos 	 */
   2931   1.1  christos 	dns_name_init(&prefix, prefix_offsets);
   2932   1.1  christos 	labels = dns_name_countlabels(trig_name);
   2933   1.1  christos 	first = 0;
   2934   1.1  christos 	for (;;) {
   2935   1.9  christos 		dns_name_getlabelsequence(trig_name, first, labels - first - 1,
   2936   1.1  christos 					  &prefix);
   2937   1.1  christos 		result = dns_name_concatenate(&prefix, suffix, p_name, NULL);
   2938   1.9  christos 		if (result == ISC_R_SUCCESS) {
   2939   1.1  christos 			break;
   2940   1.9  christos 		}
   2941   1.1  christos 		INSIST(result == DNS_R_NAMETOOLONG);
   2942   1.1  christos 		/*
   2943   1.1  christos 		 * Trim the trigger name until the combination is not too long.
   2944   1.1  christos 		 */
   2945   1.9  christos 		if (labels - first < 2) {
   2946   1.1  christos 			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, suffix,
   2947   1.9  christos 				     rpz_type, "concatenate()", result);
   2948   1.1  christos 			return (ISC_R_FAILURE);
   2949   1.1  christos 		}
   2950   1.1  christos 		/*
   2951   1.1  christos 		 * Complain once about trimming the trigger name.
   2952   1.1  christos 		 */
   2953   1.1  christos 		if (first == 0) {
   2954   1.1  christos 			rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, suffix,
   2955   1.9  christos 				     rpz_type, "concatenate()", result);
   2956   1.1  christos 		}
   2957   1.1  christos 		++first;
   2958   1.1  christos 	}
   2959   1.1  christos 	return (ISC_R_SUCCESS);
   2960   1.1  christos }
   2961   1.1  christos 
   2962   1.1  christos /*
   2963   1.1  christos  * Look in policy zone rpz for a policy of rpz_type by p_name.
   2964   1.1  christos  * The self-name (usually the client qname or an NS name) is compared with
   2965   1.1  christos  * the target of a CNAME policy for the old style passthru encoding.
   2966   1.1  christos  * If found, the policy is recorded in *zonep, *dbp, *versionp, *nodep,
   2967   1.1  christos  * *rdatasetp, and *policyp.
   2968   1.1  christos  * The target DNS type, qtype, chooses the best rdataset for *rdatasetp.
   2969   1.1  christos  * The caller must decide if the found policy is most suitable, including
   2970   1.1  christos  * better than a previously found policy.
   2971   1.1  christos  * If it is best, the caller records it in client->query.rpz_st->m.
   2972   1.1  christos  */
   2973   1.1  christos static isc_result_t
   2974   1.1  christos rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
   2975   1.1  christos 	   dns_name_t *p_name, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
   2976   1.1  christos 	   dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
   2977   1.1  christos 	   dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
   2978   1.9  christos 	   dns_rpz_policy_t *policyp) {
   2979   1.1  christos 	dns_fixedname_t foundf;
   2980   1.1  christos 	dns_name_t *found;
   2981   1.1  christos 	isc_result_t result;
   2982   1.1  christos 	dns_clientinfomethods_t cm;
   2983   1.1  christos 	dns_clientinfo_t ci;
   2984   1.6  christos 	bool found_a = false;
   2985   1.1  christos 
   2986   1.1  christos 	REQUIRE(nodep != NULL);
   2987   1.1  christos 
   2988   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_find_p");
   2989   1.1  christos 
   2990   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   2991   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   2992   1.1  christos 
   2993   1.1  christos 	/*
   2994   1.1  christos 	 * Try to find either a CNAME or the type of record demanded by the
   2995   1.1  christos 	 * request from the policy zone.
   2996   1.1  christos 	 */
   2997   1.1  christos 	rpz_clean(zonep, dbp, nodep, rdatasetp);
   2998   1.1  christos 	result = rpz_ready(client, rdatasetp);
   2999   1.1  christos 	if (result != ISC_R_SUCCESS) {
   3000   1.1  christos 		CTRACE(ISC_LOG_ERROR, "rpz_ready() failed");
   3001   1.1  christos 		return (DNS_R_SERVFAIL);
   3002   1.1  christos 	}
   3003   1.1  christos 	*versionp = NULL;
   3004   1.1  christos 	result = rpz_getdb(client, p_name, rpz_type, zonep, dbp, versionp);
   3005   1.9  christos 	if (result != ISC_R_SUCCESS) {
   3006   1.1  christos 		return (DNS_R_NXDOMAIN);
   3007   1.9  christos 	}
   3008   1.1  christos 	found = dns_fixedname_initname(&foundf);
   3009   1.1  christos 
   3010   1.1  christos 	result = dns_db_findext(*dbp, p_name, *versionp, dns_rdatatype_any, 0,
   3011   1.9  christos 				client->now, nodep, found, &cm, &ci, *rdatasetp,
   3012   1.9  christos 				NULL);
   3013   1.1  christos 	/*
   3014   1.1  christos 	 * Choose the best rdataset if we found something.
   3015   1.1  christos 	 */
   3016   1.1  christos 	if (result == ISC_R_SUCCESS) {
   3017   1.1  christos 		dns_rdatasetiter_t *rdsiter;
   3018   1.1  christos 
   3019   1.1  christos 		rdsiter = NULL;
   3020   1.1  christos 		result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0,
   3021   1.1  christos 					     &rdsiter);
   3022   1.1  christos 		if (result != ISC_R_SUCCESS) {
   3023   1.1  christos 			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name,
   3024   1.3  christos 				     rpz_type, "allrdatasets()", result);
   3025   1.1  christos 			CTRACE(ISC_LOG_ERROR,
   3026   1.1  christos 			       "rpz_find_p: allrdatasets failed");
   3027   1.1  christos 			return (DNS_R_SERVFAIL);
   3028   1.1  christos 		}
   3029   1.6  christos 		if (qtype == dns_rdatatype_aaaa &&
   3030   1.6  christos 		    !ISC_LIST_EMPTY(client->view->dns64)) {
   3031   1.6  christos 			for (result = dns_rdatasetiter_first(rdsiter);
   3032   1.6  christos 			     result == ISC_R_SUCCESS;
   3033   1.9  christos 			     result = dns_rdatasetiter_next(rdsiter))
   3034   1.9  christos 			{
   3035   1.6  christos 				dns_rdatasetiter_current(rdsiter, *rdatasetp);
   3036   1.6  christos 				if ((*rdatasetp)->type == dns_rdatatype_a) {
   3037   1.6  christos 					found_a = true;
   3038   1.6  christos 				}
   3039   1.6  christos 				dns_rdataset_disassociate(*rdatasetp);
   3040   1.6  christos 			}
   3041   1.6  christos 		}
   3042   1.1  christos 		for (result = dns_rdatasetiter_first(rdsiter);
   3043   1.1  christos 		     result == ISC_R_SUCCESS;
   3044   1.9  christos 		     result = dns_rdatasetiter_next(rdsiter))
   3045   1.9  christos 		{
   3046   1.1  christos 			dns_rdatasetiter_current(rdsiter, *rdatasetp);
   3047   1.1  christos 			if ((*rdatasetp)->type == dns_rdatatype_cname ||
   3048   1.9  christos 			    (*rdatasetp)->type == qtype) {
   3049   1.1  christos 				break;
   3050   1.9  christos 			}
   3051   1.1  christos 			dns_rdataset_disassociate(*rdatasetp);
   3052   1.1  christos 		}
   3053   1.1  christos 		dns_rdatasetiter_destroy(&rdsiter);
   3054   1.1  christos 		if (result != ISC_R_SUCCESS) {
   3055   1.1  christos 			if (result != ISC_R_NOMORE) {
   3056   1.1  christos 				rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
   3057   1.9  christos 					     p_name, rpz_type, "rdatasetiter",
   3058   1.9  christos 					     result);
   3059   1.9  christos 				CTRACE(ISC_LOG_ERROR, "rpz_find_p: "
   3060   1.9  christos 						      "rdatasetiter failed");
   3061   1.1  christos 				return (DNS_R_SERVFAIL);
   3062   1.1  christos 			}
   3063   1.1  christos 			/*
   3064   1.1  christos 			 * Ask again to get the right DNS_R_DNAME/NXRRSET/...
   3065   1.1  christos 			 * result if there is neither a CNAME nor target type.
   3066   1.1  christos 			 */
   3067   1.9  christos 			if (dns_rdataset_isassociated(*rdatasetp)) {
   3068   1.1  christos 				dns_rdataset_disassociate(*rdatasetp);
   3069   1.9  christos 			}
   3070   1.1  christos 			dns_db_detachnode(*dbp, nodep);
   3071   1.1  christos 
   3072   1.1  christos 			if (qtype == dns_rdatatype_rrsig ||
   3073   1.9  christos 			    qtype == dns_rdatatype_sig) {
   3074   1.1  christos 				result = DNS_R_NXRRSET;
   3075   1.9  christos 			} else {
   3076   1.1  christos 				result = dns_db_findext(*dbp, p_name, *versionp,
   3077   1.1  christos 							qtype, 0, client->now,
   3078   1.1  christos 							nodep, found, &cm, &ci,
   3079   1.1  christos 							*rdatasetp, NULL);
   3080   1.9  christos 			}
   3081   1.1  christos 		}
   3082   1.1  christos 	}
   3083   1.1  christos 	switch (result) {
   3084   1.1  christos 	case ISC_R_SUCCESS:
   3085   1.1  christos 		if ((*rdatasetp)->type != dns_rdatatype_cname) {
   3086   1.1  christos 			*policyp = DNS_RPZ_POLICY_RECORD;
   3087   1.1  christos 		} else {
   3088   1.1  christos 			*policyp = dns_rpz_decode_cname(rpz, *rdatasetp,
   3089   1.1  christos 							self_name);
   3090   1.1  christos 			if ((*policyp == DNS_RPZ_POLICY_RECORD ||
   3091   1.1  christos 			     *policyp == DNS_RPZ_POLICY_WILDCNAME) &&
   3092   1.1  christos 			    qtype != dns_rdatatype_cname &&
   3093   1.1  christos 			    qtype != dns_rdatatype_any)
   3094   1.9  christos 			{
   3095   1.1  christos 				return (DNS_R_CNAME);
   3096   1.9  christos 			}
   3097   1.1  christos 		}
   3098   1.1  christos 		return (ISC_R_SUCCESS);
   3099   1.1  christos 	case DNS_R_NXRRSET:
   3100   1.6  christos 		if (found_a) {
   3101   1.6  christos 			*policyp = DNS_RPZ_POLICY_DNS64;
   3102   1.6  christos 		} else {
   3103   1.6  christos 			*policyp = DNS_RPZ_POLICY_NODATA;
   3104   1.6  christos 		}
   3105   1.1  christos 		return (result);
   3106   1.1  christos 	case DNS_R_DNAME:
   3107   1.9  christos 	/*
   3108   1.9  christos 	 * DNAME policy RRs have very few if any uses that are not
   3109   1.9  christos 	 * better served with simple wildcards.  Making them work would
   3110   1.9  christos 	 * require complications to get the number of labels matched
   3111   1.9  christos 	 * in the name or the found name to the main DNS_R_DNAME case
   3112   1.9  christos 	 * in query_dname().  The domain also does not appear in the
   3113   1.9  christos 	 * summary database at the right level, so this happens only
   3114   1.9  christos 	 * with a single policy zone when we have no summary database.
   3115   1.9  christos 	 * Treat it as a miss.
   3116   1.9  christos 	 */
   3117   1.1  christos 	case DNS_R_NXDOMAIN:
   3118   1.1  christos 	case DNS_R_EMPTYNAME:
   3119   1.1  christos 		return (DNS_R_NXDOMAIN);
   3120   1.1  christos 	default:
   3121   1.9  christos 		rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, "",
   3122   1.9  christos 			     result);
   3123   1.9  christos 		CTRACE(ISC_LOG_ERROR, "rpz_find_p: unexpected result");
   3124   1.1  christos 		return (DNS_R_SERVFAIL);
   3125   1.1  christos 	}
   3126   1.1  christos }
   3127   1.1  christos 
   3128   1.1  christos static void
   3129   1.1  christos rpz_save_p(dns_rpz_st_t *st, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
   3130   1.1  christos 	   dns_rpz_policy_t policy, dns_name_t *p_name, dns_rpz_prefix_t prefix,
   3131   1.1  christos 	   isc_result_t result, dns_zone_t **zonep, dns_db_t **dbp,
   3132   1.1  christos 	   dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
   3133   1.9  christos 	   dns_dbversion_t *version) {
   3134   1.1  christos 	dns_rdataset_t *trdataset = NULL;
   3135   1.1  christos 
   3136   1.1  christos 	rpz_match_clear(st);
   3137   1.1  christos 	st->m.rpz = rpz;
   3138   1.1  christos 	st->m.type = rpz_type;
   3139   1.1  christos 	st->m.policy = policy;
   3140   1.8  christos 	dns_name_copynf(p_name, st->p_name);
   3141   1.1  christos 	st->m.prefix = prefix;
   3142   1.1  christos 	st->m.result = result;
   3143   1.1  christos 	SAVE(st->m.zone, *zonep);
   3144   1.1  christos 	SAVE(st->m.db, *dbp);
   3145   1.1  christos 	SAVE(st->m.node, *nodep);
   3146   1.1  christos 	if (*rdatasetp != NULL && dns_rdataset_isassociated(*rdatasetp)) {
   3147   1.1  christos 		/*
   3148   1.1  christos 		 * Save the replacement rdataset from the policy
   3149   1.1  christos 		 * and make the previous replacement rdataset scratch.
   3150   1.1  christos 		 */
   3151   1.1  christos 		SAVE(trdataset, st->m.rdataset);
   3152   1.1  christos 		SAVE(st->m.rdataset, *rdatasetp);
   3153   1.1  christos 		SAVE(*rdatasetp, trdataset);
   3154   1.1  christos 		st->m.ttl = ISC_MIN(st->m.rdataset->ttl, rpz->max_policy_ttl);
   3155   1.1  christos 	} else {
   3156   1.1  christos 		st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT, rpz->max_policy_ttl);
   3157   1.1  christos 	}
   3158   1.1  christos 	SAVE(st->m.version, version);
   3159   1.1  christos }
   3160   1.1  christos 
   3161   1.1  christos #ifdef USE_DNSRPS
   3162   1.1  christos /*
   3163   1.1  christos  * Check the results of a RPZ service interface lookup.
   3164   1.1  christos  * Stop after an error (<0) or not a hit on a disabled zone (0).
   3165   1.1  christos  * Continue after a hit on a disabled zone (>0).
   3166   1.1  christos  */
   3167   1.1  christos static int
   3168   1.1  christos dnsrps_ck(librpz_emsg_t *emsg, ns_client_t *client, rpsdb_t *rpsdb,
   3169   1.9  christos 	  bool recursed) {
   3170   1.1  christos 	isc_region_t region;
   3171   1.1  christos 	librpz_domain_buf_t pname_buf;
   3172   1.1  christos 
   3173   1.1  christos 	if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) {
   3174   1.1  christos 		return (-1);
   3175   1.1  christos 	}
   3176   1.1  christos 
   3177   1.1  christos 	/*
   3178   1.1  christos 	 * Forget the state from before the IP address or domain check
   3179   1.1  christos 	 * if the lookup hit nothing.
   3180   1.1  christos 	 */
   3181   1.1  christos 	if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED ||
   3182   1.1  christos 	    rpsdb->result.hit_id != rpsdb->hit_id ||
   3183   1.1  christos 	    rpsdb->result.policy != LIBRPZ_POLICY_DISABLED)
   3184   1.1  christos 	{
   3185   1.1  christos 		if (!librpz->rsp_pop_discard(emsg, rpsdb->rsp)) {
   3186   1.1  christos 			return (-1);
   3187   1.1  christos 		}
   3188   1.1  christos 		return (0);
   3189   1.1  christos 	}
   3190   1.1  christos 
   3191   1.1  christos 	/*
   3192   1.1  christos 	 * Log a hit on a disabled zone.
   3193   1.1  christos 	 * Forget the zone to not try it again, and restore the pre-hit state.
   3194   1.1  christos 	 */
   3195   1.1  christos 	if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) {
   3196   1.1  christos 		return (-1);
   3197   1.1  christos 	}
   3198   1.1  christos 	region.base = pname_buf.d;
   3199   1.1  christos 	region.length = pname_buf.size;
   3200   1.1  christos 	dns_name_fromregion(client->query.rpz_st->p_name, &region);
   3201   1.9  christos 	rpz_log_rewrite(client, true, dns_dnsrps_2policy(rpsdb->result.zpolicy),
   3202   1.1  christos 			dns_dnsrps_trig2type(rpsdb->result.trig), NULL,
   3203   1.1  christos 			client->query.rpz_st->p_name, NULL,
   3204   1.1  christos 			rpsdb->result.cznum);
   3205   1.1  christos 
   3206   1.1  christos 	if (!librpz->rsp_forget_zone(emsg, rpsdb->result.cznum, rpsdb->rsp) ||
   3207   1.1  christos 	    !librpz->rsp_pop(emsg, &rpsdb->result, rpsdb->rsp))
   3208   1.1  christos 	{
   3209   1.1  christos 		return (-1);
   3210   1.1  christos 	}
   3211   1.1  christos 	return (1);
   3212   1.1  christos }
   3213   1.1  christos 
   3214   1.1  christos /*
   3215   1.1  christos  * Ready the shim database and rdataset for a DNSRPS hit.
   3216   1.1  christos  */
   3217   1.3  christos static bool
   3218   1.1  christos dnsrps_set_p(librpz_emsg_t *emsg, ns_client_t *client, dns_rpz_st_t *st,
   3219   1.1  christos 	     dns_rdatatype_t qtype, dns_rdataset_t **p_rdatasetp,
   3220   1.9  christos 	     bool recursed) {
   3221   1.1  christos 	rpsdb_t *rpsdb;
   3222   1.1  christos 	librpz_domain_buf_t pname_buf;
   3223   1.1  christos 	isc_region_t region;
   3224   1.1  christos 	dns_zone_t *p_zone;
   3225   1.1  christos 	dns_db_t *p_db;
   3226   1.1  christos 	dns_dbnode_t *p_node;
   3227   1.1  christos 	dns_rpz_policy_t policy;
   3228   1.1  christos 	dns_fixedname_t foundf;
   3229   1.1  christos 	dns_name_t *found;
   3230   1.1  christos 	dns_rdatatype_t foundtype, searchtype;
   3231   1.1  christos 	isc_result_t result;
   3232   1.1  christos 
   3233   1.1  christos 	rpsdb = (rpsdb_t *)st->rpsdb;
   3234   1.1  christos 
   3235   1.1  christos 	if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) {
   3236   1.3  christos 		return (false);
   3237   1.1  christos 	}
   3238   1.1  christos 
   3239   1.1  christos 	if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED) {
   3240   1.3  christos 		return (true);
   3241   1.1  christos 	}
   3242   1.1  christos 
   3243   1.1  christos 	/*
   3244   1.1  christos 	 * Give the fake or shim DNSRPS database its new origin.
   3245   1.1  christos 	 */
   3246   1.1  christos 	if (!librpz->rsp_soa(emsg, NULL, NULL, &rpsdb->origin_buf,
   3247   1.1  christos 			     &rpsdb->result, rpsdb->rsp))
   3248   1.1  christos 	{
   3249   1.3  christos 		return (false);
   3250   1.1  christos 	}
   3251   1.1  christos 	region.base = rpsdb->origin_buf.d;
   3252   1.1  christos 	region.length = rpsdb->origin_buf.size;
   3253   1.1  christos 	dns_name_fromregion(&rpsdb->common.origin, &region);
   3254   1.1  christos 
   3255   1.1  christos 	if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) {
   3256   1.3  christos 		return (false);
   3257   1.1  christos 	}
   3258   1.1  christos 	region.base = pname_buf.d;
   3259   1.1  christos 	region.length = pname_buf.size;
   3260   1.1  christos 	dns_name_fromregion(st->p_name, &region);
   3261   1.1  christos 
   3262   1.1  christos 	p_zone = NULL;
   3263   1.1  christos 	p_db = NULL;
   3264   1.1  christos 	p_node = NULL;
   3265   1.1  christos 	rpz_ready(client, p_rdatasetp);
   3266   1.1  christos 	dns_db_attach(st->rpsdb, &p_db);
   3267   1.1  christos 	policy = dns_dnsrps_2policy(rpsdb->result.policy);
   3268   1.1  christos 	if (policy != DNS_RPZ_POLICY_RECORD) {
   3269   1.1  christos 		result = ISC_R_SUCCESS;
   3270   1.1  christos 	} else if (qtype == dns_rdatatype_rrsig) {
   3271   1.1  christos 		/*
   3272   1.1  christos 		 * dns_find_db() refuses to look for and fail to
   3273   1.1  christos 		 * find dns_rdatatype_rrsig.
   3274   1.1  christos 		 */
   3275   1.1  christos 		result = DNS_R_NXRRSET;
   3276   1.1  christos 		policy = DNS_RPZ_POLICY_NODATA;
   3277   1.1  christos 	} else {
   3278   1.1  christos 		/*
   3279   1.1  christos 		 * Get the next (and so first) RR from the policy node.
   3280   1.1  christos 		 * If it is a CNAME, then look for it regardless of the
   3281   1.1  christos 		 * query type.
   3282   1.1  christos 		 */
   3283   1.1  christos 		if (!librpz->rsp_rr(emsg, &foundtype, NULL, NULL, NULL,
   3284   1.1  christos 				    &rpsdb->result, rpsdb->qname->ndata,
   3285   1.1  christos 				    rpsdb->qname->length, rpsdb->rsp))
   3286   1.1  christos 		{
   3287   1.3  christos 			return (false);
   3288   1.1  christos 		}
   3289   1.1  christos 		if (foundtype == dns_rdatatype_cname) {
   3290   1.1  christos 			searchtype = dns_rdatatype_cname;
   3291   1.1  christos 		} else {
   3292   1.1  christos 			searchtype = qtype;
   3293   1.1  christos 		}
   3294   1.1  christos 		/*
   3295   1.1  christos 		 * Get the DNSPRS imitation rdataset.
   3296   1.1  christos 		 */
   3297   1.1  christos 		found = dns_fixedname_initname(&foundf);
   3298   1.9  christos 		result = dns_db_find(p_db, st->p_name, NULL, searchtype, 0, 0,
   3299   1.9  christos 				     &p_node, found, *p_rdatasetp, NULL);
   3300   1.1  christos 
   3301   1.1  christos 		if (result == ISC_R_SUCCESS) {
   3302   1.1  christos 			if (searchtype == dns_rdatatype_cname &&
   3303   1.9  christos 			    qtype != dns_rdatatype_cname) {
   3304   1.1  christos 				result = DNS_R_CNAME;
   3305   1.1  christos 			}
   3306   1.1  christos 		} else if (result == DNS_R_NXRRSET) {
   3307   1.1  christos 			policy = DNS_RPZ_POLICY_NODATA;
   3308   1.1  christos 		} else {
   3309   1.1  christos 			snprintf(emsg->c, sizeof(emsg->c), "dns_db_find(): %s",
   3310   1.1  christos 				 isc_result_totext(result));
   3311   1.3  christos 			return (false);
   3312   1.1  christos 		}
   3313   1.1  christos 	}
   3314   1.1  christos 
   3315   1.1  christos 	rpz_save_p(st, client->view->rpzs->zones[rpsdb->result.cznum],
   3316   1.9  christos 		   dns_dnsrps_trig2type(rpsdb->result.trig), policy, st->p_name,
   3317   1.9  christos 		   0, result, &p_zone, &p_db, &p_node, p_rdatasetp, NULL);
   3318   1.1  christos 
   3319   1.1  christos 	rpz_clean(NULL, NULL, NULL, p_rdatasetp);
   3320   1.1  christos 
   3321   1.3  christos 	return (true);
   3322   1.1  christos }
   3323   1.1  christos 
   3324   1.1  christos static isc_result_t
   3325   1.1  christos dnsrps_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
   3326   1.9  christos 		  dns_rpz_type_t rpz_type, dns_rdataset_t **p_rdatasetp) {
   3327   1.1  christos 	dns_rpz_st_t *st;
   3328   1.1  christos 	rpsdb_t *rpsdb;
   3329   1.1  christos 	librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP;
   3330   1.3  christos 	bool recursed = false;
   3331   1.1  christos 	int res;
   3332   1.1  christos 	librpz_emsg_t emsg;
   3333   1.1  christos 	isc_result_t result;
   3334   1.1  christos 
   3335   1.1  christos 	st = client->query.rpz_st;
   3336   1.1  christos 	rpsdb = (rpsdb_t *)st->rpsdb;
   3337   1.1  christos 
   3338   1.1  christos 	result = rpz_ready(client, p_rdatasetp);
   3339   1.1  christos 	if (result != ISC_R_SUCCESS) {
   3340   1.1  christos 		st->m.policy = DNS_RPZ_POLICY_ERROR;
   3341   1.1  christos 		return (result);
   3342   1.1  christos 	}
   3343   1.1  christos 
   3344   1.1  christos 	switch (rpz_type) {
   3345   1.1  christos 	case DNS_RPZ_TYPE_CLIENT_IP:
   3346   1.1  christos 		trig = LIBRPZ_TRIG_CLIENT_IP;
   3347   1.3  christos 		recursed = false;
   3348   1.1  christos 		break;
   3349   1.1  christos 	case DNS_RPZ_TYPE_IP:
   3350   1.1  christos 		trig = LIBRPZ_TRIG_IP;
   3351   1.3  christos 		recursed = true;
   3352   1.1  christos 		break;
   3353   1.1  christos 	case DNS_RPZ_TYPE_NSIP:
   3354   1.1  christos 		trig = LIBRPZ_TRIG_NSIP;
   3355   1.3  christos 		recursed = true;
   3356   1.1  christos 		break;
   3357   1.1  christos 	default:
   3358   1.1  christos 		INSIST(0);
   3359   1.3  christos 		ISC_UNREACHABLE();
   3360   1.1  christos 	}
   3361   1.1  christos 
   3362   1.1  christos 	do {
   3363   1.1  christos 		if (!librpz->rsp_push(&emsg, rpsdb->rsp) ||
   3364   1.1  christos 		    !librpz->ck_ip(&emsg,
   3365   1.1  christos 				   netaddr->family == AF_INET
   3366   1.9  christos 					   ? (const void *)&netaddr->type.in
   3367   1.9  christos 					   : (const void *)&netaddr->type.in6,
   3368   1.1  christos 				   netaddr->family, trig, ++rpsdb->hit_id,
   3369   1.1  christos 				   recursed, rpsdb->rsp) ||
   3370   1.1  christos 		    (res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0)
   3371   1.1  christos 		{
   3372   1.1  christos 			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
   3373   1.1  christos 				     rpz_type, emsg.c, DNS_R_SERVFAIL);
   3374   1.1  christos 			st->m.policy = DNS_RPZ_POLICY_ERROR;
   3375   1.1  christos 			return (DNS_R_SERVFAIL);
   3376   1.1  christos 		}
   3377   1.1  christos 	} while (res != 0);
   3378   1.1  christos 	return (ISC_R_SUCCESS);
   3379   1.1  christos }
   3380   1.1  christos 
   3381   1.1  christos static isc_result_t
   3382   1.9  christos dnsrps_rewrite_name(ns_client_t *client, dns_name_t *trig_name, bool recursed,
   3383   1.9  christos 		    dns_rpz_type_t rpz_type, dns_rdataset_t **p_rdatasetp) {
   3384   1.1  christos 	dns_rpz_st_t *st;
   3385   1.1  christos 	rpsdb_t *rpsdb;
   3386   1.1  christos 	librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP;
   3387   1.1  christos 	isc_region_t r;
   3388   1.1  christos 	int res;
   3389   1.1  christos 	librpz_emsg_t emsg;
   3390   1.1  christos 	isc_result_t result;
   3391   1.1  christos 
   3392   1.1  christos 	st = client->query.rpz_st;
   3393   1.1  christos 	rpsdb = (rpsdb_t *)st->rpsdb;
   3394   1.1  christos 
   3395   1.1  christos 	result = rpz_ready(client, p_rdatasetp);
   3396   1.1  christos 	if (result != ISC_R_SUCCESS) {
   3397   1.1  christos 		st->m.policy = DNS_RPZ_POLICY_ERROR;
   3398   1.1  christos 		return (result);
   3399   1.1  christos 	}
   3400   1.1  christos 
   3401   1.1  christos 	switch (rpz_type) {
   3402   1.1  christos 	case DNS_RPZ_TYPE_QNAME:
   3403   1.1  christos 		trig = LIBRPZ_TRIG_QNAME;
   3404   1.1  christos 		break;
   3405   1.1  christos 	case DNS_RPZ_TYPE_NSDNAME:
   3406   1.1  christos 		trig = LIBRPZ_TRIG_NSDNAME;
   3407   1.1  christos 		break;
   3408   1.1  christos 	default:
   3409   1.1  christos 		INSIST(0);
   3410   1.3  christos 		ISC_UNREACHABLE();
   3411   1.1  christos 	}
   3412   1.1  christos 
   3413   1.1  christos 	dns_name_toregion(trig_name, &r);
   3414   1.1  christos 	do {
   3415   1.1  christos 		if (!librpz->rsp_push(&emsg, rpsdb->rsp) ||
   3416   1.9  christos 		    !librpz->ck_domain(&emsg, r.base, r.length, trig,
   3417   1.9  christos 				       ++rpsdb->hit_id, recursed, rpsdb->rsp) ||
   3418   1.1  christos 		    (res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0)
   3419   1.1  christos 		{
   3420   1.1  christos 			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
   3421   1.1  christos 				     rpz_type, emsg.c, DNS_R_SERVFAIL);
   3422   1.1  christos 			st->m.policy = DNS_RPZ_POLICY_ERROR;
   3423   1.1  christos 			return (DNS_R_SERVFAIL);
   3424   1.1  christos 		}
   3425   1.1  christos 	} while (res != 0);
   3426   1.1  christos 	return (ISC_R_SUCCESS);
   3427   1.1  christos }
   3428   1.1  christos #endif /* USE_DNSRPS */
   3429   1.1  christos 
   3430   1.1  christos /*
   3431   1.1  christos  * Check this address in every eligible policy zone.
   3432   1.1  christos  */
   3433   1.1  christos static isc_result_t
   3434   1.1  christos rpz_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
   3435   1.1  christos 	       dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
   3436   1.9  christos 	       dns_rpz_zbits_t zbits, dns_rdataset_t **p_rdatasetp) {
   3437   1.1  christos 	dns_rpz_zones_t *rpzs;
   3438   1.1  christos 	dns_rpz_st_t *st;
   3439   1.1  christos 	dns_rpz_zone_t *rpz;
   3440   1.1  christos 	dns_rpz_prefix_t prefix;
   3441   1.1  christos 	dns_rpz_num_t rpz_num;
   3442   1.1  christos 	dns_fixedname_t ip_namef, p_namef;
   3443   1.1  christos 	dns_name_t *ip_name, *p_name;
   3444   1.1  christos 	dns_zone_t *p_zone;
   3445   1.1  christos 	dns_db_t *p_db;
   3446   1.1  christos 	dns_dbversion_t *p_version;
   3447   1.1  christos 	dns_dbnode_t *p_node;
   3448   1.1  christos 	dns_rpz_policy_t policy;
   3449   1.1  christos 	isc_result_t result;
   3450   1.1  christos 
   3451   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip");
   3452   1.1  christos 
   3453   1.1  christos 	rpzs = client->view->rpzs;
   3454   1.1  christos 	st = client->query.rpz_st;
   3455   1.1  christos #ifdef USE_DNSRPS
   3456   1.1  christos 	if (st->popt.dnsrps_enabled) {
   3457   1.1  christos 		return (dnsrps_rewrite_ip(client, netaddr, rpz_type,
   3458   1.9  christos 					  p_rdatasetp));
   3459   1.1  christos 	}
   3460   1.9  christos #endif /* ifdef USE_DNSRPS */
   3461   1.1  christos 
   3462   1.1  christos 	ip_name = dns_fixedname_initname(&ip_namef);
   3463   1.1  christos 
   3464   1.1  christos 	p_zone = NULL;
   3465   1.1  christos 	p_db = NULL;
   3466   1.1  christos 	p_node = NULL;
   3467   1.1  christos 
   3468   1.1  christos 	while (zbits != 0) {
   3469   1.1  christos 		rpz_num = dns_rpz_find_ip(rpzs, rpz_type, zbits, netaddr,
   3470   1.1  christos 					  ip_name, &prefix);
   3471   1.9  christos 		if (rpz_num == DNS_RPZ_INVALID_NUM) {
   3472   1.1  christos 			break;
   3473   1.9  christos 		}
   3474   1.1  christos 		zbits &= (DNS_RPZ_ZMASK(rpz_num) >> 1);
   3475   1.1  christos 
   3476   1.1  christos 		/*
   3477   1.1  christos 		 * Do not try applying policy zones that cannot replace a
   3478   1.1  christos 		 * previously found policy zone.
   3479   1.1  christos 		 * Stop looking if the next best choice cannot
   3480   1.1  christos 		 * replace what we already have.
   3481   1.1  christos 		 */
   3482   1.1  christos 		rpz = rpzs->zones[rpz_num];
   3483   1.1  christos 		if (st->m.policy != DNS_RPZ_POLICY_MISS) {
   3484   1.9  christos 			if (st->m.rpz->num < rpz->num) {
   3485   1.1  christos 				break;
   3486   1.9  christos 			}
   3487   1.1  christos 			if (st->m.rpz->num == rpz->num &&
   3488   1.9  christos 			    (st->m.type < rpz_type || st->m.prefix > prefix))
   3489   1.9  christos 			{
   3490   1.1  christos 				break;
   3491   1.9  christos 			}
   3492   1.1  christos 		}
   3493   1.1  christos 
   3494   1.1  christos 		/*
   3495   1.1  christos 		 * Get the policy for a prefix at least as long
   3496   1.1  christos 		 * as the prefix of the entry we had before.
   3497   1.1  christos 		 */
   3498   1.1  christos 		p_name = dns_fixedname_initname(&p_namef);
   3499   1.1  christos 		result = rpz_get_p_name(client, p_name, rpz, rpz_type, ip_name);
   3500   1.9  christos 		if (result != ISC_R_SUCCESS) {
   3501   1.1  christos 			continue;
   3502   1.9  christos 		}
   3503   1.9  christos 		result = rpz_find_p(client, ip_name, qtype, p_name, rpz,
   3504   1.9  christos 				    rpz_type, &p_zone, &p_db, &p_version,
   3505   1.9  christos 				    &p_node, p_rdatasetp, &policy);
   3506   1.1  christos 		switch (result) {
   3507   1.1  christos 		case DNS_R_NXDOMAIN:
   3508   1.1  christos 			/*
   3509   1.1  christos 			 * Continue after a policy record that is missing
   3510   1.1  christos 			 * contrary to the summary data.  The summary
   3511   1.1  christos 			 * data can out of date during races with and among
   3512   1.1  christos 			 * policy zone updates.
   3513   1.1  christos 			 */
   3514   1.9  christos 			CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip: mismatched "
   3515   1.9  christos 					      "summary data; "
   3516   1.9  christos 					      "continuing");
   3517   1.1  christos 			continue;
   3518   1.1  christos 		case DNS_R_SERVFAIL:
   3519   1.1  christos 			rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp);
   3520   1.1  christos 			st->m.policy = DNS_RPZ_POLICY_ERROR;
   3521   1.1  christos 			return (DNS_R_SERVFAIL);
   3522   1.1  christos 		default:
   3523   1.1  christos 			/*
   3524   1.1  christos 			 * Forget this policy if it is not preferable
   3525   1.1  christos 			 * to the previously found policy.
   3526   1.1  christos 			 * If this policy is not good, then stop looking
   3527   1.1  christos 			 * because none of the later policy zones would work.
   3528   1.1  christos 			 *
   3529   1.1  christos 			 * With more than one applicable policy, prefer
   3530   1.1  christos 			 * the earliest configured policy,
   3531   1.1  christos 			 * client-IP over QNAME over IP over NSDNAME over NSIP,
   3532   1.1  christos 			 * the longest prefix
   3533   1.1  christos 			 * the lexically smallest address.
   3534   1.1  christos 			 * dns_rpz_find_ip() ensures st->m.rpz->num >= rpz->num.
   3535   1.1  christos 			 * We can compare new and current p_name because
   3536   1.1  christos 			 * both are of the same type and in the same zone.
   3537   1.1  christos 			 * The tests above eliminate other reasons to
   3538   1.1  christos 			 * reject this policy.  If this policy can't work,
   3539   1.1  christos 			 * then neither can later zones.
   3540   1.1  christos 			 */
   3541   1.1  christos 			if (st->m.policy != DNS_RPZ_POLICY_MISS &&
   3542   1.1  christos 			    rpz->num == st->m.rpz->num &&
   3543   1.9  christos 			    (st->m.type == rpz_type && st->m.prefix == prefix &&
   3544   1.9  christos 			     0 > dns_name_rdatacompare(st->p_name, p_name)))
   3545   1.9  christos 			{
   3546   1.1  christos 				break;
   3547   1.9  christos 			}
   3548   1.1  christos 
   3549   1.1  christos 			/*
   3550   1.1  christos 			 * Stop checking after saving an enabled hit in this
   3551   1.1  christos 			 * policy zone.  The radix tree in the policy zone
   3552   1.1  christos 			 * ensures that we found the longest match.
   3553   1.1  christos 			 */
   3554   1.1  christos 			if (rpz->policy != DNS_RPZ_POLICY_DISABLED) {
   3555   1.9  christos 				CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip: "
   3556   1.9  christos 							 "rpz_save_p");
   3557   1.9  christos 				rpz_save_p(st, rpz, rpz_type, policy, p_name,
   3558   1.9  christos 					   prefix, result, &p_zone, &p_db,
   3559   1.9  christos 					   &p_node, p_rdatasetp, p_version);
   3560   1.1  christos 				break;
   3561   1.1  christos 			}
   3562   1.1  christos 
   3563   1.1  christos 			/*
   3564   1.1  christos 			 * Log DNS_RPZ_POLICY_DISABLED zones
   3565   1.1  christos 			 * and try the next eligible policy zone.
   3566   1.1  christos 			 */
   3567   1.9  christos 			rpz_log_rewrite(client, true, policy, rpz_type, p_zone,
   3568   1.9  christos 					p_name, NULL, rpz_num);
   3569   1.1  christos 		}
   3570   1.1  christos 	}
   3571   1.1  christos 
   3572   1.1  christos 	rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp);
   3573   1.1  christos 	return (ISC_R_SUCCESS);
   3574   1.1  christos }
   3575   1.1  christos 
   3576   1.1  christos /*
   3577   1.1  christos  * Check the IP addresses in the A or AAAA rrsets for name against
   3578   1.1  christos  * all eligible rpz_type (IP or NSIP) response policy rewrite rules.
   3579   1.1  christos  */
   3580   1.1  christos static isc_result_t
   3581   1.9  christos rpz_rewrite_ip_rrset(ns_client_t *client, dns_name_t *name,
   3582   1.9  christos 		     dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
   3583   1.9  christos 		     dns_rdatatype_t ip_type, dns_db_t **ip_dbp,
   3584   1.9  christos 		     dns_dbversion_t *ip_version, dns_rdataset_t **ip_rdatasetp,
   3585   1.9  christos 		     dns_rdataset_t **p_rdatasetp, bool resuming) {
   3586   1.1  christos 	dns_rpz_zbits_t zbits;
   3587   1.1  christos 	isc_netaddr_t netaddr;
   3588   1.1  christos 	struct in_addr ina;
   3589   1.1  christos 	struct in6_addr in6a;
   3590   1.1  christos 	isc_result_t result;
   3591   1.1  christos 
   3592   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrset");
   3593   1.1  christos 
   3594   1.1  christos 	zbits = rpz_get_zbits(client, ip_type, rpz_type);
   3595   1.9  christos 	if (zbits == 0) {
   3596   1.1  christos 		return (ISC_R_SUCCESS);
   3597   1.9  christos 	}
   3598   1.1  christos 
   3599   1.1  christos 	/*
   3600   1.1  christos 	 * Get the A or AAAA rdataset.
   3601   1.1  christos 	 */
   3602   1.1  christos 	result = rpz_rrset_find(client, name, ip_type, rpz_type, ip_dbp,
   3603   1.1  christos 				ip_version, ip_rdatasetp, resuming);
   3604   1.1  christos 	switch (result) {
   3605   1.1  christos 	case ISC_R_SUCCESS:
   3606   1.1  christos 	case DNS_R_GLUE:
   3607   1.1  christos 	case DNS_R_ZONECUT:
   3608   1.1  christos 		break;
   3609   1.1  christos 	case DNS_R_EMPTYNAME:
   3610   1.1  christos 	case DNS_R_EMPTYWILD:
   3611   1.1  christos 	case DNS_R_NXDOMAIN:
   3612   1.1  christos 	case DNS_R_NCACHENXDOMAIN:
   3613   1.1  christos 	case DNS_R_NXRRSET:
   3614   1.1  christos 	case DNS_R_NCACHENXRRSET:
   3615   1.1  christos 	case ISC_R_NOTFOUND:
   3616   1.1  christos 		return (ISC_R_SUCCESS);
   3617   1.1  christos 	case DNS_R_DELEGATION:
   3618   1.1  christos 	case DNS_R_DUPLICATE:
   3619   1.1  christos 	case DNS_R_DROP:
   3620   1.1  christos 		return (result);
   3621   1.1  christos 	case DNS_R_CNAME:
   3622   1.1  christos 	case DNS_R_DNAME:
   3623   1.1  christos 		rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name, rpz_type,
   3624   1.3  christos 			     "NS address rewrite rrset", result);
   3625   1.1  christos 		return (ISC_R_SUCCESS);
   3626   1.1  christos 	default:
   3627   1.1  christos 		if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
   3628   1.1  christos 			client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR;
   3629   1.1  christos 			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
   3630   1.3  christos 				     rpz_type, "NS address rewrite rrset",
   3631   1.1  christos 				     result);
   3632   1.1  christos 		}
   3633   1.9  christos 		CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip_rrset: unexpected "
   3634   1.9  christos 				      "result");
   3635   1.1  christos 		return (DNS_R_SERVFAIL);
   3636   1.1  christos 	}
   3637   1.1  christos 
   3638   1.1  christos 	/*
   3639   1.1  christos 	 * Check all of the IP addresses in the rdataset.
   3640   1.1  christos 	 */
   3641   1.1  christos 	for (result = dns_rdataset_first(*ip_rdatasetp);
   3642   1.9  christos 	     result == ISC_R_SUCCESS; result = dns_rdataset_next(*ip_rdatasetp))
   3643   1.9  christos 	{
   3644   1.1  christos 		dns_rdata_t rdata = DNS_RDATA_INIT;
   3645   1.1  christos 		dns_rdataset_current(*ip_rdatasetp, &rdata);
   3646   1.1  christos 		switch (rdata.type) {
   3647   1.1  christos 		case dns_rdatatype_a:
   3648   1.1  christos 			INSIST(rdata.length == 4);
   3649   1.1  christos 			memmove(&ina.s_addr, rdata.data, 4);
   3650   1.1  christos 			isc_netaddr_fromin(&netaddr, &ina);
   3651   1.1  christos 			break;
   3652   1.1  christos 		case dns_rdatatype_aaaa:
   3653   1.1  christos 			INSIST(rdata.length == 16);
   3654   1.1  christos 			memmove(in6a.s6_addr, rdata.data, 16);
   3655   1.1  christos 			isc_netaddr_fromin6(&netaddr, &in6a);
   3656   1.1  christos 			break;
   3657   1.1  christos 		default:
   3658   1.1  christos 			continue;
   3659   1.1  christos 		}
   3660   1.1  christos 
   3661   1.1  christos 		result = rpz_rewrite_ip(client, &netaddr, qtype, rpz_type,
   3662   1.1  christos 					zbits, p_rdatasetp);
   3663   1.9  christos 		if (result != ISC_R_SUCCESS) {
   3664   1.1  christos 			return (result);
   3665   1.9  christos 		}
   3666   1.1  christos 	}
   3667   1.1  christos 
   3668   1.1  christos 	return (ISC_R_SUCCESS);
   3669   1.1  christos }
   3670   1.1  christos 
   3671   1.1  christos /*
   3672   1.1  christos  * Look for IP addresses in A and AAAA rdatasets
   3673   1.1  christos  * that trigger all eligible IP or NSIP policy rules.
   3674   1.1  christos  */
   3675   1.1  christos static isc_result_t
   3676   1.1  christos rpz_rewrite_ip_rrsets(ns_client_t *client, dns_name_t *name,
   3677   1.1  christos 		      dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
   3678   1.9  christos 		      dns_rdataset_t **ip_rdatasetp, bool resuming) {
   3679   1.1  christos 	dns_rpz_st_t *st;
   3680   1.1  christos 	dns_dbversion_t *ip_version;
   3681   1.1  christos 	dns_db_t *ip_db;
   3682   1.1  christos 	dns_rdataset_t *p_rdataset;
   3683   1.1  christos 	isc_result_t result;
   3684   1.1  christos 
   3685   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrsets");
   3686   1.1  christos 
   3687   1.1  christos 	st = client->query.rpz_st;
   3688   1.1  christos 	ip_version = NULL;
   3689   1.1  christos 	ip_db = NULL;
   3690   1.1  christos 	p_rdataset = NULL;
   3691   1.1  christos 	if ((st->state & DNS_RPZ_DONE_IPv4) == 0 &&
   3692   1.9  christos 	    (qtype == dns_rdatatype_a || qtype == dns_rdatatype_any ||
   3693   1.9  christos 	     rpz_type == DNS_RPZ_TYPE_NSIP))
   3694   1.9  christos 	{
   3695   1.1  christos 		/*
   3696   1.1  christos 		 * Rewrite based on an IPv4 address that will appear
   3697   1.1  christos 		 * in the ANSWER section or if we are checking IP addresses.
   3698   1.1  christos 		 */
   3699   1.9  christos 		result = rpz_rewrite_ip_rrset(
   3700   1.9  christos 			client, name, qtype, rpz_type, dns_rdatatype_a, &ip_db,
   3701   1.9  christos 			ip_version, ip_rdatasetp, &p_rdataset, resuming);
   3702   1.9  christos 		if (result == ISC_R_SUCCESS) {
   3703   1.1  christos 			st->state |= DNS_RPZ_DONE_IPv4;
   3704   1.9  christos 		}
   3705   1.1  christos 	} else {
   3706   1.1  christos 		result = ISC_R_SUCCESS;
   3707   1.1  christos 	}
   3708   1.1  christos 	if (result == ISC_R_SUCCESS &&
   3709   1.9  christos 	    (qtype == dns_rdatatype_aaaa || qtype == dns_rdatatype_any ||
   3710   1.9  christos 	     rpz_type == DNS_RPZ_TYPE_NSIP))
   3711   1.9  christos 	{
   3712   1.1  christos 		/*
   3713   1.1  christos 		 * Rewrite based on IPv6 addresses that will appear
   3714   1.1  christos 		 * in the ANSWER section or if we are checking IP addresses.
   3715   1.1  christos 		 */
   3716   1.9  christos 		result = rpz_rewrite_ip_rrset(client, name, qtype, rpz_type,
   3717   1.9  christos 					      dns_rdatatype_aaaa, &ip_db,
   3718   1.9  christos 					      ip_version, ip_rdatasetp,
   3719   1.1  christos 					      &p_rdataset, resuming);
   3720   1.1  christos 	}
   3721   1.9  christos 	if (ip_db != NULL) {
   3722   1.1  christos 		dns_db_detach(&ip_db);
   3723   1.9  christos 	}
   3724   1.3  christos 	ns_client_putrdataset(client, &p_rdataset);
   3725   1.1  christos 	return (result);
   3726   1.1  christos }
   3727   1.1  christos 
   3728   1.1  christos /*
   3729   1.1  christos  * Try to rewrite a request for a qtype rdataset based on the trigger name
   3730   1.1  christos  * trig_name and rpz_type (DNS_RPZ_TYPE_QNAME or DNS_RPZ_TYPE_NSDNAME).
   3731   1.1  christos  * Record the results including the replacement rdataset if any
   3732   1.1  christos  * in client->query.rpz_st.
   3733   1.1  christos  * *rdatasetp is a scratch rdataset.
   3734   1.1  christos  */
   3735   1.1  christos static isc_result_t
   3736   1.1  christos rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name,
   3737   1.1  christos 		 dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
   3738   1.3  christos 		 dns_rpz_zbits_t allowed_zbits, bool recursed,
   3739   1.9  christos 		 dns_rdataset_t **rdatasetp) {
   3740   1.1  christos 	dns_rpz_zones_t *rpzs;
   3741   1.1  christos 	dns_rpz_zone_t *rpz;
   3742   1.1  christos 	dns_rpz_st_t *st;
   3743   1.1  christos 	dns_fixedname_t p_namef;
   3744   1.1  christos 	dns_name_t *p_name;
   3745   1.1  christos 	dns_rpz_zbits_t zbits;
   3746   1.1  christos 	dns_rpz_num_t rpz_num;
   3747   1.1  christos 	dns_zone_t *p_zone;
   3748   1.1  christos 	dns_db_t *p_db;
   3749   1.1  christos 	dns_dbversion_t *p_version;
   3750   1.1  christos 	dns_dbnode_t *p_node;
   3751   1.1  christos 	dns_rpz_policy_t policy;
   3752   1.1  christos 	isc_result_t result;
   3753   1.1  christos 
   3754   1.1  christos #ifndef USE_DNSRPS
   3755   1.1  christos 	UNUSED(recursed);
   3756   1.9  christos #endif /* ifndef USE_DNSRPS */
   3757   1.1  christos 
   3758   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name");
   3759   1.1  christos 
   3760   1.1  christos 	rpzs = client->view->rpzs;
   3761   1.1  christos 	st = client->query.rpz_st;
   3762   1.1  christos 
   3763   1.1  christos #ifdef USE_DNSRPS
   3764   1.1  christos 	if (st->popt.dnsrps_enabled) {
   3765   1.1  christos 		return (dnsrps_rewrite_name(client, trig_name, recursed,
   3766   1.9  christos 					    rpz_type, rdatasetp));
   3767   1.1  christos 	}
   3768   1.9  christos #endif /* ifdef USE_DNSRPS */
   3769   1.1  christos 
   3770   1.1  christos 	zbits = rpz_get_zbits(client, qtype, rpz_type);
   3771   1.1  christos 	zbits &= allowed_zbits;
   3772   1.9  christos 	if (zbits == 0) {
   3773   1.1  christos 		return (ISC_R_SUCCESS);
   3774   1.9  christos 	}
   3775   1.1  christos 
   3776   1.1  christos 	/*
   3777   1.1  christos 	 * Use the summary database to find the bit mask of policy zones
   3778   1.1  christos 	 * with policies for this trigger name. We do this even if there
   3779   1.1  christos 	 * is only one eligible policy zone so that wildcard triggers
   3780   1.1  christos 	 * are matched correctly, and not into their parent.
   3781   1.1  christos 	 */
   3782   1.1  christos 	zbits = dns_rpz_find_name(rpzs, rpz_type, zbits, trig_name);
   3783   1.9  christos 	if (zbits == 0) {
   3784   1.1  christos 		return (ISC_R_SUCCESS);
   3785   1.9  christos 	}
   3786   1.1  christos 
   3787   1.1  christos 	p_name = dns_fixedname_initname(&p_namef);
   3788   1.1  christos 
   3789   1.1  christos 	p_zone = NULL;
   3790   1.1  christos 	p_db = NULL;
   3791   1.1  christos 	p_node = NULL;
   3792   1.1  christos 
   3793   1.1  christos 	/*
   3794   1.1  christos 	 * Check the trigger name in every policy zone that the summary data
   3795   1.1  christos 	 * says has a hit for the trigger name.
   3796   1.1  christos 	 * Most of the time there are no eligible zones and the summary data
   3797   1.1  christos 	 * keeps us from getting this far.
   3798   1.1  christos 	 * We check the most eligible zone first and so usually check only
   3799   1.1  christos 	 * one policy zone.
   3800   1.1  christos 	 */
   3801   1.1  christos 	for (rpz_num = 0; zbits != 0; ++rpz_num, zbits >>= 1) {
   3802   1.9  christos 		if ((zbits & 1) == 0) {
   3803   1.1  christos 			continue;
   3804   1.9  christos 		}
   3805   1.1  christos 
   3806   1.1  christos 		/*
   3807   1.1  christos 		 * Do not check policy zones that cannot replace a previously
   3808   1.1  christos 		 * found policy.
   3809   1.1  christos 		 */
   3810   1.1  christos 		rpz = rpzs->zones[rpz_num];
   3811   1.1  christos 		if (st->m.policy != DNS_RPZ_POLICY_MISS) {
   3812   1.9  christos 			if (st->m.rpz->num < rpz->num) {
   3813   1.1  christos 				break;
   3814   1.9  christos 			}
   3815   1.9  christos 			if (st->m.rpz->num == rpz->num && st->m.type < rpz_type)
   3816   1.9  christos 			{
   3817   1.1  christos 				break;
   3818   1.9  christos 			}
   3819   1.1  christos 		}
   3820   1.1  christos 
   3821   1.1  christos 		/*
   3822   1.1  christos 		 * Get the next policy zone's record for this trigger name.
   3823   1.1  christos 		 */
   3824   1.1  christos 		result = rpz_get_p_name(client, p_name, rpz, rpz_type,
   3825   1.1  christos 					trig_name);
   3826   1.9  christos 		if (result != ISC_R_SUCCESS) {
   3827   1.1  christos 			continue;
   3828   1.9  christos 		}
   3829   1.9  christos 		result = rpz_find_p(client, trig_name, qtype, p_name, rpz,
   3830   1.9  christos 				    rpz_type, &p_zone, &p_db, &p_version,
   3831   1.9  christos 				    &p_node, rdatasetp, &policy);
   3832   1.1  christos 		switch (result) {
   3833   1.1  christos 		case DNS_R_NXDOMAIN:
   3834   1.1  christos 			/*
   3835   1.1  christos 			 * Continue after a missing policy record
   3836   1.1  christos 			 * contrary to the summary data.  The summary
   3837   1.1  christos 			 * data can out of date during races with and among
   3838   1.1  christos 			 * policy zone updates.
   3839   1.1  christos 			 */
   3840   1.9  christos 			CTRACE(ISC_LOG_ERROR, "rpz_rewrite_name: mismatched "
   3841   1.9  christos 					      "summary data; "
   3842   1.9  christos 					      "continuing");
   3843   1.1  christos 			continue;
   3844   1.1  christos 		case DNS_R_SERVFAIL:
   3845   1.1  christos 			rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
   3846   1.1  christos 			st->m.policy = DNS_RPZ_POLICY_ERROR;
   3847   1.1  christos 			return (DNS_R_SERVFAIL);
   3848   1.1  christos 		default:
   3849   1.1  christos 			/*
   3850   1.1  christos 			 * With more than one applicable policy, prefer
   3851   1.1  christos 			 * the earliest configured policy,
   3852   1.1  christos 			 * client-IP over QNAME over IP over NSDNAME over NSIP,
   3853   1.1  christos 			 * and the smallest name.
   3854   1.1  christos 			 * We known st->m.rpz->num >= rpz->num  and either
   3855   1.1  christos 			 * st->m.rpz->num > rpz->num or st->m.type >= rpz_type
   3856   1.1  christos 			 */
   3857   1.1  christos 			if (st->m.policy != DNS_RPZ_POLICY_MISS &&
   3858   1.1  christos 			    rpz->num == st->m.rpz->num &&
   3859   1.1  christos 			    (st->m.type < rpz_type ||
   3860   1.1  christos 			     (st->m.type == rpz_type &&
   3861   1.1  christos 			      0 >= dns_name_compare(p_name, st->p_name))))
   3862   1.9  christos 			{
   3863   1.1  christos 				continue;
   3864   1.9  christos 			}
   3865   1.4  christos 
   3866   1.1  christos 			if (rpz->policy != DNS_RPZ_POLICY_DISABLED) {
   3867   1.9  christos 				CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name: "
   3868   1.9  christos 							 "rpz_save_p");
   3869   1.9  christos 				rpz_save_p(st, rpz, rpz_type, policy, p_name, 0,
   3870   1.9  christos 					   result, &p_zone, &p_db, &p_node,
   3871   1.1  christos 					   rdatasetp, p_version);
   3872   1.1  christos 				/*
   3873   1.1  christos 				 * After a hit, higher numbered policy zones
   3874   1.1  christos 				 * are irrelevant
   3875   1.1  christos 				 */
   3876   1.1  christos 				rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
   3877   1.1  christos 				return (ISC_R_SUCCESS);
   3878   1.1  christos 			}
   3879   1.1  christos 			/*
   3880   1.1  christos 			 * Log DNS_RPZ_POLICY_DISABLED zones
   3881   1.1  christos 			 * and try the next eligible policy zone.
   3882   1.1  christos 			 */
   3883   1.9  christos 			rpz_log_rewrite(client, true, policy, rpz_type, p_zone,
   3884   1.9  christos 					p_name, NULL, rpz_num);
   3885   1.1  christos 			break;
   3886   1.1  christos 		}
   3887   1.1  christos 	}
   3888   1.1  christos 
   3889   1.1  christos 	rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
   3890   1.1  christos 	return (ISC_R_SUCCESS);
   3891   1.1  christos }
   3892   1.1  christos 
   3893   1.1  christos static void
   3894   1.1  christos rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname,
   3895   1.9  christos 		    isc_result_t result, int level, const char *str) {
   3896   1.1  christos 	dns_rpz_st_t *st;
   3897   1.1  christos 
   3898   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ns_skip");
   3899   1.1  christos 
   3900   1.1  christos 	st = client->query.rpz_st;
   3901   1.1  christos 
   3902   1.9  christos 	if (str != NULL) {
   3903   1.9  christos 		rpz_log_fail_helper(client, level, nsname, DNS_RPZ_TYPE_NSIP,
   3904   1.9  christos 				    DNS_RPZ_TYPE_NSDNAME, str, result);
   3905   1.9  christos 	}
   3906   1.1  christos 	if (st->r.ns_rdataset != NULL &&
   3907   1.9  christos 	    dns_rdataset_isassociated(st->r.ns_rdataset)) {
   3908   1.1  christos 		dns_rdataset_disassociate(st->r.ns_rdataset);
   3909   1.9  christos 	}
   3910   1.1  christos 
   3911   1.1  christos 	st->r.label--;
   3912   1.1  christos }
   3913   1.1  christos 
   3914   1.1  christos /*
   3915   1.1  christos  * RPZ query result types
   3916   1.1  christos  */
   3917   1.1  christos typedef enum {
   3918   1.1  christos 	qresult_type_done = 0,
   3919   1.1  christos 	qresult_type_restart = 1,
   3920   1.1  christos 	qresult_type_recurse = 2
   3921   1.1  christos } qresult_type_t;
   3922   1.1  christos 
   3923   1.1  christos /*
   3924   1.1  christos  * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting.
   3925   1.1  christos  */
   3926   1.1  christos static isc_result_t
   3927   1.9  christos rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult,
   3928   1.9  christos 	    bool resuming, dns_rdataset_t *ordataset, dns_rdataset_t *osigset) {
   3929   1.1  christos 	dns_rpz_zones_t *rpzs;
   3930   1.1  christos 	dns_rpz_st_t *st;
   3931   1.1  christos 	dns_rdataset_t *rdataset;
   3932   1.1  christos 	dns_fixedname_t nsnamef;
   3933   1.1  christos 	dns_name_t *nsname;
   3934   1.1  christos 	qresult_type_t qresult_type;
   3935   1.1  christos 	dns_rpz_zbits_t zbits;
   3936   1.1  christos 	isc_result_t result = ISC_R_SUCCESS;
   3937   1.1  christos 	dns_rpz_have_t have;
   3938   1.1  christos 	dns_rpz_popt_t popt;
   3939   1.1  christos 	int rpz_ver;
   3940   1.1  christos #ifdef USE_DNSRPS
   3941   1.1  christos 	librpz_emsg_t emsg;
   3942   1.9  christos #endif /* ifdef USE_DNSRPS */
   3943   1.1  christos 
   3944   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite");
   3945   1.1  christos 
   3946   1.1  christos 	rpzs = client->view->rpzs;
   3947   1.1  christos 	st = client->query.rpz_st;
   3948   1.1  christos 
   3949   1.1  christos 	if (rpzs == NULL ||
   3950   1.9  christos 	    (st != NULL && (st->state & DNS_RPZ_REWRITTEN) != 0)) {
   3951   1.1  christos 		return (DNS_R_DISALLOWED);
   3952   1.9  christos 	}
   3953   1.1  christos 
   3954   1.1  christos 	RWLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   3955   1.1  christos 	if ((rpzs->p.num_zones == 0 && !rpzs->p.dnsrps_enabled) ||
   3956   1.1  christos 	    (!RECURSIONOK(client) && rpzs->p.no_rd_ok == 0) ||
   3957   1.1  christos 	    !rpz_ck_dnssec(client, qresult, ordataset, osigset))
   3958   1.1  christos 	{
   3959   1.1  christos 		RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   3960   1.1  christos 		return (DNS_R_DISALLOWED);
   3961   1.1  christos 	}
   3962   1.1  christos 	have = rpzs->have;
   3963   1.1  christos 	popt = rpzs->p;
   3964   1.1  christos 	rpz_ver = rpzs->rpz_ver;
   3965   1.1  christos 	RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   3966   1.1  christos 
   3967   1.1  christos #ifndef USE_DNSRPS
   3968   1.1  christos 	INSIST(!popt.dnsrps_enabled);
   3969   1.9  christos #endif /* ifndef USE_DNSRPS */
   3970   1.1  christos 
   3971   1.1  christos 	if (st == NULL) {
   3972   1.1  christos 		st = isc_mem_get(client->mctx, sizeof(*st));
   3973   1.1  christos 		st->state = 0;
   3974   1.1  christos 		st->rpsdb = NULL;
   3975   1.1  christos 	}
   3976   1.1  christos 	if (st->state == 0) {
   3977   1.1  christos 		st->state |= DNS_RPZ_ACTIVE;
   3978   1.1  christos 		memset(&st->m, 0, sizeof(st->m));
   3979   1.1  christos 		st->m.type = DNS_RPZ_TYPE_BAD;
   3980   1.1  christos 		st->m.policy = DNS_RPZ_POLICY_MISS;
   3981   1.1  christos 		st->m.ttl = ~0;
   3982   1.1  christos 		memset(&st->r, 0, sizeof(st->r));
   3983   1.1  christos 		memset(&st->q, 0, sizeof(st->q));
   3984   1.1  christos 		st->p_name = dns_fixedname_initname(&st->_p_namef);
   3985   1.1  christos 		st->r_name = dns_fixedname_initname(&st->_r_namef);
   3986   1.1  christos 		st->fname = dns_fixedname_initname(&st->_fnamef);
   3987   1.1  christos 		st->have = have;
   3988   1.1  christos 		st->popt = popt;
   3989   1.1  christos 		st->rpz_ver = rpz_ver;
   3990   1.1  christos 		client->query.rpz_st = st;
   3991   1.1  christos #ifdef USE_DNSRPS
   3992   1.1  christos 		if (popt.dnsrps_enabled) {
   3993   1.1  christos 			if (st->rpsdb != NULL) {
   3994   1.1  christos 				dns_db_detach(&st->rpsdb);
   3995   1.1  christos 			}
   3996   1.9  christos 			result = dns_dnsrps_rewrite_init(
   3997   1.9  christos 				&emsg, st, rpzs, client->query.qname,
   3998   1.9  christos 				client->mctx, RECURSIONOK(client));
   3999   1.1  christos 			if (result != ISC_R_SUCCESS) {
   4000   1.9  christos 				rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
   4001   1.9  christos 					     DNS_RPZ_TYPE_QNAME, emsg.c,
   4002   1.9  christos 					     result);
   4003   1.1  christos 				st->m.policy = DNS_RPZ_POLICY_ERROR;
   4004   1.1  christos 				return (ISC_R_SUCCESS);
   4005   1.1  christos 			}
   4006   1.1  christos 		}
   4007   1.9  christos #endif /* ifdef USE_DNSRPS */
   4008   1.1  christos 	}
   4009   1.1  christos 
   4010   1.1  christos 	/*
   4011   1.1  christos 	 * There is nothing to rewrite if the main query failed.
   4012   1.1  christos 	 */
   4013   1.1  christos 	switch (qresult) {
   4014   1.1  christos 	case ISC_R_SUCCESS:
   4015   1.1  christos 	case DNS_R_GLUE:
   4016   1.1  christos 	case DNS_R_ZONECUT:
   4017   1.1  christos 		qresult_type = qresult_type_done;
   4018   1.1  christos 		break;
   4019   1.1  christos 	case DNS_R_EMPTYNAME:
   4020   1.1  christos 	case DNS_R_NXRRSET:
   4021   1.1  christos 	case DNS_R_NXDOMAIN:
   4022   1.1  christos 	case DNS_R_EMPTYWILD:
   4023   1.1  christos 	case DNS_R_NCACHENXDOMAIN:
   4024   1.1  christos 	case DNS_R_NCACHENXRRSET:
   4025   1.3  christos 	case DNS_R_COVERINGNSEC:
   4026   1.1  christos 	case DNS_R_CNAME:
   4027   1.1  christos 	case DNS_R_DNAME:
   4028   1.1  christos 		qresult_type = qresult_type_restart;
   4029   1.1  christos 		break;
   4030   1.1  christos 	case DNS_R_DELEGATION:
   4031   1.1  christos 	case ISC_R_NOTFOUND:
   4032   1.1  christos 		/*
   4033   1.1  christos 		 * If recursion is on, do only tentative rewriting.
   4034   1.1  christos 		 * If recursion is off, this the normal and only time we
   4035   1.1  christos 		 * can rewrite.
   4036   1.1  christos 		 */
   4037   1.9  christos 		if (RECURSIONOK(client)) {
   4038   1.1  christos 			qresult_type = qresult_type_recurse;
   4039   1.9  christos 		} else {
   4040   1.1  christos 			qresult_type = qresult_type_restart;
   4041   1.9  christos 		}
   4042   1.1  christos 		break;
   4043   1.1  christos 	case ISC_R_FAILURE:
   4044   1.1  christos 	case ISC_R_TIMEDOUT:
   4045   1.1  christos 	case DNS_R_BROKENCHAIN:
   4046   1.1  christos 		rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, NULL,
   4047   1.1  christos 			     DNS_RPZ_TYPE_QNAME,
   4048   1.3  christos 			     "stop on qresult in rpz_rewrite()", qresult);
   4049   1.1  christos 		return (ISC_R_SUCCESS);
   4050   1.1  christos 	default:
   4051   1.1  christos 		rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, NULL,
   4052   1.1  christos 			     DNS_RPZ_TYPE_QNAME,
   4053   1.3  christos 			     "stop on unrecognized qresult in rpz_rewrite()",
   4054   1.1  christos 			     qresult);
   4055   1.1  christos 		return (ISC_R_SUCCESS);
   4056   1.1  christos 	}
   4057   1.1  christos 
   4058   1.1  christos 	rdataset = NULL;
   4059   1.1  christos 
   4060   1.1  christos 	if ((st->state & (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) !=
   4061   1.1  christos 	    (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME))
   4062   1.1  christos 	{
   4063   1.1  christos 		isc_netaddr_t netaddr;
   4064   1.1  christos 		dns_rpz_zbits_t allowed;
   4065   1.1  christos 
   4066   1.1  christos 		if (!st->popt.dnsrps_enabled &&
   4067   1.9  christos 		    qresult_type == qresult_type_recurse) {
   4068   1.1  christos 			/*
   4069   1.1  christos 			 * This request needs recursion that has not been done.
   4070   1.1  christos 			 * Get bits for the policy zones that do not need
   4071   1.1  christos 			 * to wait for the results of recursion.
   4072   1.1  christos 			 */
   4073   1.1  christos 			allowed = st->have.qname_skip_recurse;
   4074   1.1  christos 			if (allowed == 0) {
   4075   1.1  christos 				return (ISC_R_SUCCESS);
   4076   1.1  christos 			}
   4077   1.1  christos 		} else {
   4078   1.1  christos 			allowed = DNS_RPZ_ALL_ZBITS;
   4079   1.1  christos 		}
   4080   1.1  christos 
   4081   1.1  christos 		/*
   4082   1.1  christos 		 * Check once for triggers for the client IP address.
   4083   1.1  christos 		 */
   4084   1.1  christos 		if ((st->state & DNS_RPZ_DONE_CLIENT_IP) == 0) {
   4085   1.1  christos 			zbits = rpz_get_zbits(client, dns_rdatatype_none,
   4086   1.1  christos 					      DNS_RPZ_TYPE_CLIENT_IP);
   4087   1.1  christos 			zbits &= allowed;
   4088   1.1  christos 			if (zbits != 0) {
   4089   1.1  christos 				isc_netaddr_fromsockaddr(&netaddr,
   4090   1.1  christos 							 &client->peeraddr);
   4091   1.1  christos 				result = rpz_rewrite_ip(client, &netaddr, qtype,
   4092   1.1  christos 							DNS_RPZ_TYPE_CLIENT_IP,
   4093   1.1  christos 							zbits, &rdataset);
   4094   1.9  christos 				if (result != ISC_R_SUCCESS) {
   4095   1.1  christos 					goto cleanup;
   4096   1.9  christos 				}
   4097   1.1  christos 			}
   4098   1.1  christos 		}
   4099   1.1  christos 
   4100   1.1  christos 		/*
   4101   1.1  christos 		 * Check triggers for the query name if this is the first time
   4102   1.1  christos 		 * for the current qname.
   4103   1.1  christos 		 * There is a first time for each name in a CNAME chain
   4104   1.1  christos 		 */
   4105   1.1  christos 		if ((st->state & DNS_RPZ_DONE_QNAME) == 0) {
   4106   1.3  christos 			bool norec = (qresult_type != qresult_type_recurse);
   4107   1.1  christos 			result = rpz_rewrite_name(client, client->query.qname,
   4108   1.1  christos 						  qtype, DNS_RPZ_TYPE_QNAME,
   4109   1.9  christos 						  allowed, norec, &rdataset);
   4110   1.9  christos 			if (result != ISC_R_SUCCESS) {
   4111   1.1  christos 				goto cleanup;
   4112   1.9  christos 			}
   4113   1.1  christos 
   4114   1.1  christos 			/*
   4115   1.1  christos 			 * Check IPv4 addresses in A RRs next.
   4116   1.1  christos 			 * Reset to the start of the NS names.
   4117   1.1  christos 			 */
   4118   1.1  christos 			st->r.label = dns_name_countlabels(client->query.qname);
   4119   1.1  christos 			st->state &= ~(DNS_RPZ_DONE_QNAME_IP |
   4120   1.1  christos 				       DNS_RPZ_DONE_IPv4);
   4121   1.1  christos 		}
   4122   1.1  christos 
   4123   1.1  christos 		/*
   4124   1.1  christos 		 * Quit if this was an attempt to find a qname or
   4125   1.1  christos 		 * client-IP trigger before recursion.
   4126   1.1  christos 		 * We will be back if no pre-recursion triggers hit.
   4127   1.1  christos 		 * For example, consider 2 policy zones, both with qname and
   4128   1.1  christos 		 * IP address triggers.  If the qname misses the 1st zone,
   4129   1.1  christos 		 * then we cannot know whether a hit for the qname in the
   4130   1.1  christos 		 * 2nd zone matters until after recursing to get the A RRs and
   4131   1.1  christos 		 * testing them in the first zone.
   4132   1.1  christos 		 * Do not bother saving the work from this attempt,
   4133   1.9  christos 		 * because recursion is so slow.
   4134   1.1  christos 		 */
   4135   1.9  christos 		if (qresult_type == qresult_type_recurse) {
   4136   1.1  christos 			goto cleanup;
   4137   1.9  christos 		}
   4138   1.1  christos 
   4139   1.1  christos 		/*
   4140   1.1  christos 		 * DNS_RPZ_DONE_QNAME but not DNS_RPZ_DONE_CLIENT_IP
   4141   1.1  christos 		 * is reset at the end of dealing with each CNAME.
   4142   1.1  christos 		 */
   4143   1.1  christos 		st->state |= (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME);
   4144   1.1  christos 	}
   4145   1.1  christos 
   4146   1.1  christos 	/*
   4147   1.1  christos 	 * Check known IP addresses for the query name if the database lookup
   4148   1.1  christos 	 * resulted in some addresses (qresult_type == qresult_type_done)
   4149   1.1  christos 	 * and if we have not already checked them.
   4150   1.1  christos 	 * Any recursion required for the query has already happened.
   4151   1.1  christos 	 * Do not check addresses that will not be in the ANSWER section.
   4152   1.1  christos 	 */
   4153   1.1  christos 	if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 &&
   4154   1.1  christos 	    qresult_type == qresult_type_done &&
   4155   1.9  christos 	    rpz_get_zbits(client, qtype, DNS_RPZ_TYPE_IP) != 0)
   4156   1.9  christos 	{
   4157   1.9  christos 		result = rpz_rewrite_ip_rrsets(client, client->query.qname,
   4158   1.9  christos 					       qtype, DNS_RPZ_TYPE_IP,
   4159   1.1  christos 					       &rdataset, resuming);
   4160   1.9  christos 		if (result != ISC_R_SUCCESS) {
   4161   1.1  christos 			goto cleanup;
   4162   1.9  christos 		}
   4163   1.1  christos 		/*
   4164   1.1  christos 		 * We are finished checking the IP addresses for the qname.
   4165   1.9  christos 		 * Start with IPv4 if we will check NS IP addresses.
   4166   1.1  christos 		 */
   4167   1.1  christos 		st->state |= DNS_RPZ_DONE_QNAME_IP;
   4168   1.1  christos 		st->state &= ~DNS_RPZ_DONE_IPv4;
   4169   1.1  christos 	}
   4170   1.1  christos 
   4171   1.1  christos 	/*
   4172   1.1  christos 	 * Stop looking for rules if there are none of the other kinds
   4173   1.1  christos 	 * that could override what we already have.
   4174   1.1  christos 	 */
   4175   1.9  christos 	if (rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSDNAME) ==
   4176   1.9  christos 		    0 &&
   4177   1.9  christos 	    rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSIP) == 0)
   4178   1.9  christos 	{
   4179   1.1  christos 		result = ISC_R_SUCCESS;
   4180   1.1  christos 		goto cleanup;
   4181   1.1  christos 	}
   4182   1.1  christos 
   4183   1.1  christos 	dns_fixedname_init(&nsnamef);
   4184   1.1  christos 	dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef));
   4185   1.1  christos 	while (st->r.label > st->popt.min_ns_labels) {
   4186   1.1  christos 		/*
   4187   1.1  christos 		 * Get NS rrset for each domain in the current qname.
   4188   1.1  christos 		 */
   4189   1.1  christos 		if (st->r.label == dns_name_countlabels(client->query.qname)) {
   4190   1.1  christos 			nsname = client->query.qname;
   4191   1.1  christos 		} else {
   4192   1.1  christos 			nsname = dns_fixedname_name(&nsnamef);
   4193   1.9  christos 			dns_name_split(client->query.qname, st->r.label, NULL,
   4194   1.9  christos 				       nsname);
   4195   1.1  christos 		}
   4196   1.1  christos 		if (st->r.ns_rdataset == NULL ||
   4197   1.9  christos 		    !dns_rdataset_isassociated(st->r.ns_rdataset)) {
   4198   1.1  christos 			dns_db_t *db = NULL;
   4199   1.1  christos 			result = rpz_rrset_find(client, nsname,
   4200   1.1  christos 						dns_rdatatype_ns,
   4201   1.9  christos 						DNS_RPZ_TYPE_NSDNAME, &db, NULL,
   4202   1.9  christos 						&st->r.ns_rdataset, resuming);
   4203   1.9  christos 			if (db != NULL) {
   4204   1.1  christos 				dns_db_detach(&db);
   4205   1.9  christos 			}
   4206   1.9  christos 			if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
   4207   1.1  christos 				goto cleanup;
   4208   1.9  christos 			}
   4209   1.1  christos 			switch (result) {
   4210   1.1  christos 			case ISC_R_SUCCESS:
   4211   1.1  christos 				result = dns_rdataset_first(st->r.ns_rdataset);
   4212   1.9  christos 				if (result != ISC_R_SUCCESS) {
   4213   1.1  christos 					goto cleanup;
   4214   1.9  christos 				}
   4215   1.1  christos 				st->state &= ~(DNS_RPZ_DONE_NSDNAME |
   4216   1.1  christos 					       DNS_RPZ_DONE_IPv4);
   4217   1.1  christos 				break;
   4218   1.1  christos 			case DNS_R_DELEGATION:
   4219   1.1  christos 			case DNS_R_DUPLICATE:
   4220   1.1  christos 			case DNS_R_DROP:
   4221   1.1  christos 				goto cleanup;
   4222   1.1  christos 			case DNS_R_EMPTYNAME:
   4223   1.1  christos 			case DNS_R_NXRRSET:
   4224   1.1  christos 			case DNS_R_EMPTYWILD:
   4225   1.1  christos 			case DNS_R_NXDOMAIN:
   4226   1.1  christos 			case DNS_R_NCACHENXDOMAIN:
   4227   1.1  christos 			case DNS_R_NCACHENXRRSET:
   4228   1.1  christos 			case ISC_R_NOTFOUND:
   4229   1.1  christos 			case DNS_R_CNAME:
   4230   1.1  christos 			case DNS_R_DNAME:
   4231   1.9  christos 				rpz_rewrite_ns_skip(client, nsname, result, 0,
   4232   1.9  christos 						    NULL);
   4233   1.1  christos 				continue;
   4234   1.1  christos 			case ISC_R_TIMEDOUT:
   4235   1.1  christos 			case DNS_R_BROKENCHAIN:
   4236   1.1  christos 			case ISC_R_FAILURE:
   4237   1.1  christos 				rpz_rewrite_ns_skip(client, nsname, result,
   4238   1.9  christos 						    DNS_RPZ_DEBUG_LEVEL3,
   4239   1.9  christos 						    " NS rpz_rrset_find()");
   4240   1.1  christos 				continue;
   4241   1.1  christos 			default:
   4242   1.1  christos 				rpz_rewrite_ns_skip(client, nsname, result,
   4243   1.9  christos 						    DNS_RPZ_INFO_LEVEL,
   4244   1.9  christos 						    " unrecognized NS"
   4245   1.9  christos 						    " rpz_rrset_find()");
   4246   1.1  christos 				continue;
   4247   1.1  christos 			}
   4248   1.1  christos 		}
   4249   1.1  christos 		/*
   4250   1.1  christos 		 * Check all NS names.
   4251   1.1  christos 		 */
   4252   1.1  christos 		do {
   4253   1.1  christos 			dns_rdata_ns_t ns;
   4254   1.1  christos 			dns_rdata_t nsrdata = DNS_RDATA_INIT;
   4255   1.1  christos 
   4256   1.1  christos 			dns_rdataset_current(st->r.ns_rdataset, &nsrdata);
   4257   1.1  christos 			result = dns_rdata_tostruct(&nsrdata, &ns, NULL);
   4258   1.3  christos 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4259   1.1  christos 			dns_rdata_reset(&nsrdata);
   4260   1.3  christos 
   4261   1.1  christos 			/*
   4262   1.1  christos 			 * Do nothing about "NS ."
   4263   1.1  christos 			 */
   4264   1.1  christos 			if (dns_name_equal(&ns.name, dns_rootname)) {
   4265   1.1  christos 				dns_rdata_freestruct(&ns);
   4266   1.1  christos 				result = dns_rdataset_next(st->r.ns_rdataset);
   4267   1.1  christos 				continue;
   4268   1.1  christos 			}
   4269   1.1  christos 			/*
   4270   1.1  christos 			 * Check this NS name if we did not handle it
   4271   1.1  christos 			 * during a previous recursion.
   4272   1.1  christos 			 */
   4273   1.1  christos 			if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0) {
   4274   1.9  christos 				result = rpz_rewrite_name(
   4275   1.9  christos 					client, &ns.name, qtype,
   4276   1.9  christos 					DNS_RPZ_TYPE_NSDNAME, DNS_RPZ_ALL_ZBITS,
   4277   1.9  christos 					true, &rdataset);
   4278   1.1  christos 				if (result != ISC_R_SUCCESS) {
   4279   1.1  christos 					dns_rdata_freestruct(&ns);
   4280   1.1  christos 					goto cleanup;
   4281   1.1  christos 				}
   4282   1.1  christos 				st->state |= DNS_RPZ_DONE_NSDNAME;
   4283   1.1  christos 			}
   4284   1.1  christos 			/*
   4285   1.1  christos 			 * Check all IP addresses for this NS name.
   4286   1.1  christos 			 */
   4287   1.1  christos 			result = rpz_rewrite_ip_rrsets(client, &ns.name, qtype,
   4288   1.1  christos 						       DNS_RPZ_TYPE_NSIP,
   4289   1.1  christos 						       &rdataset, resuming);
   4290   1.1  christos 			dns_rdata_freestruct(&ns);
   4291   1.9  christos 			if (result != ISC_R_SUCCESS) {
   4292   1.1  christos 				goto cleanup;
   4293   1.9  christos 			}
   4294   1.1  christos 			st->state &= ~(DNS_RPZ_DONE_NSDNAME |
   4295   1.1  christos 				       DNS_RPZ_DONE_IPv4);
   4296   1.1  christos 			result = dns_rdataset_next(st->r.ns_rdataset);
   4297   1.1  christos 		} while (result == ISC_R_SUCCESS);
   4298   1.1  christos 		dns_rdataset_disassociate(st->r.ns_rdataset);
   4299   1.1  christos 		st->r.label--;
   4300   1.1  christos 
   4301   1.1  christos 		if (rpz_get_zbits(client, dns_rdatatype_any,
   4302   1.1  christos 				  DNS_RPZ_TYPE_NSDNAME) == 0 &&
   4303   1.1  christos 		    rpz_get_zbits(client, dns_rdatatype_any,
   4304   1.1  christos 				  DNS_RPZ_TYPE_NSIP) == 0)
   4305   1.9  christos 		{
   4306   1.1  christos 			break;
   4307   1.9  christos 		}
   4308   1.1  christos 	}
   4309   1.1  christos 
   4310   1.1  christos 	/*
   4311   1.1  christos 	 * Use the best hit, if any.
   4312   1.1  christos 	 */
   4313   1.1  christos 	result = ISC_R_SUCCESS;
   4314   1.1  christos 
   4315   1.1  christos cleanup:
   4316   1.1  christos #ifdef USE_DNSRPS
   4317   1.9  christos 	if (st->popt.dnsrps_enabled && st->m.policy != DNS_RPZ_POLICY_ERROR &&
   4318   1.1  christos 	    !dnsrps_set_p(&emsg, client, st, qtype, &rdataset,
   4319   1.3  christos 			  (qresult_type != qresult_type_recurse)))
   4320   1.1  christos 	{
   4321   1.1  christos 		rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
   4322   1.1  christos 			     DNS_RPZ_TYPE_BAD, emsg.c, DNS_R_SERVFAIL);
   4323   1.1  christos 		st->m.policy = DNS_RPZ_POLICY_ERROR;
   4324   1.1  christos 	}
   4325   1.9  christos #endif /* ifdef USE_DNSRPS */
   4326   1.1  christos 	if (st->m.policy != DNS_RPZ_POLICY_MISS &&
   4327   1.1  christos 	    st->m.policy != DNS_RPZ_POLICY_ERROR &&
   4328   1.1  christos 	    st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN)
   4329   1.9  christos 	{
   4330   1.1  christos 		st->m.policy = st->m.rpz->policy;
   4331   1.9  christos 	}
   4332   1.1  christos 	if (st->m.policy == DNS_RPZ_POLICY_MISS ||
   4333   1.1  christos 	    st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
   4334   1.9  christos 	    st->m.policy == DNS_RPZ_POLICY_ERROR)
   4335   1.9  christos 	{
   4336   1.1  christos 		if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
   4337   1.9  christos 		    result != DNS_R_DELEGATION) {
   4338   1.9  christos 			rpz_log_rewrite(client, false, st->m.policy, st->m.type,
   4339   1.9  christos 					st->m.zone, st->p_name, NULL,
   4340   1.9  christos 					st->m.rpz->num);
   4341   1.9  christos 		}
   4342   1.1  christos 		rpz_match_clear(st);
   4343   1.1  christos 	}
   4344   1.1  christos 	if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
   4345   1.1  christos 		CTRACE(ISC_LOG_ERROR, "SERVFAIL due to RPZ policy");
   4346   1.1  christos 		st->m.type = DNS_RPZ_TYPE_BAD;
   4347   1.1  christos 		result = DNS_R_SERVFAIL;
   4348   1.1  christos 	}
   4349   1.3  christos 	ns_client_putrdataset(client, &rdataset);
   4350   1.9  christos 	if ((st->state & DNS_RPZ_RECURSING) == 0) {
   4351   1.1  christos 		rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset);
   4352   1.9  christos 	}
   4353   1.1  christos 
   4354   1.1  christos 	return (result);
   4355   1.1  christos }
   4356   1.1  christos 
   4357   1.1  christos /*
   4358   1.1  christos  * See if response policy zone rewriting is allowed by a lack of interest
   4359   1.1  christos  * by the client in DNSSEC or a lack of signatures.
   4360   1.1  christos  */
   4361   1.3  christos static bool
   4362   1.1  christos rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult,
   4363   1.9  christos 	      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
   4364   1.1  christos 	dns_fixedname_t fixed;
   4365   1.1  christos 	dns_name_t *found;
   4366   1.1  christos 	dns_rdataset_t trdataset;
   4367   1.1  christos 	dns_rdatatype_t type;
   4368   1.1  christos 	isc_result_t result;
   4369   1.1  christos 
   4370   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "rpz_ck_dnssec");
   4371   1.1  christos 
   4372   1.9  christos 	if (client->view->rpzs->p.break_dnssec || !WANTDNSSEC(client)) {
   4373   1.3  christos 		return (true);
   4374   1.9  christos 	}
   4375   1.1  christos 
   4376   1.1  christos 	/*
   4377   1.1  christos 	 * We do not know if there are signatures if we have not recursed
   4378   1.1  christos 	 * for them.
   4379   1.1  christos 	 */
   4380   1.9  christos 	if (qresult == DNS_R_DELEGATION || qresult == ISC_R_NOTFOUND) {
   4381   1.3  christos 		return (false);
   4382   1.9  christos 	}
   4383   1.1  christos 
   4384   1.9  christos 	if (sigrdataset == NULL) {
   4385   1.3  christos 		return (true);
   4386   1.9  christos 	}
   4387   1.9  christos 	if (dns_rdataset_isassociated(sigrdataset)) {
   4388   1.3  christos 		return (false);
   4389   1.9  christos 	}
   4390   1.1  christos 
   4391   1.1  christos 	/*
   4392   1.1  christos 	 * We are happy to rewrite nothing.
   4393   1.1  christos 	 */
   4394   1.9  christos 	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
   4395   1.3  christos 		return (true);
   4396   1.9  christos 	}
   4397   1.1  christos 	/*
   4398   1.1  christos 	 * Do not rewrite if there is any sign of signatures.
   4399   1.1  christos 	 */
   4400   1.1  christos 	if (rdataset->type == dns_rdatatype_nsec ||
   4401   1.1  christos 	    rdataset->type == dns_rdatatype_nsec3 ||
   4402   1.1  christos 	    rdataset->type == dns_rdatatype_rrsig)
   4403   1.9  christos 	{
   4404   1.3  christos 		return (false);
   4405   1.9  christos 	}
   4406   1.1  christos 
   4407   1.1  christos 	/*
   4408   1.1  christos 	 * Look for a signature in a negative cache rdataset.
   4409   1.1  christos 	 */
   4410   1.9  christos 	if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0) {
   4411   1.3  christos 		return (true);
   4412   1.9  christos 	}
   4413   1.1  christos 	found = dns_fixedname_initname(&fixed);
   4414   1.1  christos 	dns_rdataset_init(&trdataset);
   4415   1.9  christos 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   4416   1.9  christos 	     result = dns_rdataset_next(rdataset))
   4417   1.9  christos 	{
   4418   1.1  christos 		dns_ncache_current(rdataset, found, &trdataset);
   4419   1.1  christos 		type = trdataset.type;
   4420   1.1  christos 		dns_rdataset_disassociate(&trdataset);
   4421   1.9  christos 		if (type == dns_rdatatype_nsec || type == dns_rdatatype_nsec3 ||
   4422   1.1  christos 		    type == dns_rdatatype_rrsig)
   4423   1.9  christos 		{
   4424   1.3  christos 			return (false);
   4425   1.9  christos 		}
   4426   1.1  christos 	}
   4427   1.3  christos 	return (true);
   4428   1.1  christos }
   4429   1.1  christos 
   4430   1.1  christos /*
   4431   1.1  christos  * Extract a network address from the RDATA of an A or AAAA
   4432   1.1  christos  * record.
   4433   1.1  christos  *
   4434   1.1  christos  * Returns:
   4435   1.1  christos  *	ISC_R_SUCCESS
   4436   1.1  christos  *	ISC_R_NOTIMPLEMENTED	The rdata is not a known address type.
   4437   1.1  christos  */
   4438   1.1  christos static isc_result_t
   4439   1.1  christos rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
   4440   1.1  christos 	struct in_addr ina;
   4441   1.1  christos 	struct in6_addr in6a;
   4442   1.1  christos 
   4443   1.1  christos 	switch (rdata->type) {
   4444   1.1  christos 	case dns_rdatatype_a:
   4445   1.1  christos 		INSIST(rdata->length == 4);
   4446   1.1  christos 		memmove(&ina.s_addr, rdata->data, 4);
   4447   1.1  christos 		isc_netaddr_fromin(netaddr, &ina);
   4448   1.1  christos 		return (ISC_R_SUCCESS);
   4449   1.1  christos 	case dns_rdatatype_aaaa:
   4450   1.1  christos 		INSIST(rdata->length == 16);
   4451   1.1  christos 		memmove(in6a.s6_addr, rdata->data, 16);
   4452   1.1  christos 		isc_netaddr_fromin6(netaddr, &in6a);
   4453   1.1  christos 		return (ISC_R_SUCCESS);
   4454   1.1  christos 	default:
   4455   1.1  christos 		return (ISC_R_NOTIMPLEMENTED);
   4456   1.1  christos 	}
   4457   1.1  christos }
   4458   1.1  christos 
   4459   1.1  christos static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
   4460   1.1  christos static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
   4461   1.1  christos static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
   4462   1.1  christos 
   4463   1.1  christos static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
   4464   1.1  christos 
   4465   1.1  christos static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
   4466   1.1  christos static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
   4467   1.1  christos static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
   4468   1.1  christos static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
   4469   1.1  christos static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
   4470   1.1  christos static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
   4471   1.1  christos static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
   4472   1.1  christos static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
   4473   1.1  christos static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
   4474   1.1  christos static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
   4475   1.1  christos static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
   4476   1.1  christos static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
   4477   1.1  christos static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
   4478   1.1  christos static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
   4479   1.1  christos static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
   4480   1.1  christos static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
   4481   1.1  christos 
   4482   1.1  christos static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
   4483   1.1  christos 
   4484   1.1  christos static dns_name_t rfc1918names[] = {
   4485   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
   4486   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
   4487   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
   4488   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
   4489   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
   4490   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
   4491   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
   4492   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
   4493   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
   4494   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
   4495   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
   4496   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
   4497   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
   4498   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
   4499   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
   4500   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
   4501   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
   4502   1.1  christos 	DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
   4503   1.1  christos };
   4504   1.1  christos 
   4505   1.1  christos static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
   4506   1.9  christos static unsigned char hostmaster_data[] = "\012hostmaster\014root-"
   4507   1.9  christos 					 "servers\003org";
   4508   1.1  christos 
   4509   1.1  christos static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
   4510   1.1  christos static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
   4511   1.1  christos 
   4512   1.9  christos static dns_name_t const prisoner = DNS_NAME_INITABSOLUTE(prisoner_data,
   4513   1.9  christos 							 prisoner_offsets);
   4514   1.9  christos static dns_name_t const hostmaster = DNS_NAME_INITABSOLUTE(hostmaster_data,
   4515   1.9  christos 							   hostmaster_offsets);
   4516   1.1  christos 
   4517   1.1  christos static void
   4518   1.1  christos warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
   4519   1.1  christos 	unsigned int i;
   4520   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4521   1.1  christos 	dns_rdata_soa_t soa;
   4522   1.1  christos 	dns_rdataset_t found;
   4523   1.1  christos 	isc_result_t result;
   4524   1.1  christos 
   4525   1.9  christos 	for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) {
   4526   1.1  christos 		if (dns_name_issubdomain(fname, &rfc1918names[i])) {
   4527   1.1  christos 			dns_rdataset_init(&found);
   4528   1.9  christos 			result = dns_ncache_getrdataset(
   4529   1.9  christos 				rdataset, &rfc1918names[i], dns_rdatatype_soa,
   4530   1.9  christos 				&found);
   4531   1.9  christos 			if (result != ISC_R_SUCCESS) {
   4532   1.1  christos 				return;
   4533   1.9  christos 			}
   4534   1.1  christos 
   4535   1.1  christos 			result = dns_rdataset_first(&found);
   4536   1.1  christos 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4537   1.1  christos 			dns_rdataset_current(&found, &rdata);
   4538   1.1  christos 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
   4539   1.1  christos 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4540   1.1  christos 			if (dns_name_equal(&soa.origin, &prisoner) &&
   4541   1.9  christos 			    dns_name_equal(&soa.contact, &hostmaster))
   4542   1.9  christos 			{
   4543   1.1  christos 				char buf[DNS_NAME_FORMATSIZE];
   4544   1.1  christos 				dns_name_format(fname, buf, sizeof(buf));
   4545   1.1  christos 				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
   4546   1.1  christos 					      NS_LOGMODULE_QUERY,
   4547   1.1  christos 					      ISC_LOG_WARNING,
   4548   1.1  christos 					      "RFC 1918 response from "
   4549   1.9  christos 					      "Internet for %s",
   4550   1.9  christos 					      buf);
   4551   1.1  christos 			}
   4552   1.1  christos 			dns_rdataset_disassociate(&found);
   4553   1.1  christos 			return;
   4554   1.1  christos 		}
   4555   1.1  christos 	}
   4556   1.1  christos }
   4557   1.1  christos 
   4558   1.1  christos static void
   4559   1.1  christos query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
   4560   1.1  christos 		       dns_dbversion_t *version, ns_client_t *client,
   4561   1.1  christos 		       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
   4562   1.9  christos 		       dns_name_t *fname, bool exact, dns_name_t *found) {
   4563   1.1  christos 	unsigned char salt[256];
   4564   1.1  christos 	size_t salt_length;
   4565   1.3  christos 	uint16_t iterations;
   4566   1.1  christos 	isc_result_t result;
   4567   1.1  christos 	unsigned int dboptions;
   4568   1.1  christos 	dns_fixedname_t fixed;
   4569   1.1  christos 	dns_hash_t hash;
   4570   1.1  christos 	dns_name_t name;
   4571   1.1  christos 	unsigned int skip = 0, labels;
   4572   1.1  christos 	dns_rdata_nsec3_t nsec3;
   4573   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4574   1.3  christos 	bool optout;
   4575   1.1  christos 	dns_clientinfomethods_t cm;
   4576   1.1  christos 	dns_clientinfo_t ci;
   4577   1.1  christos 
   4578   1.1  christos 	salt_length = sizeof(salt);
   4579   1.1  christos 	result = dns_db_getnsec3parameters(db, version, &hash, NULL,
   4580   1.1  christos 					   &iterations, salt, &salt_length);
   4581   1.9  christos 	if (result != ISC_R_SUCCESS) {
   4582   1.1  christos 		return;
   4583   1.9  christos 	}
   4584   1.1  christos 
   4585   1.1  christos 	dns_name_init(&name, NULL);
   4586   1.1  christos 	dns_name_clone(qname, &name);
   4587   1.1  christos 	labels = dns_name_countlabels(&name);
   4588   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   4589   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   4590   1.1  christos 
   4591   1.1  christos 	/*
   4592   1.1  christos 	 * Map unknown algorithm to known value.
   4593   1.1  christos 	 */
   4594   1.9  christos 	if (hash == DNS_NSEC3_UNKNOWNALG) {
   4595   1.1  christos 		hash = 1;
   4596   1.9  christos 	}
   4597   1.1  christos 
   4598   1.9  christos again:
   4599   1.1  christos 	dns_fixedname_init(&fixed);
   4600   1.1  christos 	result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
   4601   1.9  christos 				    dns_db_origin(db), hash, iterations, salt,
   4602   1.9  christos 				    salt_length);
   4603   1.9  christos 	if (result != ISC_R_SUCCESS) {
   4604   1.1  christos 		return;
   4605   1.9  christos 	}
   4606   1.1  christos 
   4607   1.1  christos 	dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
   4608   1.1  christos 	result = dns_db_findext(db, dns_fixedname_name(&fixed), version,
   4609   1.1  christos 				dns_rdatatype_nsec3, dboptions, client->now,
   4610   1.1  christos 				NULL, fname, &cm, &ci, rdataset, sigrdataset);
   4611   1.1  christos 
   4612   1.1  christos 	if (result == DNS_R_NXDOMAIN) {
   4613   1.1  christos 		if (!dns_rdataset_isassociated(rdataset)) {
   4614   1.1  christos 			return;
   4615   1.1  christos 		}
   4616   1.1  christos 		result = dns_rdataset_first(rdataset);
   4617   1.1  christos 		INSIST(result == ISC_R_SUCCESS);
   4618   1.1  christos 		dns_rdataset_current(rdataset, &rdata);
   4619   1.3  christos 		result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
   4620   1.3  christos 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4621   1.1  christos 		dns_rdata_reset(&rdata);
   4622   1.3  christos 		optout = ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
   4623   1.1  christos 		if (found != NULL && optout &&
   4624   1.9  christos 		    dns_name_issubdomain(&name, dns_db_origin(db))) {
   4625   1.1  christos 			dns_rdataset_disassociate(rdataset);
   4626   1.9  christos 			if (dns_rdataset_isassociated(sigrdataset)) {
   4627   1.1  christos 				dns_rdataset_disassociate(sigrdataset);
   4628   1.9  christos 			}
   4629   1.1  christos 			skip++;
   4630   1.1  christos 			dns_name_getlabelsequence(qname, skip, labels - skip,
   4631   1.1  christos 						  &name);
   4632   1.1  christos 			ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
   4633   1.1  christos 				      NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3),
   4634   1.1  christos 				      "looking for closest provable encloser");
   4635   1.1  christos 			goto again;
   4636   1.1  christos 		}
   4637   1.9  christos 		if (exact) {
   4638   1.1  christos 			ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
   4639   1.1  christos 				      NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
   4640   1.1  christos 				      "expected a exact match NSEC3, got "
   4641   1.1  christos 				      "a covering record");
   4642   1.9  christos 		}
   4643   1.1  christos 	} else if (result != ISC_R_SUCCESS) {
   4644   1.1  christos 		return;
   4645   1.9  christos 	} else if (!exact) {
   4646   1.1  christos 		ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
   4647   1.1  christos 			      NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
   4648   1.1  christos 			      "expected covering NSEC3, got an exact match");
   4649   1.9  christos 	}
   4650   1.1  christos 	if (found == qname) {
   4651   1.9  christos 		if (skip != 0U) {
   4652   1.1  christos 			dns_name_getlabelsequence(qname, skip, labels - skip,
   4653   1.1  christos 						  found);
   4654   1.9  christos 		}
   4655   1.9  christos 	} else if (found != NULL) {
   4656   1.8  christos 		dns_name_copynf(&name, found);
   4657   1.9  christos 	}
   4658   1.1  christos 	return;
   4659   1.1  christos }
   4660   1.1  christos 
   4661   1.3  christos static uint32_t
   4662   1.1  christos dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
   4663   1.1  christos 	dns_dbnode_t *node = NULL;
   4664   1.1  christos 	dns_rdata_soa_t soa;
   4665   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4666   1.1  christos 	dns_rdataset_t rdataset;
   4667   1.1  christos 	isc_result_t result;
   4668   1.3  christos 	uint32_t ttl = UINT32_MAX;
   4669   1.1  christos 
   4670   1.1  christos 	dns_rdataset_init(&rdataset);
   4671   1.1  christos 
   4672   1.1  christos 	result = dns_db_getoriginnode(db, &node);
   4673   1.9  christos 	if (result != ISC_R_SUCCESS) {
   4674   1.1  christos 		goto cleanup;
   4675   1.9  christos 	}
   4676   1.1  christos 
   4677   1.9  christos 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, 0, 0,
   4678   1.9  christos 				     &rdataset, NULL);
   4679   1.9  christos 	if (result != ISC_R_SUCCESS) {
   4680   1.1  christos 		goto cleanup;
   4681   1.9  christos 	}
   4682   1.1  christos 	result = dns_rdataset_first(&rdataset);
   4683   1.9  christos 	if (result != ISC_R_SUCCESS) {
   4684   1.1  christos 		goto cleanup;
   4685   1.9  christos 	}
   4686   1.1  christos 
   4687   1.1  christos 	dns_rdataset_current(&rdataset, &rdata);
   4688   1.1  christos 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   4689   1.1  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4690   1.1  christos 	ttl = ISC_MIN(rdataset.ttl, soa.minimum);
   4691   1.1  christos 
   4692   1.1  christos cleanup:
   4693   1.9  christos 	if (dns_rdataset_isassociated(&rdataset)) {
   4694   1.1  christos 		dns_rdataset_disassociate(&rdataset);
   4695   1.9  christos 	}
   4696   1.9  christos 	if (node != NULL) {
   4697   1.1  christos 		dns_db_detachnode(db, &node);
   4698   1.9  christos 	}
   4699   1.1  christos 	return (ttl);
   4700   1.1  christos }
   4701   1.1  christos 
   4702   1.3  christos static bool
   4703   1.1  christos dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
   4704   1.9  christos 	     dns_rdataset_t *sigrdataset) {
   4705   1.1  christos 	isc_netaddr_t netaddr;
   4706   1.9  christos 	dns_aclenv_t *env =
   4707   1.9  christos 		ns_interfacemgr_getaclenv(client->manager->interface->mgr);
   4708   1.1  christos 	dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
   4709   1.1  christos 	unsigned int flags = 0;
   4710   1.1  christos 	unsigned int i, count;
   4711   1.3  christos 	bool *aaaaok;
   4712   1.1  christos 
   4713   1.1  christos 	INSIST(client->query.dns64_aaaaok == NULL);
   4714   1.1  christos 	INSIST(client->query.dns64_aaaaoklen == 0);
   4715   1.1  christos 	INSIST(client->query.dns64_aaaa == NULL);
   4716   1.1  christos 	INSIST(client->query.dns64_sigaaaa == NULL);
   4717   1.1  christos 
   4718   1.9  christos 	if (dns64 == NULL) {
   4719   1.3  christos 		return (true);
   4720   1.9  christos 	}
   4721   1.1  christos 
   4722   1.9  christos 	if (RECURSIONOK(client)) {
   4723   1.1  christos 		flags |= DNS_DNS64_RECURSIVE;
   4724   1.9  christos 	}
   4725   1.1  christos 
   4726   1.1  christos 	if (WANTDNSSEC(client) && sigrdataset != NULL &&
   4727   1.1  christos 	    dns_rdataset_isassociated(sigrdataset))
   4728   1.9  christos 	{
   4729   1.1  christos 		flags |= DNS_DNS64_DNSSEC;
   4730   1.9  christos 	}
   4731   1.1  christos 
   4732   1.1  christos 	count = dns_rdataset_count(rdataset);
   4733   1.3  christos 	aaaaok = isc_mem_get(client->mctx, sizeof(bool) * count);
   4734   1.1  christos 
   4735   1.1  christos 	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
   4736   1.9  christos 	if (dns_dns64_aaaaok(dns64, &netaddr, client->signer, env, flags,
   4737   1.9  christos 			     rdataset, aaaaok, count))
   4738   1.1  christos 	{
   4739   1.1  christos 		for (i = 0; i < count; i++) {
   4740   1.1  christos 			if (aaaaok != NULL && !aaaaok[i]) {
   4741   1.1  christos 				SAVE(client->query.dns64_aaaaok, aaaaok);
   4742   1.1  christos 				client->query.dns64_aaaaoklen = count;
   4743   1.1  christos 				break;
   4744   1.1  christos 			}
   4745   1.1  christos 		}
   4746   1.9  christos 		if (aaaaok != NULL) {
   4747   1.9  christos 			isc_mem_put(client->mctx, aaaaok, sizeof(bool) * count);
   4748   1.9  christos 		}
   4749   1.3  christos 		return (true);
   4750   1.1  christos 	}
   4751   1.9  christos 	if (aaaaok != NULL) {
   4752   1.9  christos 		isc_mem_put(client->mctx, aaaaok, sizeof(bool) * count);
   4753   1.9  christos 	}
   4754   1.3  christos 	return (false);
   4755   1.1  christos }
   4756   1.1  christos 
   4757   1.1  christos /*
   4758   1.1  christos  * Look for the name and type in the redirection zone.  If found update
   4759   1.3  christos  * the arguments as appropriate.  Return true if a update was
   4760   1.1  christos  * performed.
   4761   1.1  christos  *
   4762   1.1  christos  * Only perform the update if the client is in the allow query acl and
   4763   1.1  christos  * returning the update would not cause a DNSSEC validation failure.
   4764   1.1  christos  */
   4765   1.1  christos static isc_result_t
   4766   1.1  christos redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
   4767   1.1  christos 	 dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
   4768   1.9  christos 	 dns_rdatatype_t qtype) {
   4769   1.1  christos 	dns_db_t *db = NULL;
   4770   1.1  christos 	dns_dbnode_t *node = NULL;
   4771   1.1  christos 	dns_fixedname_t fixed;
   4772   1.1  christos 	dns_name_t *found;
   4773   1.1  christos 	dns_rdataset_t trdataset;
   4774   1.1  christos 	isc_result_t result;
   4775   1.1  christos 	dns_rdatatype_t type;
   4776   1.1  christos 	dns_clientinfomethods_t cm;
   4777   1.1  christos 	dns_clientinfo_t ci;
   4778   1.1  christos 	ns_dbversion_t *dbversion;
   4779   1.1  christos 
   4780   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "redirect");
   4781   1.1  christos 
   4782   1.9  christos 	if (client->view->redirect == NULL) {
   4783   1.1  christos 		return (ISC_R_NOTFOUND);
   4784   1.9  christos 	}
   4785   1.1  christos 
   4786   1.1  christos 	found = dns_fixedname_initname(&fixed);
   4787   1.1  christos 	dns_rdataset_init(&trdataset);
   4788   1.1  christos 
   4789   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   4790   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   4791   1.1  christos 
   4792   1.1  christos 	if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
   4793   1.9  christos 	{
   4794   1.1  christos 		return (ISC_R_NOTFOUND);
   4795   1.9  christos 	}
   4796   1.1  christos 
   4797   1.1  christos 	if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
   4798   1.9  christos 		if (rdataset->trust == dns_trust_secure) {
   4799   1.1  christos 			return (ISC_R_NOTFOUND);
   4800   1.9  christos 		}
   4801   1.1  christos 		if (rdataset->trust == dns_trust_ultimate &&
   4802   1.1  christos 		    (rdataset->type == dns_rdatatype_nsec ||
   4803   1.1  christos 		     rdataset->type == dns_rdatatype_nsec3))
   4804   1.9  christos 		{
   4805   1.1  christos 			return (ISC_R_NOTFOUND);
   4806   1.9  christos 		}
   4807   1.1  christos 		if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
   4808   1.1  christos 			for (result = dns_rdataset_first(rdataset);
   4809   1.1  christos 			     result == ISC_R_SUCCESS;
   4810   1.9  christos 			     result = dns_rdataset_next(rdataset))
   4811   1.9  christos 			{
   4812   1.1  christos 				dns_ncache_current(rdataset, found, &trdataset);
   4813   1.1  christos 				type = trdataset.type;
   4814   1.1  christos 				dns_rdataset_disassociate(&trdataset);
   4815   1.1  christos 				if (type == dns_rdatatype_nsec ||
   4816   1.1  christos 				    type == dns_rdatatype_nsec3 ||
   4817   1.1  christos 				    type == dns_rdatatype_rrsig)
   4818   1.9  christos 				{
   4819   1.1  christos 					return (ISC_R_NOTFOUND);
   4820   1.9  christos 				}
   4821   1.1  christos 			}
   4822   1.1  christos 		}
   4823   1.1  christos 	}
   4824   1.1  christos 
   4825   1.9  christos 	result = ns_client_checkaclsilent(
   4826   1.9  christos 		client, NULL, dns_zone_getqueryacl(client->view->redirect),
   4827   1.9  christos 		true);
   4828   1.9  christos 	if (result != ISC_R_SUCCESS) {
   4829   1.1  christos 		return (ISC_R_NOTFOUND);
   4830   1.9  christos 	}
   4831   1.1  christos 
   4832   1.1  christos 	result = dns_zone_getdb(client->view->redirect, &db);
   4833   1.9  christos 	if (result != ISC_R_SUCCESS) {
   4834   1.1  christos 		return (ISC_R_NOTFOUND);
   4835   1.9  christos 	}
   4836   1.1  christos 
   4837   1.3  christos 	dbversion = ns_client_findversion(client, db);
   4838   1.1  christos 	if (dbversion == NULL) {
   4839   1.1  christos 		dns_db_detach(&db);
   4840   1.1  christos 		return (ISC_R_NOTFOUND);
   4841   1.1  christos 	}
   4842   1.1  christos 
   4843   1.1  christos 	/*
   4844   1.1  christos 	 * Lookup the requested data in the redirect zone.
   4845   1.1  christos 	 */
   4846   1.1  christos 	result = dns_db_findext(db, client->query.qname, dbversion->version,
   4847   1.9  christos 				qtype, DNS_DBFIND_NOZONECUT, client->now, &node,
   4848   1.9  christos 				found, &cm, &ci, &trdataset, NULL);
   4849   1.1  christos 	if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
   4850   1.9  christos 		if (dns_rdataset_isassociated(rdataset)) {
   4851   1.1  christos 			dns_rdataset_disassociate(rdataset);
   4852   1.9  christos 		}
   4853   1.9  christos 		if (dns_rdataset_isassociated(&trdataset)) {
   4854   1.1  christos 			dns_rdataset_disassociate(&trdataset);
   4855   1.9  christos 		}
   4856   1.1  christos 		goto nxrrset;
   4857   1.1  christos 	} else if (result != ISC_R_SUCCESS) {
   4858   1.9  christos 		if (dns_rdataset_isassociated(&trdataset)) {
   4859   1.1  christos 			dns_rdataset_disassociate(&trdataset);
   4860   1.9  christos 		}
   4861   1.9  christos 		if (node != NULL) {
   4862   1.1  christos 			dns_db_detachnode(db, &node);
   4863   1.9  christos 		}
   4864   1.1  christos 		dns_db_detach(&db);
   4865   1.1  christos 		return (ISC_R_NOTFOUND);
   4866   1.1  christos 	}
   4867   1.1  christos 
   4868   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done");
   4869   1.8  christos 	dns_name_copynf(found, name);
   4870   1.9  christos 	if (dns_rdataset_isassociated(rdataset)) {
   4871   1.1  christos 		dns_rdataset_disassociate(rdataset);
   4872   1.9  christos 	}
   4873   1.1  christos 	if (dns_rdataset_isassociated(&trdataset)) {
   4874   1.1  christos 		dns_rdataset_clone(&trdataset, rdataset);
   4875   1.1  christos 		dns_rdataset_disassociate(&trdataset);
   4876   1.1  christos 	}
   4877   1.9  christos nxrrset:
   4878   1.9  christos 	if (*nodep != NULL) {
   4879   1.1  christos 		dns_db_detachnode(*dbp, nodep);
   4880   1.9  christos 	}
   4881   1.1  christos 	dns_db_detach(dbp);
   4882   1.1  christos 	dns_db_attachnode(db, node, nodep);
   4883   1.1  christos 	dns_db_attach(db, dbp);
   4884   1.1  christos 	dns_db_detachnode(db, &node);
   4885   1.1  christos 	dns_db_detach(&db);
   4886   1.1  christos 	*versionp = dbversion->version;
   4887   1.1  christos 
   4888   1.1  christos 	client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
   4889   1.1  christos 				     NS_QUERYATTR_NOADDITIONAL);
   4890   1.1  christos 
   4891   1.1  christos 	return (result);
   4892   1.1  christos }
   4893   1.1  christos 
   4894   1.1  christos static isc_result_t
   4895   1.1  christos redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
   4896   1.1  christos 	  dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
   4897   1.9  christos 	  dns_rdatatype_t qtype, bool *is_zonep) {
   4898   1.1  christos 	dns_db_t *db = NULL;
   4899   1.1  christos 	dns_dbnode_t *node = NULL;
   4900   1.1  christos 	dns_fixedname_t fixed;
   4901   1.1  christos 	dns_fixedname_t fixedredirect;
   4902   1.1  christos 	dns_name_t *found, *redirectname;
   4903   1.1  christos 	dns_rdataset_t trdataset;
   4904   1.1  christos 	isc_result_t result;
   4905   1.1  christos 	dns_rdatatype_t type;
   4906   1.1  christos 	dns_clientinfomethods_t cm;
   4907   1.1  christos 	dns_clientinfo_t ci;
   4908   1.1  christos 	dns_dbversion_t *version = NULL;
   4909   1.1  christos 	dns_zone_t *zone = NULL;
   4910   1.3  christos 	bool is_zone;
   4911   1.5  christos 	unsigned int labels;
   4912   1.1  christos 	unsigned int options;
   4913   1.1  christos 
   4914   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "redirect2");
   4915   1.1  christos 
   4916   1.5  christos 	if (client->view->redirectzone == NULL) {
   4917   1.1  christos 		return (ISC_R_NOTFOUND);
   4918   1.5  christos 	}
   4919   1.1  christos 
   4920   1.5  christos 	if (dns_name_issubdomain(name, client->view->redirectzone)) {
   4921   1.1  christos 		return (ISC_R_NOTFOUND);
   4922   1.5  christos 	}
   4923   1.1  christos 
   4924   1.1  christos 	found = dns_fixedname_initname(&fixed);
   4925   1.1  christos 	dns_rdataset_init(&trdataset);
   4926   1.1  christos 
   4927   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   4928   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   4929   1.1  christos 
   4930   1.9  christos 	if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
   4931   1.9  christos 	{
   4932   1.1  christos 		return (ISC_R_NOTFOUND);
   4933   1.5  christos 	}
   4934   1.1  christos 
   4935   1.1  christos 	if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
   4936   1.9  christos 		if (rdataset->trust == dns_trust_secure) {
   4937   1.1  christos 			return (ISC_R_NOTFOUND);
   4938   1.9  christos 		}
   4939   1.1  christos 		if (rdataset->trust == dns_trust_ultimate &&
   4940   1.1  christos 		    (rdataset->type == dns_rdatatype_nsec ||
   4941   1.1  christos 		     rdataset->type == dns_rdatatype_nsec3))
   4942   1.9  christos 		{
   4943   1.1  christos 			return (ISC_R_NOTFOUND);
   4944   1.9  christos 		}
   4945   1.1  christos 		if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
   4946   1.1  christos 			for (result = dns_rdataset_first(rdataset);
   4947   1.1  christos 			     result == ISC_R_SUCCESS;
   4948   1.9  christos 			     result = dns_rdataset_next(rdataset))
   4949   1.9  christos 			{
   4950   1.1  christos 				dns_ncache_current(rdataset, found, &trdataset);
   4951   1.1  christos 				type = trdataset.type;
   4952   1.1  christos 				dns_rdataset_disassociate(&trdataset);
   4953   1.1  christos 				if (type == dns_rdatatype_nsec ||
   4954   1.1  christos 				    type == dns_rdatatype_nsec3 ||
   4955   1.1  christos 				    type == dns_rdatatype_rrsig)
   4956   1.9  christos 				{
   4957   1.1  christos 					return (ISC_R_NOTFOUND);
   4958   1.9  christos 				}
   4959   1.1  christos 			}
   4960   1.1  christos 		}
   4961   1.1  christos 	}
   4962   1.1  christos 
   4963   1.1  christos 	redirectname = dns_fixedname_initname(&fixedredirect);
   4964   1.5  christos 	labels = dns_name_countlabels(client->query.qname);
   4965   1.5  christos 	if (labels > 1U) {
   4966   1.1  christos 		dns_name_t prefix;
   4967   1.1  christos 
   4968   1.1  christos 		dns_name_init(&prefix, NULL);
   4969   1.5  christos 		dns_name_getlabelsequence(client->query.qname, 0, labels - 1,
   4970   1.5  christos 					  &prefix);
   4971   1.1  christos 		result = dns_name_concatenate(&prefix,
   4972   1.1  christos 					      client->view->redirectzone,
   4973   1.1  christos 					      redirectname, NULL);
   4974   1.9  christos 		if (result != ISC_R_SUCCESS) {
   4975   1.1  christos 			return (ISC_R_NOTFOUND);
   4976   1.9  christos 		}
   4977   1.5  christos 	} else {
   4978   1.8  christos 		dns_name_copynf(redirectname, client->view->redirectzone);
   4979   1.5  christos 	}
   4980   1.1  christos 
   4981   1.1  christos 	options = 0;
   4982   1.9  christos 	result = query_getdb(client, redirectname, qtype, options, &zone, &db,
   4983   1.9  christos 			     &version, &is_zone);
   4984   1.5  christos 	if (result != ISC_R_SUCCESS) {
   4985   1.1  christos 		return (ISC_R_NOTFOUND);
   4986   1.5  christos 	}
   4987   1.5  christos 	if (zone != NULL) {
   4988   1.1  christos 		dns_zone_detach(&zone);
   4989   1.5  christos 	}
   4990   1.1  christos 
   4991   1.1  christos 	/*
   4992   1.1  christos 	 * Lookup the requested data in the redirect zone.
   4993   1.1  christos 	 */
   4994   1.9  christos 	result = dns_db_findext(db, redirectname, version, qtype, 0,
   4995   1.9  christos 				client->now, &node, found, &cm, &ci, &trdataset,
   4996   1.9  christos 				NULL);
   4997   1.1  christos 	if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
   4998   1.9  christos 		if (dns_rdataset_isassociated(rdataset)) {
   4999   1.1  christos 			dns_rdataset_disassociate(rdataset);
   5000   1.9  christos 		}
   5001   1.9  christos 		if (dns_rdataset_isassociated(&trdataset)) {
   5002   1.1  christos 			dns_rdataset_disassociate(&trdataset);
   5003   1.9  christos 		}
   5004   1.1  christos 		goto nxrrset;
   5005   1.1  christos 	} else if (result == ISC_R_NOTFOUND || result == DNS_R_DELEGATION) {
   5006   1.1  christos 		/*
   5007   1.1  christos 		 * Cleanup.
   5008   1.1  christos 		 */
   5009   1.9  christos 		if (dns_rdataset_isassociated(&trdataset)) {
   5010   1.1  christos 			dns_rdataset_disassociate(&trdataset);
   5011   1.9  christos 		}
   5012   1.9  christos 		if (node != NULL) {
   5013   1.1  christos 			dns_db_detachnode(db, &node);
   5014   1.9  christos 		}
   5015   1.1  christos 		dns_db_detach(&db);
   5016   1.1  christos 		/*
   5017   1.1  christos 		 * Don't loop forever if the lookup failed last time.
   5018   1.1  christos 		 */
   5019   1.1  christos 		if (!REDIRECT(client)) {
   5020   1.3  christos 			result = ns_query_recurse(client, qtype, redirectname,
   5021   1.3  christos 						  NULL, NULL, true);
   5022   1.1  christos 			if (result == ISC_R_SUCCESS) {
   5023   1.1  christos 				client->query.attributes |=
   5024   1.9  christos 					NS_QUERYATTR_RECURSING;
   5025   1.1  christos 				client->query.attributes |=
   5026   1.9  christos 					NS_QUERYATTR_REDIRECT;
   5027   1.1  christos 				return (DNS_R_CONTINUE);
   5028   1.1  christos 			}
   5029   1.1  christos 		}
   5030   1.1  christos 		return (ISC_R_NOTFOUND);
   5031   1.1  christos 	} else if (result != ISC_R_SUCCESS) {
   5032   1.9  christos 		if (dns_rdataset_isassociated(&trdataset)) {
   5033   1.1  christos 			dns_rdataset_disassociate(&trdataset);
   5034   1.9  christos 		}
   5035   1.9  christos 		if (node != NULL) {
   5036   1.1  christos 			dns_db_detachnode(db, &node);
   5037   1.9  christos 		}
   5038   1.1  christos 		dns_db_detach(&db);
   5039   1.1  christos 		return (ISC_R_NOTFOUND);
   5040   1.1  christos 	}
   5041   1.1  christos 
   5042   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "redirect2: found data: done");
   5043   1.1  christos 	/*
   5044   1.1  christos 	 * Adjust the found name to not include the redirectzone suffix.
   5045   1.1  christos 	 */
   5046   1.1  christos 	dns_name_split(found, dns_name_countlabels(client->view->redirectzone),
   5047   1.1  christos 		       found, NULL);
   5048   1.1  christos 	/*
   5049   1.1  christos 	 * Make the name absolute.
   5050   1.1  christos 	 */
   5051   1.1  christos 	result = dns_name_concatenate(found, dns_rootname, found, NULL);
   5052   1.1  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5053   1.1  christos 
   5054   1.8  christos 	dns_name_copynf(found, name);
   5055   1.9  christos 	if (dns_rdataset_isassociated(rdataset)) {
   5056   1.1  christos 		dns_rdataset_disassociate(rdataset);
   5057   1.9  christos 	}
   5058   1.1  christos 	if (dns_rdataset_isassociated(&trdataset)) {
   5059   1.1  christos 		dns_rdataset_clone(&trdataset, rdataset);
   5060   1.1  christos 		dns_rdataset_disassociate(&trdataset);
   5061   1.1  christos 	}
   5062   1.9  christos nxrrset:
   5063   1.9  christos 	if (*nodep != NULL) {
   5064   1.1  christos 		dns_db_detachnode(*dbp, nodep);
   5065   1.9  christos 	}
   5066   1.1  christos 	dns_db_detach(dbp);
   5067   1.1  christos 	dns_db_attachnode(db, node, nodep);
   5068   1.1  christos 	dns_db_attach(db, dbp);
   5069   1.1  christos 	dns_db_detachnode(db, &node);
   5070   1.1  christos 	dns_db_detach(&db);
   5071   1.1  christos 	*is_zonep = is_zone;
   5072   1.1  christos 	*versionp = version;
   5073   1.1  christos 
   5074   1.1  christos 	client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
   5075   1.1  christos 				     NS_QUERYATTR_NOADDITIONAL);
   5076   1.1  christos 
   5077   1.1  christos 	return (result);
   5078   1.1  christos }
   5079   1.1  christos 
   5080   1.1  christos /*%
   5081   1.1  christos  * Initialize query context 'qctx'. Run by query_setup() when
   5082   1.1  christos  * first handling a client query, and by query_resume() when
   5083   1.1  christos  * returning from recursion.
   5084   1.3  christos  *
   5085   1.3  christos  * Whenever this function is called, qctx_destroy() must be called
   5086   1.3  christos  * when leaving the scope or freeing the qctx.
   5087   1.1  christos  */
   5088   1.1  christos static void
   5089  1.11  christos qctx_init(ns_client_t *client, dns_fetchevent_t **eventp, dns_rdatatype_t qtype,
   5090   1.9  christos 	  query_ctx_t *qctx) {
   5091   1.1  christos 	REQUIRE(qctx != NULL);
   5092   1.1  christos 	REQUIRE(client != NULL);
   5093   1.1  christos 
   5094   1.3  christos 	memset(qctx, 0, sizeof(*qctx));
   5095   1.3  christos 
   5096   1.1  christos 	/* Set this first so CCTRACE will work */
   5097   1.1  christos 	qctx->client = client;
   5098   1.9  christos 
   5099   1.3  christos 	dns_view_attach(client->view, &qctx->view);
   5100   1.1  christos 
   5101   1.3  christos 	CCTRACE(ISC_LOG_DEBUG(3), "qctx_init");
   5102   1.1  christos 
   5103  1.11  christos 	if (eventp != NULL) {
   5104  1.11  christos 		qctx->event = *eventp;
   5105  1.11  christos 		*eventp = NULL;
   5106  1.11  christos 	} else {
   5107  1.11  christos 		qctx->event = NULL;
   5108  1.11  christos 	}
   5109   1.1  christos 	qctx->qtype = qctx->type = qtype;
   5110   1.1  christos 	qctx->result = ISC_R_SUCCESS;
   5111   1.3  christos 	qctx->findcoveringnsec = qctx->view->synthfromdnssec;
   5112   1.3  christos 
   5113   1.3  christos 	CALL_HOOK_NORETURN(NS_QUERY_QCTX_INITIALIZED, qctx);
   5114   1.1  christos }
   5115   1.1  christos 
   5116  1.11  christos /*
   5117  1.11  christos  * Make 'dst' and exact copy of 'src', with exception of the
   5118  1.11  christos  * option field, which is reset to zero.
   5119  1.11  christos  * This function also attaches dst's view and db to the src's
   5120  1.11  christos  * view and cachedb.
   5121  1.11  christos  */
   5122  1.11  christos static void
   5123  1.11  christos qctx_copy(const query_ctx_t *qctx, query_ctx_t *dst) {
   5124  1.11  christos 	REQUIRE(qctx != NULL);
   5125  1.11  christos 	REQUIRE(dst != NULL);
   5126  1.11  christos 
   5127  1.11  christos 	memmove(dst, qctx, sizeof(*dst));
   5128  1.11  christos 	dst->view = NULL;
   5129  1.11  christos 	dst->db = NULL;
   5130  1.11  christos 	dst->options = 0;
   5131  1.11  christos 	dns_view_attach(qctx->view, &dst->view);
   5132  1.11  christos 	dns_db_attach(qctx->view->cachedb, &dst->db);
   5133  1.11  christos 	CCTRACE(ISC_LOG_DEBUG(3), "qctx_copy");
   5134  1.11  christos }
   5135  1.11  christos 
   5136   1.1  christos /*%
   5137   1.1  christos  * Clean up and disassociate the rdataset and node pointers in qctx.
   5138   1.1  christos  */
   5139   1.1  christos static void
   5140   1.1  christos qctx_clean(query_ctx_t *qctx) {
   5141   1.9  christos 	if (qctx->rdataset != NULL && dns_rdataset_isassociated(qctx->rdataset))
   5142   1.1  christos 	{
   5143   1.1  christos 		dns_rdataset_disassociate(qctx->rdataset);
   5144   1.1  christos 	}
   5145   1.1  christos 	if (qctx->sigrdataset != NULL &&
   5146   1.9  christos 	    dns_rdataset_isassociated(qctx->sigrdataset)) {
   5147   1.1  christos 		dns_rdataset_disassociate(qctx->sigrdataset);
   5148   1.1  christos 	}
   5149   1.1  christos 	if (qctx->db != NULL && qctx->node != NULL) {
   5150   1.1  christos 		dns_db_detachnode(qctx->db, &qctx->node);
   5151   1.1  christos 	}
   5152   1.1  christos }
   5153   1.1  christos 
   5154   1.1  christos /*%
   5155   1.1  christos  * Free any allocated memory associated with qctx.
   5156   1.1  christos  */
   5157   1.1  christos static void
   5158   1.1  christos qctx_freedata(query_ctx_t *qctx) {
   5159   1.1  christos 	if (qctx->rdataset != NULL) {
   5160   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->rdataset);
   5161   1.1  christos 	}
   5162   1.1  christos 
   5163   1.1  christos 	if (qctx->sigrdataset != NULL) {
   5164   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
   5165   1.1  christos 	}
   5166   1.1  christos 
   5167   1.1  christos 	if (qctx->fname != NULL) {
   5168   1.3  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   5169   1.1  christos 	}
   5170   1.1  christos 
   5171   1.1  christos 	if (qctx->db != NULL) {
   5172   1.1  christos 		INSIST(qctx->node == NULL);
   5173   1.1  christos 		dns_db_detach(&qctx->db);
   5174   1.1  christos 	}
   5175   1.1  christos 
   5176   1.1  christos 	if (qctx->zone != NULL) {
   5177   1.1  christos 		dns_zone_detach(&qctx->zone);
   5178   1.1  christos 	}
   5179   1.1  christos 
   5180   1.1  christos 	if (qctx->zdb != NULL) {
   5181   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->zsigrdataset);
   5182   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->zrdataset);
   5183   1.3  christos 		ns_client_releasename(qctx->client, &qctx->zfname);
   5184   1.3  christos 		dns_db_detachnode(qctx->zdb, &qctx->znode);
   5185   1.1  christos 		dns_db_detach(&qctx->zdb);
   5186   1.1  christos 	}
   5187   1.1  christos 
   5188  1.11  christos 	if (qctx->event != NULL && !QUERY_STALEONLY(&qctx->client->query)) {
   5189   1.9  christos 		free_devent(qctx->client, ISC_EVENT_PTR(&qctx->event),
   5190   1.9  christos 			    &qctx->event);
   5191   1.1  christos 	}
   5192   1.1  christos }
   5193   1.1  christos 
   5194   1.3  christos static void
   5195   1.3  christos qctx_destroy(query_ctx_t *qctx) {
   5196   1.3  christos 	CALL_HOOK_NORETURN(NS_QUERY_QCTX_DESTROYED, qctx);
   5197   1.3  christos 
   5198   1.3  christos 	dns_view_detach(&qctx->view);
   5199   1.3  christos }
   5200   1.3  christos 
   5201   1.1  christos /*%
   5202   1.1  christos  * Log detailed information about the query immediately after
   5203   1.1  christos  * the client request or a return from recursion.
   5204   1.1  christos  */
   5205   1.1  christos static void
   5206   1.1  christos query_trace(query_ctx_t *qctx) {
   5207   1.1  christos #ifdef WANT_QUERYTRACE
   5208   1.6  christos 	char mbuf[2 * DNS_NAME_FORMATSIZE];
   5209   1.1  christos 	char qbuf[DNS_NAME_FORMATSIZE];
   5210   1.1  christos 
   5211   1.9  christos 	if (qctx->client->query.origqname != NULL) {
   5212   1.1  christos 		dns_name_format(qctx->client->query.origqname, qbuf,
   5213   1.1  christos 				sizeof(qbuf));
   5214   1.9  christos 	} else {
   5215   1.1  christos 		snprintf(qbuf, sizeof(qbuf), "<unset>");
   5216   1.9  christos 	}
   5217   1.1  christos 
   5218   1.1  christos 	snprintf(mbuf, sizeof(mbuf) - 1,
   5219   1.1  christos 		 "client attr:0x%x, query attr:0x%X, restarts:%u, "
   5220   1.1  christos 		 "origqname:%s, timer:%d, authdb:%d, referral:%d",
   5221   1.9  christos 		 qctx->client->attributes, qctx->client->query.attributes,
   5222   1.1  christos 		 qctx->client->query.restarts, qbuf,
   5223   1.9  christos 		 (int)qctx->client->query.timerset,
   5224   1.9  christos 		 (int)qctx->client->query.authdbset,
   5225   1.9  christos 		 (int)qctx->client->query.isreferral);
   5226   1.1  christos 	CCTRACE(ISC_LOG_DEBUG(3), mbuf);
   5227   1.9  christos #else  /* ifdef WANT_QUERYTRACE */
   5228   1.1  christos 	UNUSED(qctx);
   5229   1.9  christos #endif /* ifdef WANT_QUERYTRACE */
   5230   1.1  christos }
   5231   1.1  christos 
   5232   1.1  christos /*
   5233   1.1  christos  * Set up query processing for the current query of 'client'.
   5234   1.1  christos  * Calls qctx_init() to initialize a query context, checks
   5235   1.1  christos  * the SERVFAIL cache, then hands off processing to ns__query_start().
   5236   1.1  christos  *
   5237   1.1  christos  * This is called only from ns_query_start(), to begin a query
   5238   1.1  christos  * for the first time.  Restarting an existing query (for
   5239   1.1  christos  * instance, to handle CNAME lookups), is done by calling
   5240   1.1  christos  * ns__query_start() again with the same query context. Resuming from
   5241   1.1  christos  * recursion is handled by query_resume().
   5242   1.1  christos  */
   5243   1.1  christos static isc_result_t
   5244   1.1  christos query_setup(ns_client_t *client, dns_rdatatype_t qtype) {
   5245   1.1  christos 	isc_result_t result;
   5246   1.1  christos 	query_ctx_t qctx;
   5247   1.1  christos 
   5248   1.1  christos 	qctx_init(client, NULL, qtype, &qctx);
   5249   1.1  christos 	query_trace(&qctx);
   5250   1.1  christos 
   5251   1.3  christos 	CALL_HOOK(NS_QUERY_SETUP, &qctx);
   5252   1.3  christos 
   5253   1.1  christos 	/*
   5254   1.1  christos 	 * If it's a SIG query, we'll iterate the node.
   5255   1.1  christos 	 */
   5256   1.1  christos 	if (qctx.qtype == dns_rdatatype_rrsig ||
   5257   1.9  christos 	    qctx.qtype == dns_rdatatype_sig) {
   5258   1.1  christos 		qctx.type = dns_rdatatype_any;
   5259   1.1  christos 	}
   5260   1.1  christos 
   5261   1.1  christos 	/*
   5262   1.1  christos 	 * Check SERVFAIL cache
   5263   1.1  christos 	 */
   5264   1.1  christos 	result = ns__query_sfcache(&qctx);
   5265   1.1  christos 	if (result != ISC_R_COMPLETE) {
   5266   1.3  christos 		qctx_destroy(&qctx);
   5267   1.1  christos 		return (result);
   5268   1.1  christos 	}
   5269   1.1  christos 
   5270   1.3  christos 	result = ns__query_start(&qctx);
   5271   1.3  christos 
   5272   1.9  christos cleanup:
   5273   1.3  christos 	qctx_destroy(&qctx);
   5274   1.3  christos 	return (result);
   5275   1.1  christos }
   5276   1.1  christos 
   5277   1.3  christos static bool
   5278   1.1  christos get_root_key_sentinel_id(query_ctx_t *qctx, const char *ndata) {
   5279   1.1  christos 	unsigned int v = 0;
   5280   1.1  christos 	int i;
   5281   1.1  christos 
   5282   1.1  christos 	for (i = 0; i < 5; i++) {
   5283   1.1  christos 		if (ndata[i] < '0' || ndata[i] > '9') {
   5284   1.3  christos 			return (false);
   5285   1.1  christos 		}
   5286   1.1  christos 		v *= 10;
   5287   1.1  christos 		v += ndata[i] - '0';
   5288   1.1  christos 	}
   5289   1.1  christos 	if (v > 65535U) {
   5290   1.3  christos 		return (false);
   5291   1.1  christos 	}
   5292   1.1  christos 	qctx->client->query.root_key_sentinel_keyid = v;
   5293   1.3  christos 	return (true);
   5294   1.1  christos }
   5295   1.1  christos 
   5296   1.1  christos /*%
   5297   1.1  christos  * Find out if the query is for a root key sentinel and if so, record the type
   5298   1.1  christos  * of root key sentinel query and the key id that is being checked for.
   5299   1.1  christos  *
   5300   1.1  christos  * The code is assuming a zero padded decimal field of width 5.
   5301   1.1  christos  */
   5302   1.1  christos static void
   5303   1.1  christos root_key_sentinel_detect(query_ctx_t *qctx) {
   5304   1.1  christos 	const char *ndata = (const char *)qctx->client->query.qname->ndata;
   5305   1.1  christos 
   5306   1.1  christos 	if (qctx->client->query.qname->length > 30 && ndata[0] == 29 &&
   5307   1.1  christos 	    strncasecmp(ndata + 1, "root-key-sentinel-is-ta-", 24) == 0)
   5308   1.1  christos 	{
   5309   1.1  christos 		if (!get_root_key_sentinel_id(qctx, ndata + 25)) {
   5310   1.1  christos 			return;
   5311   1.1  christos 		}
   5312   1.3  christos 		qctx->client->query.root_key_sentinel_is_ta = true;
   5313   1.1  christos 		/*
   5314   1.9  christos 		 * Simplify processing by disabling aggressive
   5315   1.1  christos 		 * negative caching.
   5316   1.1  christos 		 */
   5317   1.3  christos 		qctx->findcoveringnsec = false;
   5318   1.1  christos 		ns_client_log(qctx->client, NS_LOGCATEGORY_TAT,
   5319   1.1  christos 			      NS_LOGMODULE_QUERY, ISC_LOG_INFO,
   5320   1.1  christos 			      "root-key-sentinel-is-ta query label found");
   5321   1.1  christos 	} else if (qctx->client->query.qname->length > 31 && ndata[0] == 30 &&
   5322   1.1  christos 		   strncasecmp(ndata + 1, "root-key-sentinel-not-ta-", 25) == 0)
   5323   1.1  christos 	{
   5324   1.1  christos 		if (!get_root_key_sentinel_id(qctx, ndata + 26)) {
   5325   1.1  christos 			return;
   5326   1.1  christos 		}
   5327   1.3  christos 		qctx->client->query.root_key_sentinel_not_ta = true;
   5328   1.1  christos 		/*
   5329   1.9  christos 		 * Simplify processing by disabling aggressive
   5330   1.1  christos 		 * negative caching.
   5331   1.1  christos 		 */
   5332   1.3  christos 		qctx->findcoveringnsec = false;
   5333   1.1  christos 		ns_client_log(qctx->client, NS_LOGCATEGORY_TAT,
   5334   1.1  christos 			      NS_LOGMODULE_QUERY, ISC_LOG_INFO,
   5335   1.1  christos 			      "root-key-sentinel-not-ta query label found");
   5336   1.1  christos 	}
   5337   1.1  christos }
   5338   1.1  christos 
   5339   1.1  christos /*%
   5340   1.1  christos  * Starting point for a client query or a chaining query.
   5341   1.1  christos  *
   5342   1.1  christos  * Called first by query_setup(), and then again as often as needed to
   5343   1.1  christos  * follow a CNAME chain.  Determines which authoritative database to
   5344   1.1  christos  * search, then hands off processing to query_lookup().
   5345   1.1  christos  */
   5346   1.1  christos isc_result_t
   5347   1.1  christos ns__query_start(query_ctx_t *qctx) {
   5348   1.1  christos 	isc_result_t result;
   5349   1.1  christos 	CCTRACE(ISC_LOG_DEBUG(3), "ns__query_start");
   5350   1.3  christos 	qctx->want_restart = false;
   5351   1.3  christos 	qctx->authoritative = false;
   5352   1.1  christos 	qctx->version = NULL;
   5353   1.1  christos 	qctx->zversion = NULL;
   5354   1.3  christos 	qctx->need_wildcardproof = false;
   5355   1.3  christos 	qctx->rpz = false;
   5356   1.3  christos 
   5357   1.3  christos 	CALL_HOOK(NS_QUERY_START_BEGIN, qctx);
   5358   1.3  christos 
   5359   1.3  christos 	/*
   5360   1.3  christos 	 * If we require a server cookie then send back BADCOOKIE
   5361   1.3  christos 	 * before we have done too much work.
   5362   1.3  christos 	 */
   5363   1.3  christos 	if (!TCP(qctx->client) && qctx->view->requireservercookie &&
   5364   1.3  christos 	    WANTCOOKIE(qctx->client) && !HAVECOOKIE(qctx->client))
   5365   1.3  christos 	{
   5366   1.3  christos 		qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA;
   5367   1.3  christos 		qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
   5368   1.3  christos 		qctx->client->message->rcode = dns_rcode_badcookie;
   5369   1.3  christos 		return (ns_query_done(qctx));
   5370   1.3  christos 	}
   5371   1.1  christos 
   5372   1.3  christos 	if (qctx->view->checknames &&
   5373   1.1  christos 	    !dns_rdata_checkowner(qctx->client->query.qname,
   5374   1.9  christos 				  qctx->client->message->rdclass, qctx->qtype,
   5375   1.9  christos 				  false))
   5376   1.1  christos 	{
   5377   1.1  christos 		char namebuf[DNS_NAME_FORMATSIZE];
   5378   1.3  christos 		char typebuf[DNS_RDATATYPE_FORMATSIZE];
   5379   1.3  christos 		char classbuf[DNS_RDATACLASS_FORMATSIZE];
   5380   1.1  christos 
   5381   1.9  christos 		dns_name_format(qctx->client->query.qname, namebuf,
   5382   1.9  christos 				sizeof(namebuf));
   5383   1.3  christos 		dns_rdatatype_format(qctx->qtype, typebuf, sizeof(typebuf));
   5384   1.9  christos 		dns_rdataclass_format(qctx->client->message->rdclass, classbuf,
   5385   1.9  christos 				      sizeof(classbuf));
   5386   1.1  christos 		ns_client_log(qctx->client, DNS_LOGCATEGORY_SECURITY,
   5387   1.1  christos 			      NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
   5388   1.9  christos 			      "check-names failure %s/%s/%s", namebuf, typebuf,
   5389   1.9  christos 			      classbuf);
   5390   1.1  christos 		QUERY_ERROR(qctx, DNS_R_REFUSED);
   5391   1.3  christos 		return (ns_query_done(qctx));
   5392   1.1  christos 	}
   5393   1.1  christos 
   5394   1.1  christos 	/*
   5395   1.1  christos 	 * Setup for root key sentinel processing.
   5396   1.1  christos 	 */
   5397   1.3  christos 	if (qctx->view->root_key_sentinel &&
   5398   1.1  christos 	    qctx->client->query.restarts == 0 &&
   5399   1.1  christos 	    (qctx->qtype == dns_rdatatype_a ||
   5400   1.1  christos 	     qctx->qtype == dns_rdatatype_aaaa) &&
   5401   1.1  christos 	    (qctx->client->message->flags & DNS_MESSAGEFLAG_CD) == 0)
   5402   1.1  christos 	{
   5403   1.9  christos 		root_key_sentinel_detect(qctx);
   5404   1.1  christos 	}
   5405   1.1  christos 
   5406   1.1  christos 	/*
   5407   1.1  christos 	 * First we must find the right database.
   5408   1.1  christos 	 */
   5409   1.1  christos 	qctx->options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */
   5410   1.1  christos 	if (dns_rdatatype_atparent(qctx->qtype) &&
   5411   1.1  christos 	    !dns_name_equal(qctx->client->query.qname, dns_rootname))
   5412   1.1  christos 	{
   5413   1.1  christos 		/*
   5414   1.1  christos 		 * If authoritative data for this QTYPE is supposed to live in
   5415   1.1  christos 		 * the parent zone, do not look for an exact match for QNAME,
   5416   1.1  christos 		 * but rather for its containing zone (unless the QNAME is
   5417   1.1  christos 		 * root).
   5418   1.1  christos 		 */
   5419   1.1  christos 		qctx->options |= DNS_GETDB_NOEXACT;
   5420   1.1  christos 	}
   5421   1.1  christos 
   5422   1.1  christos 	result = query_getdb(qctx->client, qctx->client->query.qname,
   5423   1.9  christos 			     qctx->qtype, qctx->options, &qctx->zone, &qctx->db,
   5424   1.9  christos 			     &qctx->version, &qctx->is_zone);
   5425   1.1  christos 	if (ISC_UNLIKELY((result != ISC_R_SUCCESS || !qctx->is_zone) &&
   5426   1.1  christos 			 qctx->qtype == dns_rdatatype_ds &&
   5427   1.1  christos 			 !RECURSIONOK(qctx->client) &&
   5428   1.1  christos 			 (qctx->options & DNS_GETDB_NOEXACT) != 0))
   5429   1.1  christos 	{
   5430   1.1  christos 		/*
   5431   1.1  christos 		 * This is a non-recursive QTYPE=DS query with QNAME whose
   5432   1.1  christos 		 * parent we are not authoritative for.  Check whether we are
   5433   1.1  christos 		 * authoritative for QNAME, because if so, we need to send a
   5434   1.1  christos 		 * "no data" response as required by RFC 4035, section 3.1.4.1.
   5435   1.1  christos 		 */
   5436   1.1  christos 		dns_db_t *tdb = NULL;
   5437   1.1  christos 		dns_zone_t *tzone = NULL;
   5438   1.1  christos 		dns_dbversion_t *tversion = NULL;
   5439   1.1  christos 		isc_result_t tresult;
   5440   1.1  christos 
   5441   1.9  christos 		tresult = query_getzonedb(
   5442   1.9  christos 			qctx->client, qctx->client->query.qname, qctx->qtype,
   5443   1.9  christos 			DNS_GETDB_PARTIAL, &tzone, &tdb, &tversion);
   5444   1.1  christos 		if (tresult == ISC_R_SUCCESS) {
   5445   1.1  christos 			/*
   5446   1.1  christos 			 * We are authoritative for QNAME.  Attach the relevant
   5447   1.1  christos 			 * zone to query context, set result to ISC_R_SUCCESS.
   5448   1.1  christos 			 */
   5449   1.1  christos 			qctx->options &= ~DNS_GETDB_NOEXACT;
   5450   1.3  christos 			ns_client_putrdataset(qctx->client, &qctx->rdataset);
   5451   1.1  christos 			if (qctx->db != NULL) {
   5452   1.1  christos 				dns_db_detach(&qctx->db);
   5453   1.1  christos 			}
   5454   1.1  christos 			if (qctx->zone != NULL) {
   5455   1.1  christos 				dns_zone_detach(&qctx->zone);
   5456   1.1  christos 			}
   5457   1.1  christos 			qctx->version = NULL;
   5458   1.1  christos 			RESTORE(qctx->version, tversion);
   5459   1.1  christos 			RESTORE(qctx->db, tdb);
   5460   1.1  christos 			RESTORE(qctx->zone, tzone);
   5461   1.3  christos 			qctx->is_zone = true;
   5462   1.1  christos 			result = ISC_R_SUCCESS;
   5463   1.1  christos 		} else {
   5464   1.1  christos 			/*
   5465   1.1  christos 			 * We are not authoritative for QNAME.  Clean up and
   5466   1.1  christos 			 * leave result as it was.
   5467   1.1  christos 			 */
   5468   1.1  christos 			if (tdb != NULL) {
   5469   1.1  christos 				dns_db_detach(&tdb);
   5470   1.1  christos 			}
   5471   1.1  christos 			if (tzone != NULL) {
   5472   1.1  christos 				dns_zone_detach(&tzone);
   5473   1.1  christos 			}
   5474   1.1  christos 		}
   5475   1.1  christos 	}
   5476   1.1  christos 	/*
   5477   1.1  christos 	 * If we did not find a database from which we can answer the query,
   5478   1.1  christos 	 * respond with either REFUSED or SERVFAIL, depending on what the
   5479   1.1  christos 	 * result of query_getdb() was.
   5480   1.1  christos 	 */
   5481   1.1  christos 	if (result != ISC_R_SUCCESS) {
   5482   1.1  christos 		if (result == DNS_R_REFUSED) {
   5483   1.1  christos 			if (WANTRECURSION(qctx->client)) {
   5484   1.1  christos 				inc_stats(qctx->client,
   5485   1.1  christos 					  ns_statscounter_recurserej);
   5486   1.1  christos 			} else {
   5487   1.1  christos 				inc_stats(qctx->client,
   5488   1.1  christos 					  ns_statscounter_authrej);
   5489   1.1  christos 			}
   5490   1.1  christos 			if (!PARTIALANSWER(qctx->client)) {
   5491   1.1  christos 				QUERY_ERROR(qctx, DNS_R_REFUSED);
   5492   1.1  christos 			}
   5493   1.1  christos 		} else {
   5494   1.9  christos 			CCTRACE(ISC_LOG_ERROR, "ns__query_start: query_getdb "
   5495   1.9  christos 					       "failed");
   5496   1.3  christos 			QUERY_ERROR(qctx, result);
   5497   1.1  christos 		}
   5498   1.3  christos 		return (ns_query_done(qctx));
   5499   1.1  christos 	}
   5500   1.1  christos 
   5501   1.1  christos 	/*
   5502   1.1  christos 	 * We found a database from which we can answer the query.  Update
   5503   1.1  christos 	 * relevant query context flags if the answer is to be prepared using
   5504   1.1  christos 	 * authoritative data.
   5505   1.1  christos 	 */
   5506   1.3  christos 	qctx->is_staticstub_zone = false;
   5507   1.1  christos 	if (qctx->is_zone) {
   5508   1.3  christos 		qctx->authoritative = true;
   5509   1.3  christos 		if (qctx->zone != NULL) {
   5510   1.3  christos 			if (dns_zone_gettype(qctx->zone) == dns_zone_mirror) {
   5511   1.3  christos 				qctx->authoritative = false;
   5512   1.3  christos 			}
   5513   1.9  christos 			if (dns_zone_gettype(qctx->zone) == dns_zone_staticstub)
   5514   1.3  christos 			{
   5515   1.3  christos 				qctx->is_staticstub_zone = true;
   5516   1.3  christos 			}
   5517   1.1  christos 		}
   5518   1.1  christos 	}
   5519   1.1  christos 
   5520   1.1  christos 	/*
   5521   1.1  christos 	 * Attach to the database which will be used to prepare the answer.
   5522   1.1  christos 	 * Update query statistics.
   5523   1.1  christos 	 */
   5524   1.1  christos 	if (qctx->event == NULL && qctx->client->query.restarts == 0) {
   5525   1.1  christos 		if (qctx->is_zone) {
   5526   1.1  christos 			if (qctx->zone != NULL) {
   5527   1.1  christos 				/*
   5528   1.1  christos 				 * if is_zone = true, zone = NULL then this is
   5529   1.1  christos 				 * a DLZ zone.  Don't attempt to attach zone.
   5530   1.1  christos 				 */
   5531   1.1  christos 				dns_zone_attach(qctx->zone,
   5532   1.1  christos 						&qctx->client->query.authzone);
   5533   1.1  christos 			}
   5534   1.1  christos 			dns_db_attach(qctx->db, &qctx->client->query.authdb);
   5535   1.1  christos 		}
   5536   1.3  christos 		qctx->client->query.authdbset = true;
   5537   1.1  christos 
   5538   1.1  christos 		/* Track TCP vs UDP stats per zone */
   5539   1.1  christos 		if (TCP(qctx->client)) {
   5540   1.1  christos 			inc_stats(qctx->client, ns_statscounter_tcp);
   5541   1.1  christos 		} else {
   5542   1.1  christos 			inc_stats(qctx->client, ns_statscounter_udp);
   5543   1.1  christos 		}
   5544   1.1  christos 	}
   5545   1.1  christos 
   5546  1.11  christos 	if (!qctx->is_zone && (qctx->view->staleanswerclienttimeout == 0) &&
   5547  1.11  christos 	    dns_view_staleanswerenabled(qctx->view))
   5548  1.11  christos 	{
   5549  1.11  christos 		/*
   5550  1.11  christos 		 * If stale answers are enabled and
   5551  1.11  christos 		 * stale-answer-client-timeout is zero, then we can promptly
   5552  1.11  christos 		 * answer with a stale RRset if one is available in cache.
   5553  1.11  christos 		 */
   5554  1.11  christos 		qctx->options |= DNS_GETDB_STALEFIRST;
   5555  1.11  christos 	}
   5556  1.11  christos 
   5557  1.11  christos 	result = query_lookup(qctx);
   5558  1.11  christos 
   5559  1.11  christos 	/*
   5560  1.11  christos 	 * Clear "look-also-for-stale-data" flag.
   5561  1.11  christos 	 * If a fetch is created to resolve this query, then,
   5562  1.11  christos 	 * when it completes, this option is not expected to be set.
   5563  1.11  christos 	 */
   5564  1.11  christos 	qctx->options &= ~DNS_GETDB_STALEFIRST;
   5565   1.3  christos 
   5566   1.9  christos cleanup:
   5567   1.3  christos 	return (result);
   5568   1.1  christos }
   5569   1.1  christos 
   5570  1.11  christos /*
   5571  1.11  christos  * Allocate buffers in 'qctx' used to store query results.
   5572  1.11  christos  *
   5573  1.11  christos  * 'buffer' must be a pointer to an object whose lifetime
   5574  1.11  christos  * doesn't expire while 'qctx' is in use.
   5575  1.11  christos  */
   5576  1.11  christos static isc_result_t
   5577  1.11  christos qctx_prepare_buffers(query_ctx_t *qctx, isc_buffer_t *buffer) {
   5578  1.11  christos 	REQUIRE(qctx != NULL);
   5579  1.11  christos 	REQUIRE(qctx->client != NULL);
   5580  1.11  christos 	REQUIRE(buffer != NULL);
   5581  1.11  christos 
   5582  1.11  christos 	qctx->dbuf = ns_client_getnamebuf(qctx->client);
   5583  1.11  christos 	if (ISC_UNLIKELY(qctx->dbuf == NULL)) {
   5584  1.11  christos 		CCTRACE(ISC_LOG_ERROR,
   5585  1.11  christos 			"qctx_prepare_buffers: ns_client_getnamebuf "
   5586  1.11  christos 			"failed");
   5587  1.11  christos 		return (ISC_R_NOMEMORY);
   5588  1.11  christos 	}
   5589  1.11  christos 
   5590  1.11  christos 	qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, buffer);
   5591  1.11  christos 	if (ISC_UNLIKELY(qctx->fname == NULL)) {
   5592  1.11  christos 		CCTRACE(ISC_LOG_ERROR,
   5593  1.11  christos 			"qctx_prepare_buffers: ns_client_newname failed");
   5594  1.11  christos 
   5595  1.11  christos 		return (ISC_R_NOMEMORY);
   5596  1.11  christos 	}
   5597  1.11  christos 
   5598  1.11  christos 	qctx->rdataset = ns_client_newrdataset(qctx->client);
   5599  1.11  christos 	if (ISC_UNLIKELY(qctx->rdataset == NULL)) {
   5600  1.11  christos 		CCTRACE(ISC_LOG_ERROR,
   5601  1.11  christos 			"qctx_prepare_buffers: ns_client_newrdataset failed");
   5602  1.11  christos 		goto error;
   5603  1.11  christos 	}
   5604  1.11  christos 
   5605  1.11  christos 	if ((WANTDNSSEC(qctx->client) || qctx->findcoveringnsec) &&
   5606  1.11  christos 	    (!qctx->is_zone || dns_db_issecure(qctx->db)))
   5607  1.11  christos 	{
   5608  1.11  christos 		qctx->sigrdataset = ns_client_newrdataset(qctx->client);
   5609  1.11  christos 		if (qctx->sigrdataset == NULL) {
   5610  1.11  christos 			CCTRACE(ISC_LOG_ERROR,
   5611  1.11  christos 				"qctx_prepare_buffers: "
   5612  1.11  christos 				"ns_client_newrdataset failed (2)");
   5613  1.11  christos 			goto error;
   5614  1.11  christos 		}
   5615  1.11  christos 	}
   5616  1.11  christos 
   5617  1.11  christos 	return (ISC_R_SUCCESS);
   5618  1.11  christos 
   5619  1.11  christos error:
   5620  1.11  christos 	if (qctx->fname != NULL) {
   5621  1.11  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   5622  1.11  christos 	}
   5623  1.11  christos 	if (qctx->rdataset != NULL) {
   5624  1.11  christos 		ns_client_putrdataset(qctx->client, &qctx->rdataset);
   5625  1.11  christos 	}
   5626  1.11  christos 
   5627  1.11  christos 	return (ISC_R_NOMEMORY);
   5628  1.11  christos }
   5629  1.11  christos 
   5630  1.11  christos /*
   5631  1.11  christos  * Setup a new query context for resolving a query.
   5632  1.11  christos  *
   5633  1.11  christos  * This function is only called if both these conditions are met:
   5634  1.11  christos  *    1. BIND is configured with stale-answer-client-timeout 0.
   5635  1.11  christos  *    2. A stale RRset is found in cache during initial query
   5636  1.11  christos  *       database lookup.
   5637  1.11  christos  *
   5638  1.11  christos  * We continue with this function for refreshing/resolving an RRset
   5639  1.11  christos  * after answering a client with stale data.
   5640  1.11  christos  */
   5641  1.11  christos static void
   5642  1.11  christos query_refresh_rrset(query_ctx_t *orig_qctx) {
   5643  1.11  christos 	isc_buffer_t buffer;
   5644  1.11  christos 	query_ctx_t qctx;
   5645  1.11  christos 
   5646  1.11  christos 	REQUIRE(orig_qctx != NULL);
   5647  1.11  christos 	REQUIRE(orig_qctx->client != NULL);
   5648  1.11  christos 
   5649  1.11  christos 	qctx_copy(orig_qctx, &qctx);
   5650  1.11  christos 	qctx.client->query.dboptions &= ~(DNS_DBFIND_STALEONLY |
   5651  1.11  christos 					  DNS_DBFIND_STALEOK |
   5652  1.11  christos 					  DNS_DBFIND_STALEENABLED);
   5653  1.11  christos 
   5654  1.11  christos 	/*
   5655  1.11  christos 	 * We'll need some resources...
   5656  1.11  christos 	 */
   5657  1.11  christos 	if (qctx_prepare_buffers(&qctx, &buffer) != ISC_R_SUCCESS) {
   5658  1.11  christos 		dns_db_detach(&qctx.db);
   5659  1.11  christos 		qctx_destroy(&qctx);
   5660  1.11  christos 		return;
   5661  1.11  christos 	}
   5662  1.11  christos 
   5663  1.11  christos 	/*
   5664  1.11  christos 	 * Pretend we didn't find anything in cache.
   5665  1.11  christos 	 */
   5666  1.11  christos 	(void)query_gotanswer(&qctx, ISC_R_NOTFOUND);
   5667  1.11  christos 
   5668  1.11  christos 	if (qctx.fname != NULL) {
   5669  1.11  christos 		ns_client_releasename(qctx.client, &qctx.fname);
   5670  1.11  christos 	}
   5671  1.11  christos 	if (qctx.rdataset != NULL) {
   5672  1.11  christos 		ns_client_putrdataset(qctx.client, &qctx.rdataset);
   5673  1.11  christos 	}
   5674  1.11  christos 
   5675  1.11  christos 	qctx_destroy(&qctx);
   5676  1.11  christos }
   5677  1.11  christos 
   5678   1.1  christos /*%
   5679   1.1  christos  * Perform a local database lookup, in either an authoritative or
   5680   1.3  christos  * cache database. If unable to answer, call ns_query_done(); otherwise
   5681   1.1  christos  * hand off processing to query_gotanswer().
   5682   1.1  christos  */
   5683   1.1  christos static isc_result_t
   5684   1.1  christos query_lookup(query_ctx_t *qctx) {
   5685  1.11  christos 	isc_buffer_t buffer;
   5686  1.11  christos 	isc_result_t result = ISC_R_UNSET;
   5687   1.1  christos 	dns_clientinfomethods_t cm;
   5688   1.1  christos 	dns_clientinfo_t ci;
   5689   1.1  christos 	dns_name_t *rpzqname = NULL;
   5690   1.1  christos 	unsigned int dboptions;
   5691  1.11  christos 	dns_ttl_t stale_refresh = 0;
   5692  1.11  christos 	bool dbfind_stale = false;
   5693  1.11  christos 	bool stale_only = false;
   5694  1.11  christos 	bool stale_found = false;
   5695  1.11  christos 	bool refresh_rrset = false;
   5696  1.11  christos 	bool stale_refresh_window = false;
   5697   1.1  christos 
   5698   1.1  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_lookup");
   5699   1.1  christos 
   5700   1.3  christos 	CALL_HOOK(NS_QUERY_LOOKUP_BEGIN, qctx);
   5701   1.1  christos 
   5702   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   5703   1.1  christos 	dns_clientinfo_init(&ci, qctx->client, NULL);
   5704   1.1  christos 
   5705   1.1  christos 	/*
   5706   1.1  christos 	 * We'll need some resources...
   5707   1.1  christos 	 */
   5708  1.11  christos 	result = qctx_prepare_buffers(qctx, &buffer);
   5709  1.11  christos 	if (result != ISC_R_SUCCESS) {
   5710  1.11  christos 		QUERY_ERROR(qctx, result);
   5711   1.3  christos 		return (ns_query_done(qctx));
   5712   1.1  christos 	}
   5713   1.1  christos 
   5714   1.1  christos 	/*
   5715   1.1  christos 	 * Now look for an answer in the database.
   5716   1.1  christos 	 */
   5717   1.1  christos 	if (qctx->dns64 && qctx->rpz) {
   5718   1.1  christos 		rpzqname = qctx->client->query.rpz_st->p_name;
   5719   1.1  christos 	} else {
   5720   1.1  christos 		rpzqname = qctx->client->query.qname;
   5721   1.1  christos 	}
   5722   1.1  christos 
   5723  1.11  christos 	if ((qctx->options & DNS_GETDB_STALEFIRST) != 0) {
   5724  1.11  christos 		/*
   5725  1.11  christos 		 * If DNS_GETDB_STALEFIRST is set, it means that a stale
   5726  1.11  christos 		 * RRset may be returned as part of this lookup. An attempt
   5727  1.11  christos 		 * to refresh the RRset will still take place if an
   5728  1.11  christos 		 * active RRset is not available.
   5729  1.11  christos 		 */
   5730  1.11  christos 		qctx->client->query.dboptions |= DNS_DBFIND_STALEONLY;
   5731  1.11  christos 	}
   5732  1.11  christos 
   5733   1.1  christos 	dboptions = qctx->client->query.dboptions;
   5734   1.1  christos 	if (!qctx->is_zone && qctx->findcoveringnsec &&
   5735   1.1  christos 	    (qctx->type != dns_rdatatype_null || !dns_name_istat(rpzqname)))
   5736   1.9  christos 	{
   5737   1.1  christos 		dboptions |= DNS_DBFIND_COVERINGNSEC;
   5738   1.9  christos 	}
   5739   1.1  christos 
   5740  1.11  christos 	(void)dns_db_getservestalerefresh(qctx->client->view->cachedb,
   5741  1.11  christos 					  &stale_refresh);
   5742  1.11  christos 	if (stale_refresh > 0 &&
   5743  1.11  christos 	    dns_view_staleanswerenabled(qctx->client->view)) {
   5744  1.11  christos 		dboptions |= DNS_DBFIND_STALEENABLED;
   5745  1.11  christos 	}
   5746  1.11  christos 
   5747   1.1  christos 	result = dns_db_findext(qctx->db, rpzqname, qctx->version, qctx->type,
   5748   1.1  christos 				dboptions, qctx->client->now, &qctx->node,
   5749   1.9  christos 				qctx->fname, &cm, &ci, qctx->rdataset,
   5750   1.9  christos 				qctx->sigrdataset);
   5751   1.1  christos 
   5752   1.1  christos 	/*
   5753   1.1  christos 	 * Fixup fname and sigrdataset.
   5754   1.1  christos 	 */
   5755   1.1  christos 	if (qctx->dns64 && qctx->rpz) {
   5756   1.8  christos 		dns_name_copynf(qctx->client->query.qname, qctx->fname);
   5757   1.1  christos 		if (qctx->sigrdataset != NULL &&
   5758   1.9  christos 		    dns_rdataset_isassociated(qctx->sigrdataset)) {
   5759   1.1  christos 			dns_rdataset_disassociate(qctx->sigrdataset);
   5760   1.1  christos 		}
   5761   1.1  christos 	}
   5762   1.1  christos 
   5763   1.1  christos 	if (!qctx->is_zone) {
   5764   1.3  christos 		dns_cache_updatestats(qctx->view->cache, result);
   5765   1.1  christos 	}
   5766   1.1  christos 
   5767  1.11  christos 	/*
   5768  1.11  christos 	 * If DNS_DBFIND_STALEOK is set this means we are dealing with a
   5769  1.11  christos 	 * lookup following a failed lookup and it is okay to serve a stale
   5770  1.11  christos 	 * answer. This will (re)start the 'stale-refresh-time' window in
   5771  1.11  christos 	 * rbtdb, tracking the last time the RRset lookup failed.
   5772  1.11  christos 	 */
   5773  1.11  christos 	dbfind_stale = ((dboptions & DNS_DBFIND_STALEOK) != 0);
   5774  1.11  christos 
   5775  1.11  christos 	/*
   5776  1.11  christos 	 * If DNS_DBFIND_STALEENABLED is set, this may be a normal lookup, but
   5777  1.11  christos 	 * we are allowed to immediately respond with a stale answer if the
   5778  1.11  christos 	 * request is within the 'stale-refresh-time' window.
   5779  1.11  christos 	 */
   5780  1.11  christos 	stale_refresh_window = (STALE_WINDOW(qctx->rdataset) &&
   5781  1.11  christos 				(dboptions & DNS_DBFIND_STALEENABLED) != 0);
   5782  1.11  christos 
   5783  1.11  christos 	/*
   5784  1.11  christos 	 * If DNS_DBFIND_STALEONLY is set, a stale positive answer is requested.
   5785  1.11  christos 	 * This can happen if 'stale-answer-client-timeout' is enabled.
   5786  1.11  christos 	 *
   5787  1.11  christos 	 * If 'stale-answer-client-timeout' is set to 0, and a stale positive
   5788  1.11  christos 	 * answer is found, send it to the client, and try to refresh the
   5789  1.11  christos 	 * RRset. If a stale negative answer is found, continue with recursion
   5790  1.11  christos 	 * (perhaps the query will be resolved eventually and the answer from
   5791  1.11  christos 	 * the authoritative is returned to the client, or the query will
   5792  1.11  christos 	 * timeout, in that case DNS_DBFIND_STALEOK may be set, and a stale
   5793  1.11  christos 	 * negative answer is returned (or SERVFAIL).
   5794  1.11  christos 	 *
   5795  1.11  christos 	 * If 'stale-answer-client-timeout' is non-zero, and a stale positive
   5796  1.11  christos 	 * answer is found, send it to the client. Don't try to refresh the
   5797  1.11  christos 	 * RRset because a fetch is already in progress. If a stale negative
   5798  1.11  christos 	 * answer is found, then abort the lookup and the client has to wait
   5799  1.11  christos 	 * until recursion is finished.
   5800  1.11  christos 	 */
   5801  1.11  christos 	stale_only = ((dboptions & DNS_DBFIND_STALEONLY) != 0);
   5802  1.11  christos 
   5803  1.11  christos 	if (dbfind_stale ||
   5804  1.11  christos 	    (STALE(qctx->rdataset) && (stale_only || stale_refresh_window)))
   5805  1.11  christos 	{
   5806   1.1  christos 		char namebuf[DNS_NAME_FORMATSIZE];
   5807   1.1  christos 
   5808  1.11  christos 		inc_stats(qctx->client, ns_statscounter_trystale);
   5809  1.11  christos 
   5810   1.1  christos 		if (dns_rdataset_isassociated(qctx->rdataset) &&
   5811   1.1  christos 		    dns_rdataset_count(qctx->rdataset) > 0 &&
   5812   1.9  christos 		    STALE(qctx->rdataset))
   5813   1.9  christos 		{
   5814   1.3  christos 			qctx->rdataset->ttl = qctx->view->staleanswerttl;
   5815  1.11  christos 			stale_found = true;
   5816   1.1  christos 		} else {
   5817  1.11  christos 			stale_found = false;
   5818   1.1  christos 		}
   5819   1.1  christos 
   5820   1.9  christos 		dns_name_format(qctx->client->query.qname, namebuf,
   5821   1.9  christos 				sizeof(namebuf));
   5822   1.1  christos 
   5823  1.11  christos 		if (dbfind_stale) {
   5824  1.11  christos 			isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE,
   5825  1.11  christos 				      NS_LOGMODULE_QUERY, ISC_LOG_INFO,
   5826  1.11  christos 				      "%s resolver failure, stale answer %s",
   5827  1.11  christos 				      namebuf,
   5828  1.11  christos 				      stale_found ? "used" : "unavailable");
   5829  1.11  christos 			if (!stale_found) {
   5830  1.11  christos 				/*
   5831  1.11  christos 				 * Resolver failure, no stale data, nothing
   5832  1.11  christos 				 * more we can do, return SERVFAIL.
   5833  1.11  christos 				 */
   5834  1.11  christos 				QUERY_ERROR(qctx, DNS_R_SERVFAIL);
   5835  1.11  christos 				return (ns_query_done(qctx));
   5836  1.11  christos 			}
   5837  1.11  christos 
   5838  1.11  christos 			stale_only = false;
   5839  1.11  christos 		} else if (stale_refresh_window) {
   5840  1.11  christos 			/*
   5841  1.11  christos 			 * A recent lookup failed, so during this time window
   5842  1.11  christos 			 * we are allowed to return stale data immediately.
   5843  1.11  christos 			 */
   5844  1.11  christos 			isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE,
   5845  1.11  christos 				      NS_LOGMODULE_QUERY, ISC_LOG_INFO,
   5846  1.11  christos 				      "%s query within stale refresh time, "
   5847  1.11  christos 				      "stale answer %s",
   5848  1.11  christos 				      namebuf,
   5849  1.11  christos 				      stale_found ? "used" : "unavailable");
   5850  1.11  christos 
   5851  1.11  christos 			if (!stale_found) {
   5852  1.11  christos 				/*
   5853  1.11  christos 				 * During the stale refresh window explicitly
   5854  1.11  christos 				 * do not try to refresh the data, because a
   5855  1.11  christos 				 * recent lookup failed.
   5856  1.11  christos 				 */
   5857  1.11  christos 				QUERY_ERROR(qctx, DNS_R_SERVFAIL);
   5858  1.11  christos 				return (ns_query_done(qctx));
   5859  1.11  christos 			}
   5860  1.11  christos 
   5861  1.11  christos 			stale_only = false;
   5862  1.11  christos 		} else if ((dboptions & DNS_DBFIND_STALEONLY) != 0) {
   5863  1.11  christos 			if ((qctx->options & DNS_GETDB_STALEFIRST) != 0) {
   5864  1.11  christos 				if (stale_found && result == ISC_R_SUCCESS) {
   5865  1.11  christos 					/*
   5866  1.11  christos 					 * Immediately return the stale answer,
   5867  1.11  christos 					 * start a resolver fetch to refresh
   5868  1.11  christos 					 * the data in cache.
   5869  1.11  christos 					 */
   5870  1.11  christos 					isc_log_write(
   5871  1.11  christos 						ns_lctx,
   5872  1.11  christos 						NS_LOGCATEGORY_SERVE_STALE,
   5873  1.11  christos 						NS_LOGMODULE_QUERY,
   5874  1.11  christos 						ISC_LOG_INFO,
   5875  1.11  christos 						"%s stale answer used, an "
   5876  1.11  christos 						"attempt to refresh the RRset "
   5877  1.11  christos 						"will still be made",
   5878  1.11  christos 						namebuf);
   5879  1.11  christos 					refresh_rrset = true;
   5880  1.11  christos 				} else {
   5881  1.11  christos 					/*
   5882  1.11  christos 					 * We have nothing useful in cache to
   5883  1.11  christos 					 * return immediately.
   5884  1.11  christos 					 */
   5885  1.11  christos 					qctx_clean(qctx);
   5886  1.11  christos 					qctx_freedata(qctx);
   5887  1.11  christos 					dns_db_attach(
   5888  1.11  christos 						qctx->client->view->cachedb,
   5889  1.11  christos 						&qctx->db);
   5890  1.11  christos 					qctx->client->query.dboptions &=
   5891  1.11  christos 						~DNS_DBFIND_STALEONLY;
   5892  1.11  christos 					qctx->options &= ~DNS_GETDB_STALEFIRST;
   5893  1.11  christos 					if (qctx->client->query.fetch != NULL) {
   5894  1.11  christos 						dns_resolver_destroyfetch(
   5895  1.11  christos 							&qctx->client->query
   5896  1.11  christos 								 .fetch);
   5897  1.11  christos 					}
   5898  1.11  christos 					return query_lookup(qctx);
   5899  1.11  christos 				}
   5900  1.11  christos 			} else {
   5901  1.11  christos 				/*
   5902  1.11  christos 				 * The 'stale-answer-client-timeout' triggered,
   5903  1.11  christos 				 * return the stale answer if available,
   5904  1.11  christos 				 * otherwise wait until the resolver finishes.
   5905  1.11  christos 				 */
   5906  1.11  christos 				isc_log_write(
   5907  1.11  christos 					ns_lctx, NS_LOGCATEGORY_SERVE_STALE,
   5908  1.11  christos 					NS_LOGMODULE_QUERY, ISC_LOG_INFO,
   5909  1.11  christos 					"%s client timeout, stale answer %s",
   5910  1.11  christos 					namebuf,
   5911  1.11  christos 					stale_found ? "used" : "unavailable");
   5912  1.11  christos 				if (!stale_found || result != ISC_R_SUCCESS) {
   5913  1.11  christos 					return (result);
   5914  1.11  christos 				}
   5915  1.11  christos 			}
   5916   1.1  christos 		}
   5917  1.11  christos 	} else {
   5918  1.11  christos 		stale_only = false;
   5919  1.11  christos 	}
   5920  1.11  christos 
   5921  1.11  christos 	if (!stale_only) {
   5922  1.11  christos 		/*
   5923  1.11  christos 		 * The DNS_DBFIND_STALEONLY option may be set, but if we
   5924  1.11  christos 		 * didn't have stale data in cache, or we responded with
   5925  1.11  christos 		 * a stale answer because of 'stale-refresh-time', this is
   5926  1.11  christos 		 * actually not a 'stale-only' lookup. Clear the flag to
   5927  1.11  christos 		 * allow the client to be detach the handle.
   5928  1.11  christos 		 */
   5929  1.11  christos 		qctx->client->query.dboptions &= ~DNS_DBFIND_STALEONLY;
   5930  1.11  christos 	}
   5931  1.11  christos 
   5932  1.11  christos 	result = query_gotanswer(qctx, result);
   5933  1.11  christos 
   5934  1.11  christos 	if (refresh_rrset) {
   5935  1.11  christos 		/*
   5936  1.11  christos 		 * If we reached this point then it means that we have found a
   5937  1.11  christos 		 * stale RRset entry in cache and BIND is configured to allow
   5938  1.11  christos 		 * queries to be answered with stale data if no active RRset
   5939  1.11  christos 		 * is available, i.e. "stale-anwer-client-timeout 0". But, we
   5940  1.11  christos 		 * still need to refresh the RRset.
   5941  1.11  christos 		 */
   5942  1.11  christos 		query_refresh_rrset(qctx);
   5943   1.1  christos 	}
   5944   1.3  christos 
   5945   1.9  christos cleanup:
   5946   1.3  christos 	return (result);
   5947   1.1  christos }
   5948   1.1  christos 
   5949   1.1  christos /*
   5950  1.11  christos  * Create a new query context with the sole intent
   5951  1.11  christos  * of looking up for a stale RRset in cache.
   5952  1.11  christos  * If an entry is found, we mark the original query as
   5953  1.11  christos  * answered, in order to avoid answering the query twice,
   5954  1.11  christos  * when the original fetch finishes.
   5955  1.11  christos  */
   5956  1.11  christos static inline void
   5957  1.11  christos query_lookup_staleonly(ns_client_t *client) {
   5958  1.11  christos 	query_ctx_t qctx;
   5959  1.11  christos 
   5960  1.11  christos 	qctx_init(client, NULL, client->query.qtype, &qctx);
   5961  1.11  christos 	dns_db_attach(client->view->cachedb, &qctx.db);
   5962  1.11  christos 	client->query.dboptions |= DNS_DBFIND_STALEONLY;
   5963  1.11  christos 	(void)query_lookup(&qctx);
   5964  1.11  christos 	if (qctx.node != NULL) {
   5965  1.11  christos 		dns_db_detachnode(qctx.db, &qctx.node);
   5966  1.11  christos 	}
   5967  1.11  christos 	qctx_freedata(&qctx);
   5968  1.11  christos 	client->query.dboptions &= ~DNS_DBFIND_STALEONLY;
   5969  1.11  christos 	qctx_destroy(&qctx);
   5970  1.11  christos }
   5971  1.11  christos 
   5972  1.11  christos /*
   5973  1.11  christos  * Event handler to resume processing a query after recursion, or when a
   5974  1.11  christos  * client timeout is triggered. If the query has timed out or been cancelled
   5975  1.11  christos  * or the system is shutting down, clean up and exit. If a client timeout is
   5976  1.11  christos  * triggered, see if we can respond with a stale answer from cache. Otherwise,
   5977  1.11  christos  * call query_resume() to continue the ongoing work.
   5978   1.1  christos  */
   5979   1.1  christos static void
   5980   1.1  christos fetch_callback(isc_task_t *task, isc_event_t *event) {
   5981   1.1  christos 	dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
   5982   1.1  christos 	dns_fetch_t *fetch = NULL;
   5983   1.1  christos 	ns_client_t *client;
   5984   1.3  christos 	bool fetch_canceled, client_shuttingdown;
   5985   1.1  christos 	isc_result_t result;
   5986   1.1  christos 	isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_ERRORS;
   5987   1.1  christos 	int errorloglevel;
   5988  1.11  christos 	query_ctx_t qctx;
   5989   1.1  christos 
   5990   1.1  christos 	UNUSED(task);
   5991   1.1  christos 
   5992  1.11  christos 	REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE ||
   5993  1.11  christos 		event->ev_type == DNS_EVENT_TRYSTALE);
   5994   1.1  christos 	client = devent->ev_arg;
   5995   1.1  christos 	REQUIRE(NS_CLIENT_VALID(client));
   5996   1.1  christos 	REQUIRE(task == client->task);
   5997   1.1  christos 	REQUIRE(RECURSING(client));
   5998   1.1  christos 
   5999   1.9  christos 	CTRACE(ISC_LOG_DEBUG(3), "fetch_callback");
   6000   1.9  christos 
   6001  1.11  christos 	if (event->ev_type == DNS_EVENT_TRYSTALE) {
   6002  1.11  christos 		query_lookup_staleonly(client);
   6003  1.11  christos 		isc_event_free(ISC_EVENT_PTR(&event));
   6004  1.11  christos 		return;
   6005  1.11  christos 	} else {
   6006  1.11  christos 		client->query.dboptions &= ~DNS_DBFIND_STALEONLY;
   6007  1.11  christos 	}
   6008  1.11  christos 
   6009   1.1  christos 	LOCK(&client->query.fetchlock);
   6010   1.1  christos 	if (client->query.fetch != NULL) {
   6011   1.1  christos 		/*
   6012   1.1  christos 		 * This is the fetch we've been waiting for.
   6013   1.1  christos 		 */
   6014   1.1  christos 		INSIST(devent->fetch == client->query.fetch);
   6015   1.1  christos 		client->query.fetch = NULL;
   6016   1.3  christos 		fetch_canceled = false;
   6017   1.1  christos 		/*
   6018   1.1  christos 		 * Update client->now.
   6019   1.1  christos 		 */
   6020   1.1  christos 		isc_stdtime_get(&client->now);
   6021   1.1  christos 	} else {
   6022   1.1  christos 		/*
   6023   1.1  christos 		 * This is a fetch completion event for a canceled fetch.
   6024   1.1  christos 		 * Clean up and don't resume the find.
   6025   1.1  christos 		 */
   6026   1.3  christos 		fetch_canceled = true;
   6027   1.1  christos 	}
   6028   1.1  christos 	UNLOCK(&client->query.fetchlock);
   6029   1.1  christos 	INSIST(client->query.fetch == NULL);
   6030   1.1  christos 
   6031   1.9  christos 	SAVE(fetch, devent->fetch);
   6032   1.9  christos 
   6033   1.9  christos 	/*
   6034   1.9  christos 	 * We're done recursing, detach from quota and unlink from
   6035   1.9  christos 	 * the manager's recursing-clients list.
   6036   1.9  christos 	 */
   6037   1.9  christos 
   6038   1.9  christos 	if (client->recursionquota != NULL) {
   6039   1.9  christos 		isc_quota_detach(&client->recursionquota);
   6040   1.9  christos 		ns_stats_decrement(client->sctx->nsstats,
   6041   1.9  christos 				   ns_statscounter_recursclients);
   6042  1.11  christos 	} else if (client->attributes & NS_CLIENTATTR_RECURSING) {
   6043  1.11  christos 		client->attributes &= ~NS_CLIENTATTR_RECURSING;
   6044  1.11  christos 		/*
   6045  1.11  christos 		 * Detached from recursionquota via prefetch_done(),
   6046  1.11  christos 		 * but need to decrement recursive client stats here anyway,
   6047  1.11  christos 		 * since it was incremented in ns_query_recurse().
   6048  1.11  christos 		 */
   6049  1.11  christos 		ns_stats_decrement(client->sctx->nsstats,
   6050  1.11  christos 				   ns_statscounter_recursclients);
   6051   1.9  christos 	}
   6052   1.9  christos 
   6053   1.9  christos 	LOCK(&client->manager->reclock);
   6054   1.9  christos 	if (ISC_LINK_LINKED(client, rlink)) {
   6055   1.9  christos 		ISC_LIST_UNLINK(client->manager->recursing, client, rlink);
   6056   1.9  christos 	}
   6057   1.9  christos 	UNLOCK(&client->manager->reclock);
   6058   1.9  christos 
   6059  1.11  christos 	isc_nmhandle_detach(&client->fetchhandle);
   6060  1.11  christos 
   6061   1.1  christos 	client->query.attributes &= ~NS_QUERYATTR_RECURSING;
   6062   1.9  christos 	client->state = NS_CLIENTSTATE_WORKING;
   6063   1.1  christos 
   6064   1.1  christos 	/*
   6065  1.11  christos 	 * Initialize a new qctx and use it to either resume from
   6066  1.11  christos 	 * recursion or clean up after cancelation.  Transfer
   6067  1.11  christos 	 * ownership of devent to the new qctx in the process.
   6068   1.1  christos 	 */
   6069  1.11  christos 	qctx_init(client, &devent, 0, &qctx);
   6070  1.11  christos 
   6071   1.1  christos 	client_shuttingdown = ns_client_shuttingdown(client);
   6072   1.1  christos 	if (fetch_canceled || client_shuttingdown) {
   6073  1.11  christos 		/*
   6074  1.11  christos 		 * We've timed out or are shutting down. We can now
   6075  1.11  christos 		 * free the event and other resources held by qctx, but
   6076  1.11  christos 		 * don't call qctx_destroy() yet: it might destroy the
   6077  1.11  christos 		 * client, which we still need for a moment.
   6078  1.11  christos 		 */
   6079  1.11  christos 		qctx_freedata(&qctx);
   6080  1.11  christos 
   6081  1.11  christos 		/*
   6082  1.11  christos 		 * Return an error to the client, or just drop.
   6083  1.11  christos 		 */
   6084   1.1  christos 		if (fetch_canceled) {
   6085   1.1  christos 			CTRACE(ISC_LOG_ERROR, "fetch cancelled");
   6086   1.1  christos 			query_error(client, DNS_R_SERVFAIL, __LINE__);
   6087   1.1  christos 		} else {
   6088   1.1  christos 			query_next(client, ISC_R_CANCELED);
   6089   1.1  christos 		}
   6090  1.11  christos 
   6091  1.11  christos 		/*
   6092  1.11  christos 		 * Free any persistent plugin data that was allocated to
   6093  1.11  christos 		 * service the client, then detach the client object.
   6094  1.11  christos 		 */
   6095  1.11  christos 		qctx.detach_client = true;
   6096  1.11  christos 		qctx_destroy(&qctx);
   6097   1.1  christos 	} else {
   6098   1.3  christos 		/*
   6099  1.11  christos 		 * Resume the find process.
   6100   1.3  christos 		 */
   6101   1.1  christos 		query_trace(&qctx);
   6102   1.1  christos 
   6103   1.1  christos 		result = query_resume(&qctx);
   6104   1.1  christos 		if (result != ISC_R_SUCCESS) {
   6105   1.1  christos 			if (result == DNS_R_SERVFAIL) {
   6106   1.1  christos 				errorloglevel = ISC_LOG_DEBUG(2);
   6107   1.1  christos 			} else {
   6108   1.1  christos 				errorloglevel = ISC_LOG_DEBUG(4);
   6109   1.1  christos 			}
   6110   1.1  christos 			if (isc_log_wouldlog(ns_lctx, errorloglevel)) {
   6111   1.1  christos 				dns_resolver_logfetch(fetch, ns_lctx,
   6112   1.1  christos 						      logcategory,
   6113   1.1  christos 						      NS_LOGMODULE_QUERY,
   6114   1.3  christos 						      errorloglevel, false);
   6115   1.1  christos 			}
   6116   1.1  christos 		}
   6117   1.3  christos 
   6118   1.3  christos 		qctx_destroy(&qctx);
   6119   1.1  christos 	}
   6120   1.1  christos 
   6121   1.1  christos 	dns_resolver_destroyfetch(&fetch);
   6122   1.1  christos }
   6123   1.1  christos 
   6124   1.1  christos /*%
   6125   1.1  christos  * Check whether the recursion parameters in 'param' match the current query's
   6126   1.1  christos  * recursion parameters provided in 'qtype', 'qname', and 'qdomain'.
   6127   1.1  christos  */
   6128   1.3  christos static bool
   6129   1.1  christos recparam_match(const ns_query_recparam_t *param, dns_rdatatype_t qtype,
   6130   1.9  christos 	       const dns_name_t *qname, const dns_name_t *qdomain) {
   6131   1.1  christos 	REQUIRE(param != NULL);
   6132   1.1  christos 
   6133   1.9  christos 	return (param->qtype == qtype && param->qname != NULL &&
   6134   1.9  christos 		qname != NULL && param->qdomain != NULL && qdomain != NULL &&
   6135   1.3  christos 		dns_name_equal(param->qname, qname) &&
   6136   1.3  christos 		dns_name_equal(param->qdomain, qdomain));
   6137   1.1  christos }
   6138   1.1  christos 
   6139   1.1  christos /*%
   6140   1.1  christos  * Update 'param' with current query's recursion parameters provided in
   6141   1.1  christos  * 'qtype', 'qname', and 'qdomain'.
   6142   1.1  christos  */
   6143   1.1  christos static void
   6144   1.1  christos recparam_update(ns_query_recparam_t *param, dns_rdatatype_t qtype,
   6145   1.9  christos 		const dns_name_t *qname, const dns_name_t *qdomain) {
   6146   1.1  christos 	REQUIRE(param != NULL);
   6147   1.1  christos 
   6148   1.1  christos 	param->qtype = qtype;
   6149   1.1  christos 
   6150   1.1  christos 	if (qname == NULL) {
   6151   1.1  christos 		param->qname = NULL;
   6152   1.1  christos 	} else {
   6153   1.3  christos 		param->qname = dns_fixedname_initname(&param->fqname);
   6154   1.8  christos 		dns_name_copynf(qname, param->qname);
   6155   1.1  christos 	}
   6156   1.1  christos 
   6157   1.1  christos 	if (qdomain == NULL) {
   6158   1.1  christos 		param->qdomain = NULL;
   6159   1.1  christos 	} else {
   6160   1.3  christos 		param->qdomain = dns_fixedname_initname(&param->fqdomain);
   6161   1.8  christos 		dns_name_copynf(qdomain, param->qdomain);
   6162   1.1  christos 	}
   6163   1.1  christos }
   6164   1.9  christos static atomic_uint_fast32_t last_soft, last_hard;
   6165   1.9  christos #ifdef ISC_MUTEX_ATOMICS
   6166   1.9  christos static isc_once_t last_once = ISC_ONCE_INIT;
   6167   1.9  christos static void
   6168   1.9  christos last_init() {
   6169   1.9  christos 	atomic_init(&last_soft, 0);
   6170   1.9  christos 	atomic_init(&last_hard, 0);
   6171   1.9  christos }
   6172   1.9  christos #endif /* ifdef ISC_MUTEX_ATOMICS */
   6173   1.1  christos 
   6174   1.3  christos isc_result_t
   6175   1.3  christos ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
   6176   1.3  christos 		 dns_name_t *qdomain, dns_rdataset_t *nameservers,
   6177   1.9  christos 		 bool resuming) {
   6178   1.1  christos 	isc_result_t result;
   6179   1.1  christos 	dns_rdataset_t *rdataset, *sigrdataset;
   6180   1.1  christos 	isc_sockaddr_t *peeraddr = NULL;
   6181   1.1  christos 
   6182   1.3  christos 	CTRACE(ISC_LOG_DEBUG(3), "ns_query_recurse");
   6183   1.1  christos 
   6184   1.1  christos 	/*
   6185   1.1  christos 	 * Check recursion parameters from the previous query to see if they
   6186   1.1  christos 	 * match.  If not, update recursion parameters and proceed.
   6187   1.1  christos 	 */
   6188   1.1  christos 	if (recparam_match(&client->query.recparam, qtype, qname, qdomain)) {
   6189   1.9  christos 		ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY,
   6190   1.9  christos 			      ISC_LOG_INFO, "recursion loop detected");
   6191   1.1  christos 		return (ISC_R_FAILURE);
   6192   1.1  christos 	}
   6193   1.1  christos 
   6194   1.1  christos 	recparam_update(&client->query.recparam, qtype, qname, qdomain);
   6195   1.1  christos 
   6196   1.9  christos 	if (!resuming) {
   6197   1.1  christos 		inc_stats(client, ns_statscounter_recursion);
   6198   1.9  christos 	}
   6199   1.1  christos 
   6200   1.1  christos 	/*
   6201   1.1  christos 	 * We are about to recurse, which means that this client will
   6202   1.1  christos 	 * be unavailable for serving new requests for an indeterminate
   6203   1.1  christos 	 * amount of time.  If this client is currently responsible
   6204   1.1  christos 	 * for handling incoming queries, set up a new client
   6205   1.1  christos 	 * object to handle them while we are waiting for a
   6206   1.1  christos 	 * response.  There is no need to replace TCP clients
   6207   1.1  christos 	 * because those have already been replaced when the
   6208   1.1  christos 	 * connection was accepted (if allowed by the TCP quota).
   6209   1.1  christos 	 */
   6210   1.1  christos 	if (client->recursionquota == NULL) {
   6211   1.1  christos 		result = isc_quota_attach(&client->sctx->recursionquota,
   6212   1.1  christos 					  &client->recursionquota);
   6213   1.6  christos 		if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) {
   6214   1.6  christos 			ns_stats_increment(client->sctx->nsstats,
   6215   1.6  christos 					   ns_statscounter_recursclients);
   6216  1.11  christos 			client->attributes |= NS_CLIENTATTR_RECURSING;
   6217   1.6  christos 		}
   6218   1.1  christos 
   6219   1.9  christos 		if (result == ISC_R_SOFTQUOTA) {
   6220   1.9  christos #ifdef ISC_MUTEX_ATOMICS
   6221   1.9  christos 			isc_once_do(&last_once, last_init);
   6222   1.9  christos #endif /* ifdef ISC_MUTEX_ATOMICS */
   6223   1.1  christos 			isc_stdtime_t now;
   6224   1.1  christos 			isc_stdtime_get(&now);
   6225   1.9  christos 			if (now != atomic_load_relaxed(&last_soft)) {
   6226   1.9  christos 				atomic_store_relaxed(&last_soft, now);
   6227   1.1  christos 				ns_client_log(client, NS_LOGCATEGORY_CLIENT,
   6228   1.9  christos 					      NS_LOGMODULE_QUERY,
   6229   1.9  christos 					      ISC_LOG_WARNING,
   6230   1.9  christos 					      "recursive-clients soft limit "
   6231   1.9  christos 					      "exceeded (%u/%u/%u), "
   6232   1.9  christos 					      "aborting oldest query",
   6233   1.9  christos 					      isc_quota_getused(
   6234   1.9  christos 						      client->recursionquota),
   6235   1.9  christos 					      isc_quota_getsoft(
   6236   1.9  christos 						      client->recursionquota),
   6237   1.9  christos 					      isc_quota_getmax(
   6238   1.9  christos 						      client->recursionquota));
   6239   1.1  christos 			}
   6240   1.1  christos 			ns_client_killoldestquery(client);
   6241   1.1  christos 			result = ISC_R_SUCCESS;
   6242   1.1  christos 		} else if (result == ISC_R_QUOTA) {
   6243   1.9  christos #ifdef ISC_MUTEX_ATOMICS
   6244   1.9  christos 			isc_once_do(&last_once, last_init);
   6245   1.9  christos #endif /* ifdef ISC_MUTEX_ATOMICS */
   6246   1.1  christos 			isc_stdtime_t now;
   6247   1.1  christos 			isc_stdtime_get(&now);
   6248   1.9  christos 			if (now != atomic_load_relaxed(&last_hard)) {
   6249   1.4  christos 				ns_server_t *sctx = client->sctx;
   6250   1.9  christos 				atomic_store_relaxed(&last_hard, now);
   6251   1.9  christos 				ns_client_log(
   6252   1.9  christos 					client, NS_LOGCATEGORY_CLIENT,
   6253   1.9  christos 					NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
   6254   1.9  christos 					"no more recursive clients "
   6255   1.9  christos 					"(%u/%u/%u): %s",
   6256   1.9  christos 					isc_quota_getused(
   6257   1.9  christos 						&sctx->recursionquota),
   6258   1.9  christos 					isc_quota_getsoft(
   6259   1.9  christos 						&sctx->recursionquota),
   6260   1.9  christos 					isc_quota_getmax(&sctx->recursionquota),
   6261   1.9  christos 					isc_result_totext(result));
   6262   1.1  christos 			}
   6263   1.1  christos 			ns_client_killoldestquery(client);
   6264   1.1  christos 		}
   6265   1.9  christos 		if (result != ISC_R_SUCCESS) {
   6266   1.9  christos 			return (result);
   6267   1.1  christos 		}
   6268   1.9  christos 
   6269  1.11  christos 		dns_message_clonebuffer(client->message);
   6270   1.1  christos 		ns_client_recursing(client);
   6271  1.11  christos 	} else if ((client->attributes & NS_CLIENTATTR_RECURSING) == 0) {
   6272  1.11  christos 		client->attributes |= NS_CLIENTATTR_RECURSING;
   6273  1.11  christos 		/*
   6274  1.11  christos 		 * query_prefetch() attached first to client->recursionquota,
   6275  1.11  christos 		 * but we must check if NS_CLIENTATTR_RECURSING attribute is
   6276  1.11  christos 		 * on, if not then turn it on and increment recursing clients
   6277  1.11  christos 		 * stats counter only once. The attribute is also checked in
   6278  1.11  christos 		 * fetch_callback() to know if a matching decrement to this
   6279  1.11  christos 		 * counter should be applied.
   6280  1.11  christos 		 */
   6281  1.11  christos 		ns_stats_increment(client->sctx->nsstats,
   6282  1.11  christos 				   ns_statscounter_recursclients);
   6283   1.1  christos 	}
   6284   1.1  christos 
   6285   1.1  christos 	/*
   6286   1.1  christos 	 * Invoke the resolver.
   6287   1.1  christos 	 */
   6288   1.1  christos 	REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
   6289   1.1  christos 	REQUIRE(client->query.fetch == NULL);
   6290   1.1  christos 
   6291   1.3  christos 	rdataset = ns_client_newrdataset(client);
   6292   1.1  christos 	if (rdataset == NULL) {
   6293   1.1  christos 		return (ISC_R_NOMEMORY);
   6294   1.1  christos 	}
   6295   1.1  christos 
   6296   1.1  christos 	if (WANTDNSSEC(client)) {
   6297   1.3  christos 		sigrdataset = ns_client_newrdataset(client);
   6298   1.1  christos 		if (sigrdataset == NULL) {
   6299   1.3  christos 			ns_client_putrdataset(client, &rdataset);
   6300   1.1  christos 			return (ISC_R_NOMEMORY);
   6301   1.1  christos 		}
   6302   1.1  christos 	} else {
   6303   1.1  christos 		sigrdataset = NULL;
   6304   1.1  christos 	}
   6305   1.1  christos 
   6306  1.10  christos 	if (!client->query.timerset) {
   6307   1.1  christos 		ns_client_settimeout(client, 60);
   6308   1.1  christos 	}
   6309   1.1  christos 
   6310   1.1  christos 	if (!TCP(client)) {
   6311   1.1  christos 		peeraddr = &client->peeraddr;
   6312   1.1  christos 	}
   6313   1.1  christos 
   6314  1.11  christos 	if (client->view->staleanswerclienttimeout > 0 &&
   6315  1.11  christos 	    client->view->staleanswerclienttimeout != (uint32_t)-1 &&
   6316  1.11  christos 	    dns_view_staleanswerenabled(client->view))
   6317  1.11  christos 	{
   6318  1.11  christos 		client->query.fetchoptions |= DNS_FETCHOPT_TRYSTALE_ONTIMEOUT;
   6319  1.11  christos 	}
   6320  1.11  christos 
   6321  1.11  christos 	isc_nmhandle_attach(client->handle, &client->fetchhandle);
   6322   1.9  christos 	result = dns_resolver_createfetch(
   6323   1.9  christos 		client->view->resolver, qname, qtype, qdomain, nameservers,
   6324   1.9  christos 		NULL, peeraddr, client->message->id, client->query.fetchoptions,
   6325   1.9  christos 		0, NULL, client->task, fetch_callback, client, rdataset,
   6326   1.9  christos 		sigrdataset, &client->query.fetch);
   6327   1.1  christos 	if (result != ISC_R_SUCCESS) {
   6328  1.11  christos 		isc_nmhandle_detach(&client->fetchhandle);
   6329   1.3  christos 		ns_client_putrdataset(client, &rdataset);
   6330   1.1  christos 		if (sigrdataset != NULL) {
   6331   1.3  christos 			ns_client_putrdataset(client, &sigrdataset);
   6332   1.1  christos 		}
   6333   1.1  christos 	}
   6334   1.1  christos 
   6335   1.1  christos 	/*
   6336   1.1  christos 	 * We're now waiting for a fetch event. A client which is
   6337   1.1  christos 	 * shutting down will not be destroyed until all the events
   6338   1.1  christos 	 * have been received.
   6339   1.1  christos 	 */
   6340   1.1  christos 
   6341   1.1  christos 	return (result);
   6342   1.1  christos }
   6343   1.1  christos 
   6344   1.1  christos /*%
   6345   1.1  christos  * Restores the query context after resuming from recursion, and
   6346   1.1  christos  * continues the query processing if needed.
   6347   1.1  christos  */
   6348   1.1  christos static isc_result_t
   6349   1.1  christos query_resume(query_ctx_t *qctx) {
   6350   1.1  christos 	isc_result_t result;
   6351   1.1  christos 	dns_name_t *tname;
   6352   1.1  christos 	isc_buffer_t b;
   6353   1.1  christos #ifdef WANT_QUERYTRACE
   6354   1.6  christos 	char mbuf[4 * DNS_NAME_FORMATSIZE];
   6355   1.1  christos 	char qbuf[DNS_NAME_FORMATSIZE];
   6356   1.1  christos 	char tbuf[DNS_RDATATYPE_FORMATSIZE];
   6357   1.9  christos #endif /* ifdef WANT_QUERYTRACE */
   6358   1.9  christos 
   6359   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_resume");
   6360   1.1  christos 
   6361   1.3  christos 	CALL_HOOK(NS_QUERY_RESUME_BEGIN, qctx);
   6362   1.3  christos 
   6363   1.3  christos 	qctx->want_restart = false;
   6364   1.1  christos 
   6365   1.1  christos 	qctx->rpz_st = qctx->client->query.rpz_st;
   6366   1.1  christos 	if (qctx->rpz_st != NULL &&
   6367   1.9  christos 	    (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0) {
   6368   1.1  christos 		CCTRACE(ISC_LOG_DEBUG(3), "resume from RPZ recursion");
   6369   1.1  christos #ifdef WANT_QUERYTRACE
   6370   1.1  christos 		{
   6371   1.1  christos 			char pbuf[DNS_NAME_FORMATSIZE] = "<unset>";
   6372   1.1  christos 			char fbuf[DNS_NAME_FORMATSIZE] = "<unset>";
   6373   1.9  christos 			if (qctx->rpz_st->r_name != NULL) {
   6374   1.9  christos 				dns_name_format(qctx->rpz_st->r_name, qbuf,
   6375   1.9  christos 						sizeof(qbuf));
   6376   1.9  christos 			} else {
   6377   1.9  christos 				snprintf(qbuf, sizeof(qbuf), "<unset>");
   6378   1.9  christos 			}
   6379   1.9  christos 			if (qctx->rpz_st->p_name != NULL) {
   6380   1.9  christos 				dns_name_format(qctx->rpz_st->p_name, pbuf,
   6381   1.9  christos 						sizeof(pbuf));
   6382   1.9  christos 			}
   6383   1.9  christos 			if (qctx->rpz_st->fname != NULL) {
   6384   1.9  christos 				dns_name_format(qctx->rpz_st->fname, fbuf,
   6385   1.9  christos 						sizeof(fbuf));
   6386   1.9  christos 			}
   6387   1.1  christos 
   6388   1.1  christos 			snprintf(mbuf, sizeof(mbuf) - 1,
   6389   1.9  christos 				 "rpz rname:%s, pname:%s, qctx->fname:%s", qbuf,
   6390   1.9  christos 				 pbuf, fbuf);
   6391   1.1  christos 			CCTRACE(ISC_LOG_DEBUG(3), mbuf);
   6392   1.1  christos 		}
   6393   1.9  christos #endif /* ifdef WANT_QUERYTRACE */
   6394   1.1  christos 
   6395   1.1  christos 		qctx->is_zone = qctx->rpz_st->q.is_zone;
   6396   1.1  christos 		qctx->authoritative = qctx->rpz_st->q.authoritative;
   6397   1.1  christos 		RESTORE(qctx->zone, qctx->rpz_st->q.zone);
   6398   1.1  christos 		RESTORE(qctx->node, qctx->rpz_st->q.node);
   6399   1.1  christos 		RESTORE(qctx->db, qctx->rpz_st->q.db);
   6400   1.1  christos 		RESTORE(qctx->rdataset, qctx->rpz_st->q.rdataset);
   6401   1.1  christos 		RESTORE(qctx->sigrdataset, qctx->rpz_st->q.sigrdataset);
   6402   1.1  christos 		qctx->qtype = qctx->rpz_st->q.qtype;
   6403   1.1  christos 
   6404   1.9  christos 		if (qctx->event->node != NULL) {
   6405   1.1  christos 			dns_db_detachnode(qctx->event->db, &qctx->event->node);
   6406   1.9  christos 		}
   6407   1.1  christos 		SAVE(qctx->rpz_st->r.db, qctx->event->db);
   6408   1.1  christos 		qctx->rpz_st->r.r_type = qctx->event->qtype;
   6409   1.1  christos 		SAVE(qctx->rpz_st->r.r_rdataset, qctx->event->rdataset);
   6410   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->event->sigrdataset);
   6411   1.1  christos 	} else if (REDIRECT(qctx->client)) {
   6412   1.1  christos 		/*
   6413   1.1  christos 		 * Restore saved state.
   6414   1.1  christos 		 */
   6415   1.9  christos 		CCTRACE(ISC_LOG_DEBUG(3), "resume from redirect recursion");
   6416   1.1  christos #ifdef WANT_QUERYTRACE
   6417   1.9  christos 		dns_name_format(qctx->client->query.redirect.fname, qbuf,
   6418   1.9  christos 				sizeof(qbuf));
   6419   1.9  christos 		dns_rdatatype_format(qctx->client->query.redirect.qtype, tbuf,
   6420   1.9  christos 				     sizeof(tbuf));
   6421   1.1  christos 		snprintf(mbuf, sizeof(mbuf) - 1,
   6422   1.9  christos 			 "redirect qctx->fname:%s, qtype:%s, auth:%d", qbuf,
   6423   1.9  christos 			 tbuf, qctx->client->query.redirect.authoritative);
   6424   1.1  christos 		CCTRACE(ISC_LOG_DEBUG(3), mbuf);
   6425   1.9  christos #endif /* ifdef WANT_QUERYTRACE */
   6426   1.1  christos 		qctx->qtype = qctx->client->query.redirect.qtype;
   6427   1.1  christos 		INSIST(qctx->client->query.redirect.rdataset != NULL);
   6428   1.1  christos 		RESTORE(qctx->rdataset, qctx->client->query.redirect.rdataset);
   6429   1.1  christos 		RESTORE(qctx->sigrdataset,
   6430   1.1  christos 			qctx->client->query.redirect.sigrdataset);
   6431   1.1  christos 		RESTORE(qctx->db, qctx->client->query.redirect.db);
   6432   1.1  christos 		RESTORE(qctx->node, qctx->client->query.redirect.node);
   6433   1.1  christos 		RESTORE(qctx->zone, qctx->client->query.redirect.zone);
   6434   1.1  christos 		qctx->authoritative =
   6435   1.1  christos 			qctx->client->query.redirect.authoritative;
   6436   1.1  christos 
   6437   1.1  christos 		/*
   6438   1.1  christos 		 * Free resources used while recursing.
   6439   1.1  christos 		 */
   6440   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->event->rdataset);
   6441   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->event->sigrdataset);
   6442   1.9  christos 		if (qctx->event->node != NULL) {
   6443   1.1  christos 			dns_db_detachnode(qctx->event->db, &qctx->event->node);
   6444   1.9  christos 		}
   6445   1.9  christos 		if (qctx->event->db != NULL) {
   6446   1.1  christos 			dns_db_detach(&qctx->event->db);
   6447   1.9  christos 		}
   6448   1.1  christos 	} else {
   6449   1.9  christos 		CCTRACE(ISC_LOG_DEBUG(3), "resume from normal recursion");
   6450   1.3  christos 		qctx->authoritative = false;
   6451   1.1  christos 
   6452   1.1  christos 		qctx->qtype = qctx->event->qtype;
   6453   1.1  christos 		SAVE(qctx->db, qctx->event->db);
   6454   1.1  christos 		SAVE(qctx->node, qctx->event->node);
   6455   1.1  christos 		SAVE(qctx->rdataset, qctx->event->rdataset);
   6456   1.1  christos 		SAVE(qctx->sigrdataset, qctx->event->sigrdataset);
   6457   1.1  christos 	}
   6458   1.1  christos 	INSIST(qctx->rdataset != NULL);
   6459   1.1  christos 
   6460   1.1  christos 	if (qctx->qtype == dns_rdatatype_rrsig ||
   6461   1.9  christos 	    qctx->qtype == dns_rdatatype_sig) {
   6462   1.1  christos 		qctx->type = dns_rdatatype_any;
   6463   1.1  christos 	} else {
   6464   1.1  christos 		qctx->type = qctx->qtype;
   6465   1.1  christos 	}
   6466   1.1  christos 
   6467   1.3  christos 	CALL_HOOK(NS_QUERY_RESUME_RESTORED, qctx);
   6468   1.3  christos 
   6469   1.1  christos 	if (DNS64(qctx->client)) {
   6470   1.1  christos 		qctx->client->query.attributes &= ~NS_QUERYATTR_DNS64;
   6471   1.3  christos 		qctx->dns64 = true;
   6472   1.1  christos 	}
   6473   1.1  christos 
   6474   1.1  christos 	if (DNS64EXCLUDE(qctx->client)) {
   6475   1.1  christos 		qctx->client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE;
   6476   1.3  christos 		qctx->dns64_exclude = true;
   6477   1.1  christos 	}
   6478   1.1  christos 
   6479   1.1  christos 	if (qctx->rpz_st != NULL &&
   6480   1.9  christos 	    (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0) {
   6481   1.1  christos 		/*
   6482   1.1  christos 		 * Has response policy changed out from under us?
   6483   1.1  christos 		 */
   6484   1.9  christos 		if (qctx->rpz_st->rpz_ver != qctx->view->rpzs->rpz_ver) {
   6485   1.1  christos 			ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT,
   6486   1.9  christos 				      NS_LOGMODULE_QUERY, DNS_RPZ_INFO_LEVEL,
   6487   1.1  christos 				      "query_resume: RPZ settings "
   6488   1.1  christos 				      "out of date "
   6489   1.1  christos 				      "(rpz_ver %d, expected %d)",
   6490   1.3  christos 				      qctx->view->rpzs->rpz_ver,
   6491   1.1  christos 				      qctx->rpz_st->rpz_ver);
   6492   1.1  christos 			QUERY_ERROR(qctx, DNS_R_SERVFAIL);
   6493   1.3  christos 			return (ns_query_done(qctx));
   6494   1.1  christos 		}
   6495   1.1  christos 	}
   6496   1.1  christos 
   6497   1.1  christos 	/*
   6498   1.1  christos 	 * We'll need some resources...
   6499   1.1  christos 	 */
   6500   1.3  christos 	qctx->dbuf = ns_client_getnamebuf(qctx->client);
   6501   1.1  christos 	if (qctx->dbuf == NULL) {
   6502   1.9  christos 		CCTRACE(ISC_LOG_ERROR, "query_resume: ns_client_getnamebuf "
   6503   1.9  christos 				       "failed (1)");
   6504   1.3  christos 		QUERY_ERROR(qctx, ISC_R_NOMEMORY);
   6505   1.3  christos 		return (ns_query_done(qctx));
   6506   1.1  christos 	}
   6507   1.1  christos 
   6508   1.3  christos 	qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, &b);
   6509   1.1  christos 	if (qctx->fname == NULL) {
   6510   1.9  christos 		CCTRACE(ISC_LOG_ERROR, "query_resume: ns_client_newname failed "
   6511   1.9  christos 				       "(1)");
   6512   1.3  christos 		QUERY_ERROR(qctx, ISC_R_NOMEMORY);
   6513   1.3  christos 		return (ns_query_done(qctx));
   6514   1.1  christos 	}
   6515   1.1  christos 
   6516   1.1  christos 	if (qctx->rpz_st != NULL &&
   6517   1.1  christos 	    (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0) {
   6518   1.1  christos 		tname = qctx->rpz_st->fname;
   6519   1.1  christos 	} else if (REDIRECT(qctx->client)) {
   6520   1.1  christos 		tname = qctx->client->query.redirect.fname;
   6521   1.1  christos 	} else {
   6522   1.1  christos 		tname = dns_fixedname_name(&qctx->event->foundname);
   6523   1.1  christos 	}
   6524   1.1  christos 
   6525   1.8  christos 	dns_name_copynf(tname, qctx->fname);
   6526   1.1  christos 
   6527   1.1  christos 	if (qctx->rpz_st != NULL &&
   6528   1.1  christos 	    (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0) {
   6529   1.1  christos 		qctx->rpz_st->r.r_result = qctx->event->result;
   6530   1.1  christos 		result = qctx->rpz_st->q.result;
   6531   1.9  christos 		free_devent(qctx->client, ISC_EVENT_PTR(&qctx->event),
   6532   1.9  christos 			    &qctx->event);
   6533   1.1  christos 	} else if (REDIRECT(qctx->client)) {
   6534   1.1  christos 		result = qctx->client->query.redirect.result;
   6535   1.1  christos 	} else {
   6536   1.1  christos 		result = qctx->event->result;
   6537   1.1  christos 	}
   6538   1.1  christos 
   6539   1.3  christos 	qctx->resuming = true;
   6540   1.1  christos 
   6541   1.1  christos 	return (query_gotanswer(qctx, result));
   6542   1.3  christos 
   6543   1.9  christos cleanup:
   6544   1.3  christos 	return (result);
   6545   1.1  christos }
   6546   1.1  christos 
   6547   1.1  christos /*%
   6548   1.1  christos  * If the query is recursive, check the SERVFAIL cache to see whether
   6549   1.1  christos  * identical queries have failed recently.  If we find a match, and it was
   6550   1.1  christos  * from a query with CD=1, *or* if the current query has CD=0, then we just
   6551   1.1  christos  * return SERVFAIL again.  This prevents a validation failure from eliciting a
   6552   1.1  christos  * SERVFAIL response to a CD=1 query.
   6553   1.1  christos  */
   6554   1.1  christos isc_result_t
   6555   1.1  christos ns__query_sfcache(query_ctx_t *qctx) {
   6556   1.3  christos 	bool failcache;
   6557   1.3  christos 	uint32_t flags;
   6558   1.1  christos 
   6559   1.1  christos 	/*
   6560   1.1  christos 	 * The SERVFAIL cache doesn't apply to authoritative queries.
   6561   1.1  christos 	 */
   6562   1.1  christos 	if (!RECURSIONOK(qctx->client)) {
   6563   1.1  christos 		return (ISC_R_COMPLETE);
   6564   1.1  christos 	}
   6565   1.1  christos 
   6566   1.1  christos 	flags = 0;
   6567   1.1  christos #ifdef ENABLE_AFL
   6568   1.1  christos 	if (qctx->client->sctx->fuzztype == isc_fuzz_resolver) {
   6569   1.3  christos 		failcache = false;
   6570   1.1  christos 	} else {
   6571   1.9  christos 		failcache = dns_badcache_find(
   6572   1.9  christos 			qctx->view->failcache, qctx->client->query.qname,
   6573   1.9  christos 			qctx->qtype, &flags, &qctx->client->tnow);
   6574   1.1  christos 	}
   6575   1.9  christos #else  /* ifdef ENABLE_AFL */
   6576   1.3  christos 	failcache = dns_badcache_find(qctx->view->failcache,
   6577   1.9  christos 				      qctx->client->query.qname, qctx->qtype,
   6578   1.9  christos 				      &flags, &qctx->client->tnow);
   6579   1.9  christos #endif /* ifdef ENABLE_AFL */
   6580   1.1  christos 	if (failcache &&
   6581   1.1  christos 	    (((flags & NS_FAILCACHE_CD) != 0) ||
   6582   1.1  christos 	     ((qctx->client->message->flags & DNS_MESSAGEFLAG_CD) == 0)))
   6583   1.1  christos 	{
   6584   1.1  christos 		if (isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1))) {
   6585   1.1  christos 			char namebuf[DNS_NAME_FORMATSIZE];
   6586   1.3  christos 			char typebuf[DNS_RDATATYPE_FORMATSIZE];
   6587   1.1  christos 
   6588   1.9  christos 			dns_name_format(qctx->client->query.qname, namebuf,
   6589   1.9  christos 					sizeof(namebuf));
   6590   1.3  christos 			dns_rdatatype_format(qctx->qtype, typebuf,
   6591   1.3  christos 					     sizeof(typebuf));
   6592   1.9  christos 			ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT,
   6593   1.9  christos 				      NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(1),
   6594   1.9  christos 				      "servfail cache hit %s/%s (%s)", namebuf,
   6595   1.9  christos 				      typebuf,
   6596   1.9  christos 				      ((flags & NS_FAILCACHE_CD) != 0) ? "CD=1"
   6597   1.9  christos 								       : "CD="
   6598   1.9  christos 									 "0");
   6599   1.1  christos 		}
   6600   1.1  christos 
   6601   1.1  christos 		qctx->client->attributes |= NS_CLIENTATTR_NOSETFC;
   6602   1.1  christos 		QUERY_ERROR(qctx, DNS_R_SERVFAIL);
   6603   1.3  christos 		return (ns_query_done(qctx));
   6604   1.1  christos 	}
   6605   1.1  christos 
   6606   1.1  christos 	return (ISC_R_COMPLETE);
   6607   1.1  christos }
   6608   1.1  christos 
   6609   1.1  christos /*%
   6610   1.1  christos  * Handle response rate limiting (RRL).
   6611   1.1  christos  */
   6612   1.1  christos static isc_result_t
   6613   1.1  christos query_checkrrl(query_ctx_t *qctx, isc_result_t result) {
   6614   1.1  christos 	/*
   6615   1.1  christos 	 * Rate limit these responses to this client.
   6616   1.1  christos 	 * Do not delay counting and handling obvious referrals,
   6617   1.1  christos 	 *	since those won't come here again.
   6618   1.1  christos 	 * Delay handling delegations for which we are certain to recurse and
   6619   1.1  christos 	 *	return here (DNS_R_DELEGATION, not a child of one of our
   6620   1.1  christos 	 *	own zones, and recursion enabled)
   6621   1.1  christos 	 * Don't mess with responses rewritten by RPZ
   6622   1.1  christos 	 * Count each response at most once.
   6623   1.1  christos 	 */
   6624   1.3  christos 
   6625   1.3  christos 	/*
   6626   1.3  christos 	 * XXXMPA the rrl system tests fails sometimes and RRL_CHECKED
   6627   1.3  christos 	 * is set when we are called the second time preventing the
   6628   1.3  christos 	 * response being dropped.
   6629   1.3  christos 	 */
   6630   1.9  christos 	ns_client_log(
   6631   1.9  christos 		qctx->client, DNS_LOGCATEGORY_RRL, NS_LOGMODULE_QUERY,
   6632   1.9  christos 		ISC_LOG_DEBUG(99),
   6633   1.9  christos 		"rrl=%p, HAVECOOKIE=%u, result=%s, "
   6634   1.9  christos 		"fname=%p(%u), is_zone=%u, RECURSIONOK=%u, "
   6635   1.9  christos 		"query.rpz_st=%p(%u), RRL_CHECKED=%u\n",
   6636   1.9  christos 		qctx->client->view->rrl, HAVECOOKIE(qctx->client),
   6637   1.9  christos 		isc_result_toid(result), qctx->fname,
   6638   1.9  christos 		qctx->fname != NULL ? dns_name_isabsolute(qctx->fname) : 0,
   6639   1.9  christos 		qctx->is_zone, RECURSIONOK(qctx->client),
   6640   1.9  christos 		qctx->client->query.rpz_st,
   6641   1.9  christos 		qctx->client->query.rpz_st != NULL
   6642   1.9  christos 			? ((qctx->client->query.rpz_st->state &
   6643   1.9  christos 			    DNS_RPZ_REWRITTEN) != 0)
   6644   1.9  christos 			: 0,
   6645   1.9  christos 		(qctx->client->query.attributes & NS_QUERYATTR_RRL_CHECKED) !=
   6646   1.9  christos 			0);
   6647   1.3  christos 
   6648   1.9  christos 	if (qctx->view->rrl != NULL && !HAVECOOKIE(qctx->client) &&
   6649   1.1  christos 	    ((qctx->fname != NULL && dns_name_isabsolute(qctx->fname)) ||
   6650   1.1  christos 	     (result == ISC_R_NOTFOUND && !RECURSIONOK(qctx->client))) &&
   6651   1.9  christos 	    !(result == DNS_R_DELEGATION && !qctx->is_zone &&
   6652   1.9  christos 	      RECURSIONOK(qctx->client)) &&
   6653   1.1  christos 	    (qctx->client->query.rpz_st == NULL ||
   6654   1.1  christos 	     (qctx->client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) &&
   6655   1.1  christos 	    (qctx->client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0)
   6656   1.1  christos 	{
   6657   1.1  christos 		dns_rdataset_t nc_rdataset;
   6658   1.3  christos 		bool wouldlog;
   6659   1.1  christos 		dns_fixedname_t fixed;
   6660   1.1  christos 		const dns_name_t *constname;
   6661   1.1  christos 		char log_buf[DNS_RRL_LOG_BUF_LEN];
   6662   1.1  christos 		isc_result_t nc_result, resp_result;
   6663   1.1  christos 		dns_rrl_result_t rrl_result;
   6664   1.1  christos 
   6665   1.1  christos 		qctx->client->query.attributes |= NS_QUERYATTR_RRL_CHECKED;
   6666   1.1  christos 
   6667   1.1  christos 		wouldlog = isc_log_wouldlog(ns_lctx, DNS_RRL_LOG_DROP);
   6668   1.1  christos 		constname = qctx->fname;
   6669   1.1  christos 		if (result == DNS_R_NXDOMAIN) {
   6670   1.1  christos 			/*
   6671   1.1  christos 			 * Use the database origin name to rate limit NXDOMAIN
   6672   1.1  christos 			 */
   6673   1.9  christos 			if (qctx->db != NULL) {
   6674   1.1  christos 				constname = dns_db_origin(qctx->db);
   6675   1.9  christos 			}
   6676   1.1  christos 			resp_result = result;
   6677   1.1  christos 		} else if (result == DNS_R_NCACHENXDOMAIN &&
   6678   1.1  christos 			   qctx->rdataset != NULL &&
   6679   1.1  christos 			   dns_rdataset_isassociated(qctx->rdataset) &&
   6680   1.1  christos 			   (qctx->rdataset->attributes &
   6681   1.9  christos 			    DNS_RDATASETATTR_NEGATIVE) != 0)
   6682   1.9  christos 		{
   6683   1.1  christos 			/*
   6684   1.1  christos 			 * Try to use owner name in the negative cache SOA.
   6685   1.1  christos 			 */
   6686   1.1  christos 			dns_fixedname_init(&fixed);
   6687   1.1  christos 			dns_rdataset_init(&nc_rdataset);
   6688   1.1  christos 			for (nc_result = dns_rdataset_first(qctx->rdataset);
   6689   1.1  christos 			     nc_result == ISC_R_SUCCESS;
   6690   1.1  christos 			     nc_result = dns_rdataset_next(qctx->rdataset))
   6691   1.1  christos 			{
   6692   1.1  christos 				dns_ncache_current(qctx->rdataset,
   6693   1.1  christos 						   dns_fixedname_name(&fixed),
   6694   1.1  christos 						   &nc_rdataset);
   6695   1.1  christos 				if (nc_rdataset.type == dns_rdatatype_soa) {
   6696   1.1  christos 					dns_rdataset_disassociate(&nc_rdataset);
   6697   1.1  christos 					constname = dns_fixedname_name(&fixed);
   6698   1.1  christos 					break;
   6699   1.1  christos 				}
   6700   1.1  christos 				dns_rdataset_disassociate(&nc_rdataset);
   6701   1.1  christos 			}
   6702   1.1  christos 			resp_result = DNS_R_NXDOMAIN;
   6703   1.9  christos 		} else if (result == DNS_R_NXRRSET || result == DNS_R_EMPTYNAME)
   6704   1.9  christos 		{
   6705   1.1  christos 			resp_result = DNS_R_NXRRSET;
   6706   1.1  christos 		} else if (result == DNS_R_DELEGATION) {
   6707   1.1  christos 			resp_result = result;
   6708   1.1  christos 		} else if (result == ISC_R_NOTFOUND) {
   6709   1.1  christos 			/*
   6710   1.1  christos 			 * Handle referral to ".", including when recursion
   6711   1.1  christos 			 * is off or not requested and the hints have not
   6712   1.1  christos 			 * been loaded or we have "additional-from-cache no".
   6713   1.1  christos 			 */
   6714   1.1  christos 			constname = dns_rootname;
   6715   1.1  christos 			resp_result = DNS_R_DELEGATION;
   6716   1.1  christos 		} else {
   6717   1.1  christos 			resp_result = ISC_R_SUCCESS;
   6718   1.1  christos 		}
   6719   1.1  christos 
   6720   1.9  christos 		rrl_result = dns_rrl(
   6721   1.9  christos 			qctx->view, &qctx->client->peeraddr, TCP(qctx->client),
   6722   1.9  christos 			qctx->client->message->rdclass, qctx->qtype, constname,
   6723   1.9  christos 			resp_result, qctx->client->now, wouldlog, log_buf,
   6724   1.9  christos 			sizeof(log_buf));
   6725   1.1  christos 		if (rrl_result != DNS_RRL_RESULT_OK) {
   6726   1.1  christos 			/*
   6727   1.1  christos 			 * Log dropped or slipped responses in the query
   6728   1.1  christos 			 * category so that requests are not silently lost.
   6729   1.1  christos 			 * Starts of rate-limited bursts are logged in
   6730   1.1  christos 			 * DNS_LOGCATEGORY_RRL.
   6731   1.1  christos 			 *
   6732   1.1  christos 			 * Dropped responses are counted with dropped queries
   6733   1.1  christos 			 * in QryDropped while slipped responses are counted
   6734   1.1  christos 			 * with other truncated responses in RespTruncated.
   6735   1.1  christos 			 */
   6736   1.1  christos 			if (wouldlog) {
   6737   1.1  christos 				ns_client_log(qctx->client, DNS_LOGCATEGORY_RRL,
   6738   1.1  christos 					      NS_LOGMODULE_QUERY,
   6739   1.9  christos 					      DNS_RRL_LOG_DROP, "%s", log_buf);
   6740   1.1  christos 			}
   6741   1.1  christos 
   6742   1.3  christos 			if (!qctx->view->rrl->log_only) {
   6743   1.1  christos 				if (rrl_result == DNS_RRL_RESULT_DROP) {
   6744   1.1  christos 					/*
   6745   1.1  christos 					 * These will also be counted in
   6746   1.1  christos 					 * ns_statscounter_dropped
   6747   1.1  christos 					 */
   6748   1.1  christos 					inc_stats(qctx->client,
   6749   1.9  christos 						  ns_statscounter_ratedropped);
   6750   1.1  christos 					QUERY_ERROR(qctx, DNS_R_DROP);
   6751   1.1  christos 				} else {
   6752   1.1  christos 					/*
   6753   1.1  christos 					 * These will also be counted in
   6754   1.1  christos 					 * ns_statscounter_truncatedresp
   6755   1.1  christos 					 */
   6756   1.1  christos 					inc_stats(qctx->client,
   6757   1.9  christos 						  ns_statscounter_rateslipped);
   6758   1.1  christos 					if (WANTCOOKIE(qctx->client)) {
   6759   1.1  christos 						qctx->client->message->flags &=
   6760   1.1  christos 							~DNS_MESSAGEFLAG_AA;
   6761   1.1  christos 						qctx->client->message->flags &=
   6762   1.1  christos 							~DNS_MESSAGEFLAG_AD;
   6763   1.1  christos 						qctx->client->message->rcode =
   6764   1.9  christos 							dns_rcode_badcookie;
   6765   1.1  christos 					} else {
   6766   1.1  christos 						qctx->client->message->flags |=
   6767   1.1  christos 							DNS_MESSAGEFLAG_TC;
   6768   1.1  christos 						if (resp_result ==
   6769   1.9  christos 						    DNS_R_NXDOMAIN) {
   6770   1.9  christos 							qctx->client->message
   6771   1.9  christos 								->rcode =
   6772   1.9  christos 								dns_rcode_nxdomain;
   6773   1.1  christos 						}
   6774   1.1  christos 					}
   6775   1.1  christos 				}
   6776   1.1  christos 				return (DNS_R_DROP);
   6777   1.1  christos 			}
   6778   1.1  christos 		}
   6779   1.1  christos 	}
   6780   1.1  christos 
   6781   1.1  christos 	return (ISC_R_SUCCESS);
   6782   1.1  christos }
   6783   1.1  christos 
   6784   1.1  christos /*%
   6785   1.1  christos  * Do any RPZ rewriting that may be needed for this query.
   6786   1.1  christos  */
   6787   1.1  christos static isc_result_t
   6788   1.1  christos query_checkrpz(query_ctx_t *qctx, isc_result_t result) {
   6789   1.1  christos 	isc_result_t rresult;
   6790   1.1  christos 
   6791   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_checkrpz");
   6792   1.9  christos 
   6793   1.9  christos 	rresult = rpz_rewrite(qctx->client, qctx->qtype, result, qctx->resuming,
   6794   1.1  christos 			      qctx->rdataset, qctx->sigrdataset);
   6795   1.1  christos 	qctx->rpz_st = qctx->client->query.rpz_st;
   6796   1.1  christos 	switch (rresult) {
   6797   1.1  christos 	case ISC_R_SUCCESS:
   6798   1.1  christos 		break;
   6799   1.1  christos 	case DNS_R_DISALLOWED:
   6800   1.1  christos 		return (result);
   6801   1.1  christos 	case DNS_R_DELEGATION:
   6802   1.1  christos 		/*
   6803   1.1  christos 		 * recursing for NS names or addresses,
   6804   1.1  christos 		 * so save the main query state
   6805   1.1  christos 		 */
   6806   1.1  christos 		qctx->rpz_st->q.qtype = qctx->qtype;
   6807   1.1  christos 		qctx->rpz_st->q.is_zone = qctx->is_zone;
   6808   1.1  christos 		qctx->rpz_st->q.authoritative = qctx->authoritative;
   6809   1.1  christos 		SAVE(qctx->rpz_st->q.zone, qctx->zone);
   6810   1.1  christos 		SAVE(qctx->rpz_st->q.db, qctx->db);
   6811   1.1  christos 		SAVE(qctx->rpz_st->q.node, qctx->node);
   6812   1.1  christos 		SAVE(qctx->rpz_st->q.rdataset, qctx->rdataset);
   6813   1.1  christos 		SAVE(qctx->rpz_st->q.sigrdataset, qctx->sigrdataset);
   6814   1.8  christos 		dns_name_copynf(qctx->fname, qctx->rpz_st->fname);
   6815   1.1  christos 		qctx->rpz_st->q.result = result;
   6816   1.1  christos 		qctx->client->query.attributes |= NS_QUERYATTR_RECURSING;
   6817   1.1  christos 		return (ISC_R_COMPLETE);
   6818   1.1  christos 	default:
   6819   1.3  christos 		QUERY_ERROR(qctx, rresult);
   6820   1.3  christos 		return (ISC_R_COMPLETE);
   6821   1.1  christos 	}
   6822   1.1  christos 
   6823   1.1  christos 	if (qctx->rpz_st->m.policy != DNS_RPZ_POLICY_MISS) {
   6824   1.1  christos 		qctx->rpz_st->state |= DNS_RPZ_REWRITTEN;
   6825   1.1  christos 	}
   6826   1.1  christos 
   6827   1.1  christos 	if (qctx->rpz_st->m.policy != DNS_RPZ_POLICY_MISS &&
   6828   1.1  christos 	    qctx->rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU &&
   6829   1.1  christos 	    (qctx->rpz_st->m.policy != DNS_RPZ_POLICY_TCP_ONLY ||
   6830   1.1  christos 	     !TCP(qctx->client)) &&
   6831   1.1  christos 	    qctx->rpz_st->m.policy != DNS_RPZ_POLICY_ERROR)
   6832   1.1  christos 	{
   6833   1.1  christos 		/*
   6834   1.1  christos 		 * We got a hit and are going to answer with our
   6835   1.1  christos 		 * fiction. Ensure that we answer with the name
   6836   1.1  christos 		 * we looked up even if we were stopped short
   6837   1.1  christos 		 * in recursion or for a deferral.
   6838   1.1  christos 		 */
   6839   1.8  christos 		dns_name_copynf(qctx->client->query.qname, qctx->fname);
   6840   1.1  christos 		rpz_clean(&qctx->zone, &qctx->db, &qctx->node, NULL);
   6841   1.1  christos 		if (qctx->rpz_st->m.rdataset != NULL) {
   6842   1.3  christos 			ns_client_putrdataset(qctx->client, &qctx->rdataset);
   6843   1.1  christos 			RESTORE(qctx->rdataset, qctx->rpz_st->m.rdataset);
   6844   1.1  christos 		} else {
   6845   1.1  christos 			qctx_clean(qctx);
   6846   1.1  christos 		}
   6847   1.1  christos 		qctx->version = NULL;
   6848   1.1  christos 
   6849   1.1  christos 		RESTORE(qctx->node, qctx->rpz_st->m.node);
   6850   1.1  christos 		RESTORE(qctx->db, qctx->rpz_st->m.db);
   6851   1.1  christos 		RESTORE(qctx->version, qctx->rpz_st->m.version);
   6852   1.1  christos 		RESTORE(qctx->zone, qctx->rpz_st->m.zone);
   6853   1.1  christos 
   6854   1.1  christos 		/*
   6855   1.1  christos 		 * Add SOA record to additional section
   6856   1.1  christos 		 */
   6857   1.5  christos 		if (qctx->rpz_st->m.rpz->addsoa) {
   6858   1.5  christos 			bool override_ttl =
   6859   1.9  christos 				dns_rdataset_isassociated(qctx->rdataset);
   6860   1.5  christos 			rresult = query_addsoa(qctx, override_ttl,
   6861   1.5  christos 					       DNS_SECTION_ADDITIONAL);
   6862   1.5  christos 			if (rresult != ISC_R_SUCCESS) {
   6863   1.5  christos 				QUERY_ERROR(qctx, result);
   6864   1.5  christos 				return (ISC_R_COMPLETE);
   6865   1.5  christos 			}
   6866   1.1  christos 		}
   6867   1.1  christos 
   6868   1.1  christos 		switch (qctx->rpz_st->m.policy) {
   6869   1.1  christos 		case DNS_RPZ_POLICY_TCP_ONLY:
   6870   1.1  christos 			qctx->client->message->flags |= DNS_MESSAGEFLAG_TC;
   6871   1.1  christos 			if (result == DNS_R_NXDOMAIN ||
   6872   1.9  christos 			    result == DNS_R_NCACHENXDOMAIN) {
   6873   1.1  christos 				qctx->client->message->rcode =
   6874   1.9  christos 					dns_rcode_nxdomain;
   6875   1.9  christos 			}
   6876   1.3  christos 			rpz_log_rewrite(qctx->client, false,
   6877   1.1  christos 					qctx->rpz_st->m.policy,
   6878   1.1  christos 					qctx->rpz_st->m.type, qctx->zone,
   6879   1.1  christos 					qctx->rpz_st->p_name, NULL,
   6880   1.1  christos 					qctx->rpz_st->m.rpz->num);
   6881   1.1  christos 			return (ISC_R_COMPLETE);
   6882   1.1  christos 		case DNS_RPZ_POLICY_DROP:
   6883   1.1  christos 			QUERY_ERROR(qctx, DNS_R_DROP);
   6884   1.3  christos 			rpz_log_rewrite(qctx->client, false,
   6885   1.1  christos 					qctx->rpz_st->m.policy,
   6886   1.1  christos 					qctx->rpz_st->m.type, qctx->zone,
   6887   1.1  christos 					qctx->rpz_st->p_name, NULL,
   6888   1.1  christos 					qctx->rpz_st->m.rpz->num);
   6889   1.1  christos 			return (ISC_R_COMPLETE);
   6890   1.1  christos 		case DNS_RPZ_POLICY_NXDOMAIN:
   6891   1.1  christos 			result = DNS_R_NXDOMAIN;
   6892   1.3  christos 			qctx->nxrewrite = true;
   6893   1.3  christos 			qctx->rpz = true;
   6894   1.1  christos 			break;
   6895   1.1  christos 		case DNS_RPZ_POLICY_NODATA:
   6896   1.6  christos 			qctx->nxrewrite = true;
   6897   1.9  christos 		/* FALLTHROUGH */
   6898   1.6  christos 		case DNS_RPZ_POLICY_DNS64:
   6899   1.1  christos 			result = DNS_R_NXRRSET;
   6900   1.3  christos 			qctx->rpz = true;
   6901   1.1  christos 			break;
   6902   1.1  christos 		case DNS_RPZ_POLICY_RECORD:
   6903   1.1  christos 			result = qctx->rpz_st->m.result;
   6904   1.1  christos 			if (qctx->qtype == dns_rdatatype_any &&
   6905   1.9  christos 			    result != DNS_R_CNAME) {
   6906   1.1  christos 				/*
   6907   1.1  christos 				 * We will add all of the rdatasets of
   6908   1.1  christos 				 * the node by iterating later,
   6909   1.1  christos 				 * and set the TTL then.
   6910   1.1  christos 				 */
   6911   1.9  christos 				if (dns_rdataset_isassociated(qctx->rdataset)) {
   6912   1.9  christos 					dns_rdataset_disassociate(
   6913   1.9  christos 						qctx->rdataset);
   6914   1.9  christos 				}
   6915   1.1  christos 			} else {
   6916   1.1  christos 				/*
   6917   1.1  christos 				 * We will add this rdataset.
   6918   1.1  christos 				 */
   6919   1.1  christos 				qctx->rdataset->ttl =
   6920   1.1  christos 					ISC_MIN(qctx->rdataset->ttl,
   6921   1.1  christos 						qctx->rpz_st->m.ttl);
   6922   1.1  christos 			}
   6923   1.3  christos 			qctx->rpz = true;
   6924   1.1  christos 			break;
   6925   1.1  christos 		case DNS_RPZ_POLICY_WILDCNAME: {
   6926   1.1  christos 			dns_rdata_t rdata = DNS_RDATA_INIT;
   6927   1.1  christos 			dns_rdata_cname_t cname;
   6928   1.1  christos 			result = dns_rdataset_first(qctx->rdataset);
   6929   1.1  christos 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   6930   1.1  christos 			dns_rdataset_current(qctx->rdataset, &rdata);
   6931   1.9  christos 			result = dns_rdata_tostruct(&rdata, &cname, NULL);
   6932   1.1  christos 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   6933   1.1  christos 			dns_rdata_reset(&rdata);
   6934   1.1  christos 			result = query_rpzcname(qctx, &cname.cname);
   6935   1.9  christos 			if (result != ISC_R_SUCCESS) {
   6936   1.1  christos 				return (ISC_R_COMPLETE);
   6937   1.9  christos 			}
   6938   1.1  christos 			qctx->fname = NULL;
   6939   1.3  christos 			qctx->want_restart = true;
   6940   1.1  christos 			return (ISC_R_COMPLETE);
   6941   1.1  christos 		}
   6942   1.1  christos 		case DNS_RPZ_POLICY_CNAME:
   6943   1.1  christos 			/*
   6944   1.9  christos 			 * Add overriding CNAME from a named.conf
   6945   1.1  christos 			 * response-policy statement
   6946   1.1  christos 			 */
   6947   1.1  christos 			result = query_rpzcname(qctx,
   6948   1.1  christos 						&qctx->rpz_st->m.rpz->cname);
   6949   1.9  christos 			if (result != ISC_R_SUCCESS) {
   6950   1.1  christos 				return (ISC_R_COMPLETE);
   6951   1.9  christos 			}
   6952   1.1  christos 			qctx->fname = NULL;
   6953   1.3  christos 			qctx->want_restart = true;
   6954   1.1  christos 			return (ISC_R_COMPLETE);
   6955   1.1  christos 		default:
   6956   1.1  christos 			INSIST(0);
   6957   1.3  christos 			ISC_UNREACHABLE();
   6958   1.1  christos 		}
   6959   1.1  christos 
   6960   1.1  christos 		/*
   6961   1.1  christos 		 * Turn off DNSSEC because the results of a
   6962   1.1  christos 		 * response policy zone cannot verify.
   6963   1.1  christos 		 */
   6964   1.1  christos 		qctx->client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
   6965   1.1  christos 					      NS_CLIENTATTR_WANTAD);
   6966   1.1  christos 		qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
   6967   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
   6968   1.1  christos 		qctx->rpz_st->q.is_zone = qctx->is_zone;
   6969   1.3  christos 		qctx->is_zone = true;
   6970   1.9  christos 		rpz_log_rewrite(qctx->client, false, qctx->rpz_st->m.policy,
   6971   1.1  christos 				qctx->rpz_st->m.type, qctx->zone,
   6972   1.1  christos 				qctx->rpz_st->p_name, NULL,
   6973   1.1  christos 				qctx->rpz_st->m.rpz->num);
   6974   1.1  christos 	}
   6975   1.1  christos 
   6976   1.1  christos 	return (result);
   6977   1.1  christos }
   6978   1.1  christos 
   6979   1.1  christos /*%
   6980   1.1  christos  * Add a CNAME to a query response, including translating foo.evil.com and
   6981   1.1  christos  *	*.evil.com CNAME *.example.com
   6982   1.1  christos  * to
   6983   1.1  christos  *	foo.evil.com CNAME foo.evil.com.example.com
   6984   1.1  christos  */
   6985   1.1  christos static isc_result_t
   6986   1.1  christos query_rpzcname(query_ctx_t *qctx, dns_name_t *cname) {
   6987   1.6  christos 	ns_client_t *client;
   6988   1.1  christos 	dns_fixedname_t prefix, suffix;
   6989   1.1  christos 	unsigned int labels;
   6990   1.1  christos 	isc_result_t result;
   6991   1.1  christos 
   6992   1.6  christos 	REQUIRE(qctx != NULL && qctx->client != NULL);
   6993   1.6  christos 
   6994   1.6  christos 	client = qctx->client;
   6995   1.6  christos 
   6996   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_rpzcname");
   6997   1.1  christos 
   6998   1.1  christos 	labels = dns_name_countlabels(cname);
   6999   1.1  christos 	if (labels > 2 && dns_name_iswildcard(cname)) {
   7000   1.1  christos 		dns_fixedname_init(&prefix);
   7001   1.1  christos 		dns_name_split(client->query.qname, 1,
   7002   1.1  christos 			       dns_fixedname_name(&prefix), NULL);
   7003   1.1  christos 		dns_fixedname_init(&suffix);
   7004   1.9  christos 		dns_name_split(cname, labels - 1, NULL,
   7005   1.9  christos 			       dns_fixedname_name(&suffix));
   7006   1.1  christos 		result = dns_name_concatenate(dns_fixedname_name(&prefix),
   7007   1.1  christos 					      dns_fixedname_name(&suffix),
   7008   1.1  christos 					      qctx->fname, NULL);
   7009   1.1  christos 		if (result == DNS_R_NAMETOOLONG) {
   7010   1.1  christos 			client->message->rcode = dns_rcode_yxdomain;
   7011   1.1  christos 		} else if (result != ISC_R_SUCCESS) {
   7012   1.1  christos 			return (result);
   7013   1.1  christos 		}
   7014   1.1  christos 	} else {
   7015   1.8  christos 		dns_name_copynf(cname, qctx->fname);
   7016   1.1  christos 	}
   7017   1.1  christos 
   7018   1.3  christos 	ns_client_keepname(client, qctx->fname, qctx->dbuf);
   7019   1.1  christos 	result = query_addcname(qctx, dns_trust_authanswer,
   7020   1.1  christos 				qctx->rpz_st->m.ttl);
   7021   1.1  christos 	if (result != ISC_R_SUCCESS) {
   7022   1.1  christos 		return (result);
   7023   1.1  christos 	}
   7024   1.1  christos 
   7025   1.3  christos 	rpz_log_rewrite(client, false, qctx->rpz_st->m.policy,
   7026   1.1  christos 			qctx->rpz_st->m.type, qctx->rpz_st->m.zone,
   7027   1.1  christos 			qctx->rpz_st->p_name, qctx->fname,
   7028   1.1  christos 			qctx->rpz_st->m.rpz->num);
   7029   1.1  christos 
   7030   1.1  christos 	ns_client_qnamereplace(client, qctx->fname);
   7031   1.1  christos 
   7032   1.1  christos 	/*
   7033   1.1  christos 	 * Turn off DNSSEC because the results of a
   7034   1.1  christos 	 * response policy zone cannot verify.
   7035   1.1  christos 	 */
   7036   1.1  christos 	client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
   7037   1.1  christos 				NS_CLIENTATTR_WANTAD);
   7038   1.1  christos 
   7039   1.1  christos 	return (ISC_R_SUCCESS);
   7040   1.1  christos }
   7041   1.1  christos 
   7042   1.1  christos /*%
   7043   1.1  christos  * Check the configured trust anchors for a root zone trust anchor
   7044   1.1  christos  * with a key id that matches qctx->client->query.root_key_sentinel_keyid.
   7045   1.1  christos  *
   7046   1.3  christos  * Return true when found, otherwise return false.
   7047   1.1  christos  */
   7048   1.3  christos static bool
   7049   1.1  christos has_ta(query_ctx_t *qctx) {
   7050   1.1  christos 	dns_keytable_t *keytable = NULL;
   7051   1.1  christos 	dns_keynode_t *keynode = NULL;
   7052  1.10  christos 	dns_rdataset_t dsset;
   7053   1.9  christos 	dns_keytag_t sentinel = qctx->client->query.root_key_sentinel_keyid;
   7054   1.1  christos 	isc_result_t result;
   7055   1.1  christos 
   7056   1.3  christos 	result = dns_view_getsecroots(qctx->view, &keytable);
   7057   1.1  christos 	if (result != ISC_R_SUCCESS) {
   7058   1.3  christos 		return (false);
   7059   1.1  christos 	}
   7060   1.1  christos 
   7061   1.1  christos 	result = dns_keytable_find(keytable, dns_rootname, &keynode);
   7062   1.9  christos 	if (result != ISC_R_SUCCESS) {
   7063   1.9  christos 		if (keynode != NULL) {
   7064   1.1  christos 			dns_keytable_detachkeynode(keytable, &keynode);
   7065   1.1  christos 		}
   7066   1.9  christos 		dns_keytable_detach(&keytable);
   7067   1.9  christos 		return (false);
   7068   1.9  christos 	}
   7069   1.9  christos 
   7070  1.10  christos 	dns_rdataset_init(&dsset);
   7071  1.10  christos 	if (dns_keynode_dsset(keynode, &dsset)) {
   7072  1.10  christos 		for (result = dns_rdataset_first(&dsset);
   7073  1.10  christos 		     result == ISC_R_SUCCESS;
   7074  1.10  christos 		     result = dns_rdataset_next(&dsset))
   7075   1.9  christos 		{
   7076   1.9  christos 			dns_rdata_t rdata = DNS_RDATA_INIT;
   7077   1.9  christos 			dns_rdata_ds_t ds;
   7078   1.9  christos 
   7079   1.9  christos 			dns_rdata_reset(&rdata);
   7080  1.10  christos 			dns_rdataset_current(&dsset, &rdata);
   7081   1.9  christos 			result = dns_rdata_tostruct(&rdata, &ds, NULL);
   7082   1.9  christos 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   7083   1.9  christos 			if (ds.key_tag == sentinel) {
   7084   1.9  christos 				dns_keytable_detachkeynode(keytable, &keynode);
   7085   1.9  christos 				dns_keytable_detach(&keytable);
   7086  1.10  christos 				dns_rdataset_disassociate(&dsset);
   7087   1.9  christos 				return (true);
   7088   1.9  christos 			}
   7089   1.9  christos 		}
   7090  1.10  christos 		dns_rdataset_disassociate(&dsset);
   7091   1.9  christos 	}
   7092   1.9  christos 
   7093   1.9  christos 	if (keynode != NULL) {
   7094   1.1  christos 		dns_keytable_detachkeynode(keytable, &keynode);
   7095   1.1  christos 	}
   7096   1.9  christos 
   7097   1.1  christos 	dns_keytable_detach(&keytable);
   7098   1.1  christos 
   7099   1.3  christos 	return (false);
   7100   1.1  christos }
   7101   1.1  christos 
   7102   1.1  christos /*%
   7103   1.1  christos  * Check if a root key sentinel SERVFAIL should be returned.
   7104   1.1  christos  */
   7105   1.3  christos static bool
   7106   1.1  christos root_key_sentinel_return_servfail(query_ctx_t *qctx, isc_result_t result) {
   7107   1.1  christos 	/*
   7108   1.1  christos 	 * Are we looking at a "root-key-sentinel" query?
   7109   1.1  christos 	 */
   7110   1.1  christos 	if (!qctx->client->query.root_key_sentinel_is_ta &&
   7111   1.1  christos 	    !qctx->client->query.root_key_sentinel_not_ta)
   7112   1.1  christos 	{
   7113   1.3  christos 		return (false);
   7114   1.1  christos 	}
   7115   1.1  christos 
   7116   1.1  christos 	/*
   7117   1.1  christos 	 * We only care about the query if 'result' indicates we have a cached
   7118   1.1  christos 	 * answer.
   7119   1.1  christos 	 */
   7120   1.1  christos 	switch (result) {
   7121   1.1  christos 	case ISC_R_SUCCESS:
   7122   1.1  christos 	case DNS_R_CNAME:
   7123   1.1  christos 	case DNS_R_DNAME:
   7124   1.1  christos 	case DNS_R_NCACHENXDOMAIN:
   7125   1.1  christos 	case DNS_R_NCACHENXRRSET:
   7126   1.1  christos 		break;
   7127   1.1  christos 	default:
   7128   1.3  christos 		return (false);
   7129   1.1  christos 	}
   7130   1.1  christos 
   7131   1.1  christos 	/*
   7132   1.1  christos 	 * Do we meet the specified conditions to return SERVFAIL?
   7133   1.1  christos 	 */
   7134   1.9  christos 	if (!qctx->is_zone && qctx->rdataset->trust == dns_trust_secure &&
   7135   1.1  christos 	    ((qctx->client->query.root_key_sentinel_is_ta && !has_ta(qctx)) ||
   7136   1.1  christos 	     (qctx->client->query.root_key_sentinel_not_ta && has_ta(qctx))))
   7137   1.1  christos 	{
   7138   1.3  christos 		return (true);
   7139   1.1  christos 	}
   7140   1.1  christos 
   7141   1.1  christos 	/*
   7142   1.1  christos 	 * As special processing may only be triggered by the original QNAME,
   7143   1.1  christos 	 * disable it after following a CNAME/DNAME.
   7144   1.1  christos 	 */
   7145   1.3  christos 	qctx->client->query.root_key_sentinel_is_ta = false;
   7146   1.3  christos 	qctx->client->query.root_key_sentinel_not_ta = false;
   7147   1.1  christos 
   7148   1.3  christos 	return (false);
   7149   1.1  christos }
   7150   1.1  christos 
   7151   1.1  christos /*%
   7152   1.3  christos  * If serving stale answers is allowed, set up 'qctx' to look for one and
   7153   1.3  christos  * return true; otherwise, return false.
   7154   1.3  christos  */
   7155   1.3  christos static bool
   7156   1.3  christos query_usestale(query_ctx_t *qctx) {
   7157   1.3  christos 	qctx_clean(qctx);
   7158   1.3  christos 	qctx_freedata(qctx);
   7159   1.3  christos 
   7160  1.11  christos 	if (dns_view_staleanswerenabled(qctx->client->view)) {
   7161  1.11  christos 		dns_db_attach(qctx->client->view->cachedb, &qctx->db);
   7162   1.3  christos 		qctx->client->query.dboptions |= DNS_DBFIND_STALEOK;
   7163   1.3  christos 		if (qctx->client->query.fetch != NULL) {
   7164   1.3  christos 			dns_resolver_destroyfetch(&qctx->client->query.fetch);
   7165   1.3  christos 		}
   7166  1.11  christos 
   7167  1.11  christos 		return (true);
   7168   1.3  christos 	}
   7169   1.3  christos 
   7170  1.11  christos 	return (false);
   7171   1.3  christos }
   7172   1.3  christos 
   7173   1.3  christos /*%
   7174   1.3  christos  * Continue after doing a database lookup or returning from
   7175   1.3  christos  * recursion, and call out to the next function depending on the
   7176   1.3  christos  * result from the search.
   7177   1.1  christos  */
   7178   1.1  christos static isc_result_t
   7179   1.3  christos query_gotanswer(query_ctx_t *qctx, isc_result_t res) {
   7180   1.3  christos 	isc_result_t result = res;
   7181   1.1  christos 	char errmsg[256];
   7182   1.1  christos 
   7183   1.1  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_gotanswer");
   7184   1.1  christos 
   7185   1.3  christos 	CALL_HOOK(NS_QUERY_GOT_ANSWER_BEGIN, qctx);
   7186   1.3  christos 
   7187   1.1  christos 	if (query_checkrrl(qctx, result) != ISC_R_SUCCESS) {
   7188   1.3  christos 		return (ns_query_done(qctx));
   7189   1.1  christos 	}
   7190   1.1  christos 
   7191   1.1  christos 	if (!RECURSING(qctx->client) &&
   7192   1.1  christos 	    !dns_name_equal(qctx->client->query.qname, dns_rootname))
   7193   1.1  christos 	{
   7194   1.1  christos 		result = query_checkrpz(qctx, result);
   7195   1.3  christos 		if (result == ISC_R_COMPLETE) {
   7196   1.3  christos 			return (ns_query_done(qctx));
   7197   1.3  christos 		}
   7198   1.1  christos 	}
   7199   1.1  christos 
   7200   1.1  christos 	/*
   7201   1.1  christos 	 * If required, handle special "root-key-sentinel-is-ta-<keyid>" and
   7202   1.1  christos 	 * "root-key-sentinel-not-ta-<keyid>" labels by returning SERVFAIL.
   7203   1.1  christos 	 */
   7204   1.1  christos 	if (root_key_sentinel_return_servfail(qctx, result)) {
   7205   1.1  christos 		/*
   7206   1.1  christos 		 * Don't record this response in the SERVFAIL cache.
   7207   1.1  christos 		 */
   7208   1.1  christos 		qctx->client->attributes |= NS_CLIENTATTR_NOSETFC;
   7209   1.1  christos 		QUERY_ERROR(qctx, DNS_R_SERVFAIL);
   7210   1.3  christos 		return (ns_query_done(qctx));
   7211   1.1  christos 	}
   7212   1.1  christos 
   7213   1.1  christos 	switch (result) {
   7214   1.1  christos 	case ISC_R_SUCCESS:
   7215   1.1  christos 		return (query_prepresponse(qctx));
   7216   1.1  christos 
   7217   1.1  christos 	case DNS_R_GLUE:
   7218   1.1  christos 	case DNS_R_ZONECUT:
   7219   1.1  christos 		INSIST(qctx->is_zone);
   7220   1.3  christos 		qctx->authoritative = false;
   7221   1.1  christos 		return (query_prepresponse(qctx));
   7222   1.1  christos 
   7223   1.1  christos 	case ISC_R_NOTFOUND:
   7224   1.1  christos 		return (query_notfound(qctx));
   7225   1.1  christos 
   7226   1.1  christos 	case DNS_R_DELEGATION:
   7227   1.1  christos 		return (query_delegation(qctx));
   7228   1.1  christos 
   7229   1.1  christos 	case DNS_R_EMPTYNAME:
   7230   1.1  christos 		return (query_nodata(qctx, DNS_R_EMPTYNAME));
   7231   1.1  christos 	case DNS_R_NXRRSET:
   7232   1.1  christos 		return (query_nodata(qctx, DNS_R_NXRRSET));
   7233   1.1  christos 
   7234   1.1  christos 	case DNS_R_EMPTYWILD:
   7235   1.3  christos 		return (query_nxdomain(qctx, true));
   7236   1.1  christos 
   7237   1.1  christos 	case DNS_R_NXDOMAIN:
   7238   1.3  christos 		return (query_nxdomain(qctx, false));
   7239   1.1  christos 
   7240   1.1  christos 	case DNS_R_COVERINGNSEC:
   7241   1.1  christos 		return (query_coveringnsec(qctx));
   7242   1.1  christos 
   7243   1.1  christos 	case DNS_R_NCACHENXDOMAIN:
   7244   1.1  christos 		result = query_redirect(qctx);
   7245   1.9  christos 		if (result != ISC_R_COMPLETE) {
   7246   1.1  christos 			return (result);
   7247   1.9  christos 		}
   7248   1.1  christos 		return (query_ncache(qctx, DNS_R_NCACHENXDOMAIN));
   7249   1.1  christos 
   7250   1.1  christos 	case DNS_R_NCACHENXRRSET:
   7251   1.1  christos 		return (query_ncache(qctx, DNS_R_NCACHENXRRSET));
   7252   1.1  christos 
   7253   1.1  christos 	case DNS_R_CNAME:
   7254   1.1  christos 		return (query_cname(qctx));
   7255   1.1  christos 
   7256   1.1  christos 	case DNS_R_DNAME:
   7257   1.1  christos 		return (query_dname(qctx));
   7258   1.1  christos 
   7259   1.1  christos 	default:
   7260   1.1  christos 		/*
   7261   1.1  christos 		 * Something has gone wrong.
   7262   1.1  christos 		 */
   7263   1.1  christos 		snprintf(errmsg, sizeof(errmsg) - 1,
   7264   1.1  christos 			 "query_gotanswer: unexpected error: %s",
   7265   1.1  christos 			 isc_result_totext(result));
   7266   1.1  christos 		CCTRACE(ISC_LOG_ERROR, errmsg);
   7267   1.3  christos 		if (qctx->resuming && query_usestale(qctx)) {
   7268   1.3  christos 			/*
   7269   1.3  christos 			 * If serve-stale is enabled, query_usestale() already
   7270   1.3  christos 			 * set up 'qctx' for looking up a stale response.
   7271   1.3  christos 			 */
   7272   1.3  christos 			return (query_lookup(qctx));
   7273   1.1  christos 		}
   7274   1.6  christos 
   7275   1.6  christos 		/*
   7276   1.6  christos 		 * Regardless of the triggering result, we definitely
   7277   1.6  christos 		 * want to return SERVFAIL from here.
   7278   1.6  christos 		 */
   7279   1.6  christos 		qctx->client->rcode_override = dns_rcode_servfail;
   7280   1.6  christos 
   7281   1.3  christos 		QUERY_ERROR(qctx, result);
   7282   1.3  christos 		return (ns_query_done(qctx));
   7283   1.1  christos 	}
   7284   1.3  christos 
   7285   1.9  christos cleanup:
   7286   1.3  christos 	return (result);
   7287   1.1  christos }
   7288   1.1  christos 
   7289   1.1  christos static void
   7290   1.1  christos query_addnoqnameproof(query_ctx_t *qctx) {
   7291   1.1  christos 	ns_client_t *client = qctx->client;
   7292   1.1  christos 	isc_buffer_t *dbuf, b;
   7293   1.1  christos 	dns_name_t *fname = NULL;
   7294   1.1  christos 	dns_rdataset_t *neg = NULL, *negsig = NULL;
   7295   1.1  christos 	isc_result_t result = ISC_R_NOMEMORY;
   7296   1.1  christos 
   7297   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addnoqnameproof");
   7298   1.1  christos 
   7299   1.1  christos 	if (qctx->noqname == NULL) {
   7300   1.1  christos 		return;
   7301   1.1  christos 	}
   7302   1.1  christos 
   7303   1.3  christos 	dbuf = ns_client_getnamebuf(client);
   7304   1.1  christos 	if (dbuf == NULL) {
   7305   1.1  christos 		goto cleanup;
   7306   1.1  christos 	}
   7307   1.1  christos 
   7308   1.3  christos 	fname = ns_client_newname(client, dbuf, &b);
   7309   1.3  christos 	neg = ns_client_newrdataset(client);
   7310   1.3  christos 	negsig = ns_client_newrdataset(client);
   7311   1.1  christos 	if (fname == NULL || neg == NULL || negsig == NULL) {
   7312   1.1  christos 		goto cleanup;
   7313   1.1  christos 	}
   7314   1.1  christos 
   7315   1.1  christos 	result = dns_rdataset_getnoqname(qctx->noqname, fname, neg, negsig);
   7316   1.1  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   7317   1.1  christos 
   7318   1.3  christos 	query_addrrset(qctx, &fname, &neg, &negsig, dbuf,
   7319   1.1  christos 		       DNS_SECTION_AUTHORITY);
   7320   1.1  christos 
   7321   1.1  christos 	if ((qctx->noqname->attributes & DNS_RDATASETATTR_CLOSEST) == 0) {
   7322   1.1  christos 		goto cleanup;
   7323   1.1  christos 	}
   7324   1.1  christos 
   7325   1.1  christos 	if (fname == NULL) {
   7326   1.3  christos 		dbuf = ns_client_getnamebuf(client);
   7327   1.9  christos 		if (dbuf == NULL) {
   7328   1.1  christos 			goto cleanup;
   7329   1.9  christos 		}
   7330   1.3  christos 		fname = ns_client_newname(client, dbuf, &b);
   7331   1.1  christos 	}
   7332   1.1  christos 
   7333   1.1  christos 	if (neg == NULL) {
   7334   1.3  christos 		neg = ns_client_newrdataset(client);
   7335   1.1  christos 	} else if (dns_rdataset_isassociated(neg)) {
   7336   1.1  christos 		dns_rdataset_disassociate(neg);
   7337   1.1  christos 	}
   7338   1.1  christos 
   7339   1.1  christos 	if (negsig == NULL) {
   7340   1.3  christos 		negsig = ns_client_newrdataset(client);
   7341   1.1  christos 	} else if (dns_rdataset_isassociated(negsig)) {
   7342   1.1  christos 		dns_rdataset_disassociate(negsig);
   7343   1.1  christos 	}
   7344   1.1  christos 
   7345   1.9  christos 	if (fname == NULL || neg == NULL || negsig == NULL) {
   7346   1.1  christos 		goto cleanup;
   7347   1.9  christos 	}
   7348   1.1  christos 	result = dns_rdataset_getclosest(qctx->noqname, fname, neg, negsig);
   7349   1.1  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   7350   1.1  christos 
   7351   1.3  christos 	query_addrrset(qctx, &fname, &neg, &negsig, dbuf,
   7352   1.1  christos 		       DNS_SECTION_AUTHORITY);
   7353   1.1  christos 
   7354   1.9  christos cleanup:
   7355   1.1  christos 	if (neg != NULL) {
   7356   1.3  christos 		ns_client_putrdataset(client, &neg);
   7357   1.1  christos 	}
   7358   1.1  christos 	if (negsig != NULL) {
   7359   1.3  christos 		ns_client_putrdataset(client, &negsig);
   7360   1.1  christos 	}
   7361   1.1  christos 	if (fname != NULL) {
   7362   1.3  christos 		ns_client_releasename(client, &fname);
   7363   1.1  christos 	}
   7364   1.1  christos }
   7365   1.1  christos 
   7366   1.1  christos /*%
   7367   1.1  christos  * Build the response for a query for type ANY.
   7368   1.1  christos  */
   7369   1.1  christos static isc_result_t
   7370   1.1  christos query_respond_any(query_ctx_t *qctx) {
   7371   1.5  christos 	bool found = false, hidden = false;
   7372   1.1  christos 	dns_rdatasetiter_t *rdsiter = NULL;
   7373   1.1  christos 	isc_result_t result;
   7374   1.9  christos 	dns_rdatatype_t onetype = 0; /* type to use for minimal-any */
   7375   1.3  christos 	isc_buffer_t b;
   7376   1.1  christos 
   7377   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_respond_any");
   7378   1.9  christos 
   7379   1.3  christos 	CALL_HOOK(NS_QUERY_RESPOND_ANY_BEGIN, qctx);
   7380   1.1  christos 
   7381   1.9  christos 	result = dns_db_allrdatasets(qctx->db, qctx->node, qctx->version, 0,
   7382   1.9  christos 				     &rdsiter);
   7383   1.1  christos 	if (result != ISC_R_SUCCESS) {
   7384   1.9  christos 		CCTRACE(ISC_LOG_ERROR, "query_respond_any: allrdatasets "
   7385   1.9  christos 				       "failed");
   7386   1.3  christos 		QUERY_ERROR(qctx, result);
   7387   1.3  christos 		return (ns_query_done(qctx));
   7388   1.1  christos 	}
   7389   1.1  christos 
   7390   1.1  christos 	/*
   7391   1.1  christos 	 * Calling query_addrrset() with a non-NULL dbuf is going
   7392   1.1  christos 	 * to either keep or release the name.  We don't want it to
   7393   1.1  christos 	 * release fname, since we may have to call query_addrrset()
   7394   1.3  christos 	 * more than once.  That means we have to call ns_client_keepname()
   7395   1.1  christos 	 * now, and pass a NULL dbuf to query_addrrset().
   7396   1.1  christos 	 *
   7397   1.1  christos 	 * If we do a query_addrrset() below, we must set qctx->fname to
   7398   1.1  christos 	 * NULL before leaving this block, otherwise we might try to
   7399   1.1  christos 	 * cleanup qctx->fname even though we're using it!
   7400   1.1  christos 	 */
   7401   1.3  christos 	ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
   7402   1.3  christos 	qctx->tname = qctx->fname;
   7403   1.1  christos 
   7404   1.1  christos 	result = dns_rdatasetiter_first(rdsiter);
   7405   1.1  christos 	while (result == ISC_R_SUCCESS) {
   7406   1.1  christos 		dns_rdatasetiter_current(rdsiter, qctx->rdataset);
   7407   1.1  christos 
   7408   1.1  christos 		/*
   7409   1.1  christos 		 * We found an NS RRset; no need to add one later.
   7410   1.1  christos 		 */
   7411   1.1  christos 		if (qctx->qtype == dns_rdatatype_any &&
   7412   1.1  christos 		    qctx->rdataset->type == dns_rdatatype_ns)
   7413   1.1  christos 		{
   7414   1.3  christos 			qctx->answer_has_ns = true;
   7415   1.1  christos 		}
   7416   1.1  christos 
   7417   1.1  christos 		/*
   7418   1.1  christos 		 * Note: if we're in this function, then qctx->type
   7419   1.1  christos 		 * is guaranteed to be ANY, but qctx->qtype (i.e. the
   7420   1.1  christos 		 * original type requested) might have been RRSIG or
   7421   1.1  christos 		 * SIG; we need to check for that.
   7422   1.1  christos 		 */
   7423   1.1  christos 		if (qctx->is_zone && qctx->qtype == dns_rdatatype_any &&
   7424   1.1  christos 		    !dns_db_issecure(qctx->db) &&
   7425   1.1  christos 		    dns_rdatatype_isdnssec(qctx->rdataset->type))
   7426   1.1  christos 		{
   7427   1.1  christos 			/*
   7428   1.5  christos 			 * The zone may be transitioning from insecure
   7429   1.5  christos 			 * to secure. Hide DNSSEC records from ANY queries.
   7430   1.1  christos 			 */
   7431   1.1  christos 			dns_rdataset_disassociate(qctx->rdataset);
   7432   1.5  christos 			hidden = true;
   7433   1.9  christos 		} else if (qctx->view->minimal_any && !TCP(qctx->client) &&
   7434   1.9  christos 			   !WANTDNSSEC(qctx->client) &&
   7435   1.1  christos 			   qctx->qtype == dns_rdatatype_any &&
   7436   1.1  christos 			   (qctx->rdataset->type == dns_rdatatype_sig ||
   7437   1.1  christos 			    qctx->rdataset->type == dns_rdatatype_rrsig))
   7438   1.1  christos 		{
   7439   1.1  christos 			CCTRACE(ISC_LOG_DEBUG(5), "query_respond_any: "
   7440   1.9  christos 						  "minimal-any skip signature");
   7441   1.1  christos 			dns_rdataset_disassociate(qctx->rdataset);
   7442   1.9  christos 		} else if (qctx->view->minimal_any && !TCP(qctx->client) &&
   7443   1.9  christos 			   onetype != 0 && qctx->rdataset->type != onetype &&
   7444   1.1  christos 			   qctx->rdataset->covers != onetype)
   7445   1.1  christos 		{
   7446   1.1  christos 			CCTRACE(ISC_LOG_DEBUG(5), "query_respond_any: "
   7447   1.9  christos 						  "minimal-any skip rdataset");
   7448   1.1  christos 			dns_rdataset_disassociate(qctx->rdataset);
   7449   1.1  christos 		} else if ((qctx->qtype == dns_rdatatype_any ||
   7450   1.1  christos 			    qctx->rdataset->type == qctx->qtype) &&
   7451   1.1  christos 			   qctx->rdataset->type != 0)
   7452   1.1  christos 		{
   7453   1.9  christos 			if (NOQNAME(qctx->rdataset) && WANTDNSSEC(qctx->client))
   7454   1.1  christos 			{
   7455   1.1  christos 				qctx->noqname = qctx->rdataset;
   7456   1.1  christos 			} else {
   7457   1.1  christos 				qctx->noqname = NULL;
   7458   1.1  christos 			}
   7459   1.1  christos 
   7460   1.1  christos 			qctx->rpz_st = qctx->client->query.rpz_st;
   7461   1.9  christos 			if (qctx->rpz_st != NULL) {
   7462   1.1  christos 				qctx->rdataset->ttl =
   7463   1.1  christos 					ISC_MIN(qctx->rdataset->ttl,
   7464   1.1  christos 						qctx->rpz_st->m.ttl);
   7465   1.9  christos 			}
   7466   1.1  christos 
   7467   1.1  christos 			if (!qctx->is_zone && RECURSIONOK(qctx->client)) {
   7468   1.1  christos 				dns_name_t *name;
   7469   1.9  christos 				name = (qctx->fname != NULL) ? qctx->fname
   7470   1.9  christos 							     : qctx->tname;
   7471   1.1  christos 				query_prefetch(qctx->client, name,
   7472   1.1  christos 					       qctx->rdataset);
   7473   1.1  christos 			}
   7474   1.1  christos 
   7475   1.1  christos 			/*
   7476   1.1  christos 			 * Remember the first RRtype we find so we
   7477   1.1  christos 			 * can skip others with minimal-any.
   7478   1.1  christos 			 */
   7479   1.1  christos 			if (qctx->rdataset->type == dns_rdatatype_sig ||
   7480   1.1  christos 			    qctx->rdataset->type == dns_rdatatype_rrsig)
   7481   1.3  christos 			{
   7482   1.1  christos 				onetype = qctx->rdataset->covers;
   7483   1.3  christos 			} else {
   7484   1.1  christos 				onetype = qctx->rdataset->type;
   7485   1.3  christos 			}
   7486   1.1  christos 
   7487   1.3  christos 			query_addrrset(qctx,
   7488   1.9  christos 				       (qctx->fname != NULL) ? &qctx->fname
   7489   1.9  christos 							     : &qctx->tname,
   7490   1.9  christos 				       &qctx->rdataset, NULL, NULL,
   7491   1.9  christos 				       DNS_SECTION_ANSWER);
   7492   1.1  christos 
   7493   1.1  christos 			query_addnoqnameproof(qctx);
   7494   1.1  christos 
   7495   1.3  christos 			found = true;
   7496   1.3  christos 			INSIST(qctx->tname != NULL);
   7497   1.1  christos 
   7498   1.1  christos 			/*
   7499   1.1  christos 			 * rdataset is non-NULL only in certain
   7500   1.1  christos 			 * pathological cases involving DNAMEs.
   7501   1.1  christos 			 */
   7502   1.3  christos 			if (qctx->rdataset != NULL) {
   7503   1.3  christos 				ns_client_putrdataset(qctx->client,
   7504   1.3  christos 						      &qctx->rdataset);
   7505   1.3  christos 			}
   7506   1.1  christos 
   7507   1.3  christos 			qctx->rdataset = ns_client_newrdataset(qctx->client);
   7508   1.5  christos 			if (qctx->rdataset == NULL) {
   7509   1.1  christos 				break;
   7510   1.5  christos 			}
   7511   1.1  christos 		} else {
   7512   1.1  christos 			/*
   7513   1.1  christos 			 * We're not interested in this rdataset.
   7514   1.1  christos 			 */
   7515   1.1  christos 			dns_rdataset_disassociate(qctx->rdataset);
   7516   1.1  christos 		}
   7517   1.1  christos 
   7518   1.1  christos 		result = dns_rdatasetiter_next(rdsiter);
   7519   1.1  christos 	}
   7520   1.1  christos 
   7521   1.3  christos 	dns_rdatasetiter_destroy(&rdsiter);
   7522   1.3  christos 
   7523   1.3  christos 	if (result != ISC_R_NOMORE) {
   7524   1.9  christos 		CCTRACE(ISC_LOG_ERROR, "query_respond_any: rdataset iterator "
   7525   1.9  christos 				       "failed");
   7526   1.3  christos 		QUERY_ERROR(qctx, DNS_R_SERVFAIL);
   7527   1.3  christos 		return (ns_query_done(qctx));
   7528   1.3  christos 	}
   7529   1.3  christos 
   7530   1.3  christos 	if (found) {
   7531   1.5  christos 		/*
   7532   1.5  christos 		 * Call hook if any answers were found.
   7533   1.5  christos 		 * Do this before releasing qctx->fname, in case
   7534   1.5  christos 		 * the hook function needs it.
   7535   1.5  christos 		 */
   7536   1.3  christos 		CALL_HOOK(NS_QUERY_RESPOND_ANY_FOUND, qctx);
   7537   1.3  christos 	}
   7538   1.3  christos 
   7539   1.3  christos 	if (qctx->fname != NULL) {
   7540   1.5  christos 		dns_message_puttempname(qctx->client->message, &qctx->fname);
   7541   1.1  christos 	}
   7542   1.1  christos 
   7543   1.5  christos 	if (found) {
   7544   1.5  christos 		/*
   7545   1.5  christos 		 * At least one matching rdataset was found
   7546   1.5  christos 		 */
   7547   1.1  christos 		query_addauth(qctx);
   7548   1.5  christos 	} else if (qctx->qtype == dns_rdatatype_rrsig ||
   7549   1.5  christos 		   qctx->qtype == dns_rdatatype_sig)
   7550   1.5  christos 	{
   7551   1.5  christos 		/*
   7552   1.5  christos 		 * No matching rdatasets were found, but we got
   7553   1.5  christos 		 * here on a search for RRSIG/SIG, so that's okay.
   7554   1.5  christos 		 */
   7555   1.5  christos 		if (!qctx->is_zone) {
   7556   1.5  christos 			qctx->authoritative = false;
   7557   1.5  christos 			qctx->client->attributes &= ~NS_CLIENTATTR_RA;
   7558   1.5  christos 			query_addauth(qctx);
   7559   1.5  christos 			return (ns_query_done(qctx));
   7560   1.5  christos 		}
   7561   1.5  christos 
   7562   1.5  christos 		if (qctx->qtype == dns_rdatatype_rrsig &&
   7563   1.9  christos 		    dns_db_issecure(qctx->db)) {
   7564   1.5  christos 			char namebuf[DNS_NAME_FORMATSIZE];
   7565   1.9  christos 			dns_name_format(qctx->client->query.qname, namebuf,
   7566   1.9  christos 					sizeof(namebuf));
   7567   1.5  christos 			ns_client_log(qctx->client, DNS_LOGCATEGORY_DNSSEC,
   7568   1.5  christos 				      NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
   7569   1.5  christos 				      "missing signature for %s", namebuf);
   7570   1.5  christos 		}
   7571   1.1  christos 
   7572   1.5  christos 		qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, &b);
   7573   1.5  christos 		return (query_sign_nodata(qctx));
   7574   1.5  christos 	} else if (!hidden) {
   7575   1.5  christos 		/*
   7576   1.5  christos 		 * No matching rdatasets were found and nothing was
   7577   1.5  christos 		 * deliberately hidden: something must have gone wrong.
   7578   1.5  christos 		 */
   7579   1.5  christos 		QUERY_ERROR(qctx, DNS_R_SERVFAIL);
   7580   1.3  christos 	}
   7581   1.3  christos 
   7582   1.5  christos 	return (ns_query_done(qctx));
   7583   1.3  christos 
   7584   1.9  christos cleanup:
   7585   1.3  christos 	return (result);
   7586   1.1  christos }
   7587   1.1  christos 
   7588   1.1  christos /*
   7589   1.3  christos  * Set the expire time, if requested, when answering from a slave, mirror, or
   7590   1.3  christos  * master zone.
   7591   1.1  christos  */
   7592   1.1  christos static void
   7593   1.1  christos query_getexpire(query_ctx_t *qctx) {
   7594   1.1  christos 	dns_zone_t *raw = NULL, *mayberaw;
   7595   1.1  christos 
   7596   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_getexpire");
   7597   1.9  christos 
   7598   1.1  christos 	if (qctx->zone == NULL || !qctx->is_zone ||
   7599   1.1  christos 	    qctx->qtype != dns_rdatatype_soa ||
   7600   1.1  christos 	    qctx->client->query.restarts != 0 ||
   7601   1.1  christos 	    (qctx->client->attributes & NS_CLIENTATTR_WANTEXPIRE) == 0)
   7602   1.1  christos 	{
   7603   1.1  christos 		return;
   7604   1.1  christos 	}
   7605   1.1  christos 
   7606   1.1  christos 	dns_zone_getraw(qctx->zone, &raw);
   7607   1.1  christos 	mayberaw = (raw != NULL) ? raw : qctx->zone;
   7608   1.1  christos 
   7609   1.3  christos 	if (dns_zone_gettype(mayberaw) == dns_zone_slave ||
   7610   1.3  christos 	    dns_zone_gettype(mayberaw) == dns_zone_mirror)
   7611   1.3  christos 	{
   7612   1.1  christos 		isc_time_t expiretime;
   7613   1.3  christos 		uint32_t secs;
   7614   1.1  christos 		dns_zone_getexpiretime(qctx->zone, &expiretime);
   7615   1.1  christos 		secs = isc_time_seconds(&expiretime);
   7616   1.9  christos 		if (secs >= qctx->client->now && qctx->result == ISC_R_SUCCESS)
   7617   1.1  christos 		{
   7618   1.9  christos 			qctx->client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
   7619   1.1  christos 			qctx->client->expire = secs - qctx->client->now;
   7620   1.1  christos 		}
   7621   1.1  christos 	} else if (dns_zone_gettype(mayberaw) == dns_zone_master) {
   7622   1.1  christos 		isc_result_t result;
   7623   1.1  christos 		dns_rdata_t rdata = DNS_RDATA_INIT;
   7624   1.1  christos 		dns_rdata_soa_t soa;
   7625   1.1  christos 
   7626   1.1  christos 		result = dns_rdataset_first(qctx->rdataset);
   7627   1.1  christos 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   7628   1.1  christos 
   7629   1.1  christos 		dns_rdataset_current(qctx->rdataset, &rdata);
   7630   1.1  christos 		result = dns_rdata_tostruct(&rdata, &soa, NULL);
   7631   1.1  christos 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   7632   1.1  christos 
   7633   1.1  christos 		qctx->client->expire = soa.expire;
   7634   1.1  christos 		qctx->client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
   7635   1.1  christos 	}
   7636   1.1  christos 
   7637   1.1  christos 	if (raw != NULL) {
   7638   1.1  christos 		dns_zone_detach(&raw);
   7639   1.1  christos 	}
   7640   1.1  christos }
   7641   1.1  christos 
   7642   1.3  christos /*%
   7643   1.3  christos  * Fill the ANSWER section of a positive response.
   7644   1.1  christos  */
   7645   1.1  christos static isc_result_t
   7646   1.3  christos query_addanswer(query_ctx_t *qctx) {
   7647   1.3  christos 	dns_rdataset_t **sigrdatasetp = NULL;
   7648   1.1  christos 	isc_result_t result;
   7649   1.1  christos 
   7650   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_addanswer");
   7651   1.9  christos 
   7652   1.3  christos 	CALL_HOOK(NS_QUERY_ADDANSWER_BEGIN, qctx);
   7653   1.1  christos 
   7654   1.3  christos 	if (qctx->dns64) {
   7655   1.3  christos 		result = query_dns64(qctx);
   7656   1.3  christos 		qctx->noqname = NULL;
   7657   1.3  christos 		dns_rdataset_disassociate(qctx->rdataset);
   7658   1.3  christos 		dns_message_puttemprdataset(qctx->client->message,
   7659   1.3  christos 					    &qctx->rdataset);
   7660   1.3  christos 		if (result == ISC_R_NOMORE) {
   7661   1.3  christos #ifndef dns64_bis_return_excluded_addresses
   7662   1.3  christos 			if (qctx->dns64_exclude) {
   7663   1.9  christos 				if (!qctx->is_zone) {
   7664   1.3  christos 					return (ns_query_done(qctx));
   7665   1.9  christos 				}
   7666   1.3  christos 				/*
   7667   1.3  christos 				 * Add a fake SOA record.
   7668   1.3  christos 				 */
   7669   1.3  christos 				(void)query_addsoa(qctx, 600,
   7670   1.3  christos 						   DNS_SECTION_AUTHORITY);
   7671   1.3  christos 				return (ns_query_done(qctx));
   7672   1.3  christos 			}
   7673   1.9  christos #endif /* ifndef dns64_bis_return_excluded_addresses */
   7674   1.3  christos 			if (qctx->is_zone) {
   7675   1.3  christos 				return (query_nodata(qctx, DNS_R_NXDOMAIN));
   7676   1.3  christos 			} else {
   7677   1.3  christos 				return (query_ncache(qctx, DNS_R_NXDOMAIN));
   7678   1.1  christos 			}
   7679   1.3  christos 		} else if (result != ISC_R_SUCCESS) {
   7680   1.3  christos 			qctx->result = result;
   7681   1.3  christos 			return (ns_query_done(qctx));
   7682   1.3  christos 		}
   7683   1.3  christos 	} else if (qctx->client->query.dns64_aaaaok != NULL) {
   7684   1.3  christos 		query_filter64(qctx);
   7685   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->rdataset);
   7686   1.3  christos 	} else {
   7687  1.11  christos 		if (!qctx->is_zone && RECURSIONOK(qctx->client) &&
   7688  1.11  christos 		    !QUERY_STALEONLY(&qctx->client->query))
   7689  1.11  christos 		{
   7690   1.3  christos 			query_prefetch(qctx->client, qctx->fname,
   7691   1.3  christos 				       qctx->rdataset);
   7692   1.1  christos 		}
   7693   1.3  christos 		if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) {
   7694   1.3  christos 			sigrdatasetp = &qctx->sigrdataset;
   7695   1.3  christos 		}
   7696   1.9  christos 		query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
   7697   1.9  christos 			       sigrdatasetp, qctx->dbuf, DNS_SECTION_ANSWER);
   7698   1.1  christos 	}
   7699   1.1  christos 
   7700   1.1  christos 	return (ISC_R_COMPLETE);
   7701   1.3  christos 
   7702   1.9  christos cleanup:
   7703   1.3  christos 	return (result);
   7704   1.1  christos }
   7705   1.1  christos 
   7706   1.1  christos /*%
   7707   1.9  christos  * Build a response for a "normal" query, for a type other than ANY,
   7708   1.1  christos  * for which we have an answer (either positive or negative).
   7709   1.1  christos  */
   7710   1.1  christos static isc_result_t
   7711   1.1  christos query_respond(query_ctx_t *qctx) {
   7712   1.1  christos 	isc_result_t result;
   7713   1.1  christos 
   7714   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_respond");
   7715   1.9  christos 
   7716   1.1  christos 	/*
   7717   1.1  christos 	 * Check to see if the AAAA RRset has non-excluded addresses
   7718   1.1  christos 	 * in it.  If not look for a A RRset.
   7719   1.1  christos 	 */
   7720   1.1  christos 	INSIST(qctx->client->query.dns64_aaaaok == NULL);
   7721   1.1  christos 
   7722   1.1  christos 	if (qctx->qtype == dns_rdatatype_aaaa && !qctx->dns64_exclude &&
   7723   1.3  christos 	    !ISC_LIST_EMPTY(qctx->view->dns64) &&
   7724   1.1  christos 	    qctx->client->message->rdclass == dns_rdataclass_in &&
   7725   1.1  christos 	    !dns64_aaaaok(qctx->client, qctx->rdataset, qctx->sigrdataset))
   7726   1.1  christos 	{
   7727   1.1  christos 		/*
   7728   1.1  christos 		 * Look to see if there are A records for this name.
   7729   1.1  christos 		 */
   7730   1.1  christos 		qctx->client->query.dns64_ttl = qctx->rdataset->ttl;
   7731   1.1  christos 		SAVE(qctx->client->query.dns64_aaaa, qctx->rdataset);
   7732   1.1  christos 		SAVE(qctx->client->query.dns64_sigaaaa, qctx->sigrdataset);
   7733   1.3  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   7734   1.1  christos 		dns_db_detachnode(qctx->db, &qctx->node);
   7735   1.1  christos 		qctx->type = qctx->qtype = dns_rdatatype_a;
   7736   1.3  christos 		qctx->dns64_exclude = qctx->dns64 = true;
   7737   1.1  christos 
   7738   1.1  christos 		return (query_lookup(qctx));
   7739   1.1  christos 	}
   7740   1.1  christos 
   7741   1.3  christos 	/*
   7742   1.3  christos 	 * XXX: This hook is meant to be at the top of this function,
   7743   1.3  christos 	 * but is postponed until after DNS64 in order to avoid an
   7744   1.3  christos 	 * assertion if the hook causes recursion. (When DNS64 also
   7745   1.3  christos 	 * becomes a plugin, it will be necessary to find some
   7746   1.3  christos 	 * other way to prevent that assertion, since the order in
   7747   1.3  christos 	 * which plugins are configured can't be enforced.)
   7748   1.3  christos 	 */
   7749   1.3  christos 	CALL_HOOK(NS_QUERY_RESPOND_BEGIN, qctx);
   7750   1.1  christos 
   7751   1.1  christos 	if (NOQNAME(qctx->rdataset) && WANTDNSSEC(qctx->client)) {
   7752   1.1  christos 		qctx->noqname = qctx->rdataset;
   7753   1.1  christos 	} else {
   7754   1.1  christos 		qctx->noqname = NULL;
   7755   1.1  christos 	}
   7756   1.1  christos 
   7757   1.1  christos 	/*
   7758   1.1  christos 	 * Special case NS handling
   7759   1.1  christos 	 */
   7760   1.1  christos 	if (qctx->is_zone && qctx->qtype == dns_rdatatype_ns) {
   7761   1.1  christos 		/*
   7762   1.1  christos 		 * We've already got an NS, no need to add one in
   7763   1.1  christos 		 * the authority section
   7764   1.1  christos 		 */
   7765   1.1  christos 		if (dns_name_equal(qctx->client->query.qname,
   7766   1.9  christos 				   dns_db_origin(qctx->db))) {
   7767   1.3  christos 			qctx->answer_has_ns = true;
   7768   1.1  christos 		}
   7769   1.1  christos 
   7770   1.1  christos 		/*
   7771   1.6  christos 		 * Always add glue for root priming queries, regardless
   7772   1.6  christos 		 * of "minimal-responses" setting.
   7773   1.1  christos 		 */
   7774   1.1  christos 		if (dns_name_equal(qctx->client->query.qname, dns_rootname)) {
   7775   1.1  christos 			qctx->client->query.attributes &=
   7776   1.1  christos 				~NS_QUERYATTR_NOADDITIONAL;
   7777   1.6  christos 			dns_db_attach(qctx->db, &qctx->client->query.gluedb);
   7778   1.1  christos 		}
   7779   1.1  christos 	}
   7780   1.1  christos 
   7781   1.1  christos 	/*
   7782   1.1  christos 	 * Set expire time
   7783   1.1  christos 	 */
   7784   1.1  christos 	query_getexpire(qctx);
   7785   1.1  christos 
   7786   1.3  christos 	result = query_addanswer(qctx);
   7787   1.3  christos 	if (result != ISC_R_COMPLETE) {
   7788   1.3  christos 		return (result);
   7789   1.1  christos 	}
   7790   1.1  christos 
   7791   1.1  christos 	query_addnoqnameproof(qctx);
   7792   1.1  christos 
   7793   1.1  christos 	/*
   7794   1.1  christos 	 * We shouldn't ever fail to add 'rdataset'
   7795   1.1  christos 	 * because it's already in the answer.
   7796   1.1  christos 	 */
   7797  1.11  christos 	INSIST(qctx->rdataset == NULL || QUERY_ANSWERED(&qctx->client->query));
   7798   1.1  christos 
   7799   1.1  christos 	query_addauth(qctx);
   7800   1.1  christos 
   7801   1.3  christos 	return (ns_query_done(qctx));
   7802   1.3  christos 
   7803   1.9  christos cleanup:
   7804   1.3  christos 	return (result);
   7805   1.1  christos }
   7806   1.1  christos 
   7807   1.1  christos static isc_result_t
   7808   1.1  christos query_dns64(query_ctx_t *qctx) {
   7809   1.1  christos 	ns_client_t *client = qctx->client;
   7810   1.9  christos 	dns_aclenv_t *env =
   7811   1.9  christos 		ns_interfacemgr_getaclenv(client->manager->interface->mgr);
   7812   1.1  christos 	dns_name_t *name, *mname;
   7813   1.1  christos 	dns_rdata_t *dns64_rdata;
   7814   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7815   1.1  christos 	dns_rdatalist_t *dns64_rdatalist;
   7816   1.1  christos 	dns_rdataset_t *dns64_rdataset;
   7817   1.1  christos 	dns_rdataset_t *mrdataset;
   7818   1.1  christos 	isc_buffer_t *buffer;
   7819   1.1  christos 	isc_region_t r;
   7820   1.1  christos 	isc_result_t result;
   7821   1.1  christos 	dns_view_t *view = client->view;
   7822   1.1  christos 	isc_netaddr_t netaddr;
   7823   1.1  christos 	dns_dns64_t *dns64;
   7824   1.1  christos 	unsigned int flags = 0;
   7825   1.1  christos 	const dns_section_t section = DNS_SECTION_ANSWER;
   7826   1.1  christos 
   7827   1.1  christos 	/*%
   7828   1.1  christos 	 * To the current response for 'qctx->client', add the answer RRset
   7829   1.1  christos 	 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
   7830   1.1  christos 	 * owner name '*namep', to the answer section, unless they are
   7831   1.1  christos 	 * already there.  Also add any pertinent additional data.
   7832   1.1  christos 	 *
   7833   1.1  christos 	 * If 'qctx->dbuf' is not NULL, then 'qctx->fname' is the name
   7834   1.1  christos 	 * whose data is stored 'qctx->dbuf'.  In this case,
   7835   1.1  christos 	 * query_addrrset() guarantees that when it returns the name
   7836   1.1  christos 	 * will either have been kept or released.
   7837   1.1  christos 	 */
   7838   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_dns64");
   7839   1.1  christos 
   7840   1.1  christos 	qctx->qtype = qctx->type = dns_rdatatype_aaaa;
   7841   1.1  christos 
   7842   1.1  christos 	name = qctx->fname;
   7843   1.1  christos 	mname = NULL;
   7844   1.1  christos 	mrdataset = NULL;
   7845   1.1  christos 	buffer = NULL;
   7846   1.1  christos 	dns64_rdata = NULL;
   7847   1.1  christos 	dns64_rdataset = NULL;
   7848   1.1  christos 	dns64_rdatalist = NULL;
   7849   1.9  christos 	result = dns_message_findname(
   7850   1.9  christos 		client->message, section, name, dns_rdatatype_aaaa,
   7851   1.9  christos 		qctx->rdataset->covers, &mname, &mrdataset);
   7852   1.1  christos 	if (result == ISC_R_SUCCESS) {
   7853   1.1  christos 		/*
   7854   1.1  christos 		 * We've already got an RRset of the given name and type.
   7855   1.1  christos 		 * There's nothing else to do;
   7856   1.1  christos 		 */
   7857   1.9  christos 		CTRACE(ISC_LOG_DEBUG(3), "query_dns64: dns_message_findname "
   7858   1.9  christos 					 "succeeded: done");
   7859   1.3  christos 		if (qctx->dbuf != NULL) {
   7860   1.3  christos 			ns_client_releasename(client, &qctx->fname);
   7861   1.3  christos 		}
   7862   1.1  christos 		return (ISC_R_SUCCESS);
   7863   1.1  christos 	} else if (result == DNS_R_NXDOMAIN) {
   7864   1.1  christos 		/*
   7865   1.1  christos 		 * The name doesn't exist.
   7866   1.1  christos 		 */
   7867   1.3  christos 		if (qctx->dbuf != NULL) {
   7868   1.3  christos 			ns_client_keepname(client, name, qctx->dbuf);
   7869   1.3  christos 		}
   7870   1.1  christos 		dns_message_addname(client->message, name, section);
   7871   1.1  christos 		qctx->fname = NULL;
   7872   1.1  christos 		mname = name;
   7873   1.1  christos 	} else {
   7874   1.1  christos 		RUNTIME_CHECK(result == DNS_R_NXRRSET);
   7875   1.3  christos 		if (qctx->dbuf != NULL) {
   7876   1.3  christos 			ns_client_releasename(client, &qctx->fname);
   7877   1.3  christos 		}
   7878   1.1  christos 	}
   7879   1.1  christos 
   7880   1.1  christos 	if (qctx->rdataset->trust != dns_trust_secure) {
   7881   1.1  christos 		client->query.attributes &= ~NS_QUERYATTR_SECURE;
   7882   1.1  christos 	}
   7883   1.1  christos 
   7884   1.1  christos 	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
   7885   1.1  christos 
   7886   1.9  christos 	isc_buffer_allocate(client->mctx, &buffer,
   7887   1.9  christos 			    view->dns64cnt * 16 *
   7888   1.9  christos 				    dns_rdataset_count(qctx->rdataset));
   7889   1.9  christos 	result = dns_message_gettemprdataset(client->message, &dns64_rdataset);
   7890   1.9  christos 	if (result != ISC_R_SUCCESS) {
   7891   1.1  christos 		goto cleanup;
   7892   1.9  christos 	}
   7893   1.1  christos 	result = dns_message_gettemprdatalist(client->message,
   7894   1.1  christos 					      &dns64_rdatalist);
   7895   1.9  christos 	if (result != ISC_R_SUCCESS) {
   7896   1.1  christos 		goto cleanup;
   7897   1.9  christos 	}
   7898   1.1  christos 
   7899   1.1  christos 	dns_rdatalist_init(dns64_rdatalist);
   7900   1.1  christos 	dns64_rdatalist->rdclass = dns_rdataclass_in;
   7901   1.1  christos 	dns64_rdatalist->type = dns_rdatatype_aaaa;
   7902   1.9  christos 	if (client->query.dns64_ttl != UINT32_MAX) {
   7903   1.1  christos 		dns64_rdatalist->ttl = ISC_MIN(qctx->rdataset->ttl,
   7904   1.1  christos 					       client->query.dns64_ttl);
   7905   1.9  christos 	} else {
   7906   1.1  christos 		dns64_rdatalist->ttl = ISC_MIN(qctx->rdataset->ttl, 600);
   7907   1.9  christos 	}
   7908   1.1  christos 
   7909   1.9  christos 	if (RECURSIONOK(client)) {
   7910   1.1  christos 		flags |= DNS_DNS64_RECURSIVE;
   7911   1.9  christos 	}
   7912   1.1  christos 
   7913   1.1  christos 	/*
   7914   1.1  christos 	 * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC
   7915   1.1  christos 	 * as this provides a easy way to see if the answer was signed.
   7916   1.1  christos 	 */
   7917   1.1  christos 	if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL &&
   7918   1.1  christos 	    dns_rdataset_isassociated(qctx->sigrdataset))
   7919   1.9  christos 	{
   7920   1.1  christos 		flags |= DNS_DNS64_DNSSEC;
   7921   1.9  christos 	}
   7922   1.1  christos 
   7923   1.1  christos 	for (result = dns_rdataset_first(qctx->rdataset);
   7924   1.1  christos 	     result == ISC_R_SUCCESS;
   7925   1.9  christos 	     result = dns_rdataset_next(qctx->rdataset))
   7926   1.9  christos 	{
   7927   1.9  christos 		for (dns64 = ISC_LIST_HEAD(client->view->dns64); dns64 != NULL;
   7928   1.9  christos 		     dns64 = dns_dns64_next(dns64))
   7929   1.9  christos 		{
   7930   1.1  christos 			dns_rdataset_current(qctx->rdataset, &rdata);
   7931   1.1  christos 			isc_buffer_availableregion(buffer, &r);
   7932   1.1  christos 			INSIST(r.length >= 16);
   7933   1.1  christos 			result = dns_dns64_aaaafroma(dns64, &netaddr,
   7934   1.1  christos 						     client->signer, env, flags,
   7935   1.1  christos 						     rdata.data, r.base);
   7936   1.1  christos 			if (result != ISC_R_SUCCESS) {
   7937   1.1  christos 				dns_rdata_reset(&rdata);
   7938   1.1  christos 				continue;
   7939   1.1  christos 			}
   7940   1.1  christos 			isc_buffer_add(buffer, 16);
   7941   1.1  christos 			isc_buffer_remainingregion(buffer, &r);
   7942   1.1  christos 			isc_buffer_forward(buffer, 16);
   7943   1.1  christos 			result = dns_message_gettemprdata(client->message,
   7944   1.1  christos 							  &dns64_rdata);
   7945   1.9  christos 			if (result != ISC_R_SUCCESS) {
   7946   1.1  christos 				goto cleanup;
   7947   1.9  christos 			}
   7948   1.1  christos 			dns_rdata_init(dns64_rdata);
   7949   1.1  christos 			dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in,
   7950   1.1  christos 					     dns_rdatatype_aaaa, &r);
   7951   1.1  christos 			ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata,
   7952   1.1  christos 					link);
   7953   1.1  christos 			dns64_rdata = NULL;
   7954   1.1  christos 			dns_rdata_reset(&rdata);
   7955   1.1  christos 		}
   7956   1.1  christos 	}
   7957   1.9  christos 	if (result != ISC_R_NOMORE) {
   7958   1.1  christos 		goto cleanup;
   7959   1.9  christos 	}
   7960   1.1  christos 
   7961   1.9  christos 	if (ISC_LIST_EMPTY(dns64_rdatalist->rdata)) {
   7962   1.1  christos 		goto cleanup;
   7963   1.9  christos 	}
   7964   1.1  christos 
   7965   1.1  christos 	result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset);
   7966   1.9  christos 	if (result != ISC_R_SUCCESS) {
   7967   1.1  christos 		goto cleanup;
   7968   1.9  christos 	}
   7969   1.1  christos 	dns_rdataset_setownercase(dns64_rdataset, mname);
   7970   1.1  christos 	client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
   7971   1.1  christos 	dns64_rdataset->trust = qctx->rdataset->trust;
   7972   1.3  christos 
   7973   1.3  christos 	query_addtoname(mname, dns64_rdataset);
   7974   1.3  christos 	query_setorder(qctx, mname, dns64_rdataset);
   7975   1.3  christos 
   7976   1.1  christos 	dns64_rdataset = NULL;
   7977   1.1  christos 	dns64_rdatalist = NULL;
   7978   1.1  christos 	dns_message_takebuffer(client->message, &buffer);
   7979   1.1  christos 	inc_stats(client, ns_statscounter_dns64);
   7980   1.1  christos 	result = ISC_R_SUCCESS;
   7981   1.1  christos 
   7982   1.9  christos cleanup:
   7983   1.9  christos 	if (buffer != NULL) {
   7984   1.1  christos 		isc_buffer_free(&buffer);
   7985   1.9  christos 	}
   7986   1.1  christos 
   7987   1.9  christos 	if (dns64_rdata != NULL) {
   7988   1.1  christos 		dns_message_puttemprdata(client->message, &dns64_rdata);
   7989   1.9  christos 	}
   7990   1.1  christos 
   7991   1.9  christos 	if (dns64_rdataset != NULL) {
   7992   1.1  christos 		dns_message_puttemprdataset(client->message, &dns64_rdataset);
   7993   1.9  christos 	}
   7994   1.1  christos 
   7995   1.1  christos 	if (dns64_rdatalist != NULL) {
   7996   1.1  christos 		for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata);
   7997   1.1  christos 		     dns64_rdata != NULL;
   7998   1.1  christos 		     dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata))
   7999   1.1  christos 		{
   8000   1.9  christos 			ISC_LIST_UNLINK(dns64_rdatalist->rdata, dns64_rdata,
   8001   1.9  christos 					link);
   8002   1.1  christos 			dns_message_puttemprdata(client->message, &dns64_rdata);
   8003   1.1  christos 		}
   8004   1.1  christos 		dns_message_puttemprdatalist(client->message, &dns64_rdatalist);
   8005   1.1  christos 	}
   8006   1.1  christos 
   8007   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_dns64: done");
   8008   1.1  christos 	return (result);
   8009   1.1  christos }
   8010   1.1  christos 
   8011   1.1  christos static void
   8012   1.1  christos query_filter64(query_ctx_t *qctx) {
   8013   1.1  christos 	ns_client_t *client = qctx->client;
   8014   1.1  christos 	dns_name_t *name, *mname;
   8015   1.1  christos 	dns_rdata_t *myrdata;
   8016   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   8017   1.1  christos 	dns_rdatalist_t *myrdatalist;
   8018   1.1  christos 	dns_rdataset_t *myrdataset;
   8019   1.1  christos 	isc_buffer_t *buffer;
   8020   1.1  christos 	isc_region_t r;
   8021   1.1  christos 	isc_result_t result;
   8022   1.1  christos 	unsigned int i;
   8023   1.1  christos 	const dns_section_t section = DNS_SECTION_ANSWER;
   8024   1.1  christos 
   8025   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_filter64");
   8026   1.1  christos 
   8027   1.1  christos 	INSIST(client->query.dns64_aaaaok != NULL);
   8028   1.1  christos 	INSIST(client->query.dns64_aaaaoklen ==
   8029   1.1  christos 	       dns_rdataset_count(qctx->rdataset));
   8030   1.1  christos 
   8031   1.1  christos 	name = qctx->fname;
   8032   1.1  christos 	mname = NULL;
   8033   1.1  christos 	buffer = NULL;
   8034   1.1  christos 	myrdata = NULL;
   8035   1.1  christos 	myrdataset = NULL;
   8036   1.1  christos 	myrdatalist = NULL;
   8037   1.9  christos 	result = dns_message_findname(
   8038   1.9  christos 		client->message, section, name, dns_rdatatype_aaaa,
   8039   1.9  christos 		qctx->rdataset->covers, &mname, &myrdataset);
   8040   1.1  christos 	if (result == ISC_R_SUCCESS) {
   8041   1.1  christos 		/*
   8042   1.1  christos 		 * We've already got an RRset of the given name and type.
   8043   1.1  christos 		 * There's nothing else to do;
   8044   1.1  christos 		 */
   8045   1.9  christos 		CTRACE(ISC_LOG_DEBUG(3), "query_filter64: dns_message_findname "
   8046   1.9  christos 					 "succeeded: done");
   8047   1.3  christos 		if (qctx->dbuf != NULL) {
   8048   1.3  christos 			ns_client_releasename(client, &qctx->fname);
   8049   1.3  christos 		}
   8050   1.1  christos 		return;
   8051   1.1  christos 	} else if (result == DNS_R_NXDOMAIN) {
   8052   1.1  christos 		mname = name;
   8053   1.1  christos 		qctx->fname = NULL;
   8054   1.1  christos 	} else {
   8055   1.1  christos 		RUNTIME_CHECK(result == DNS_R_NXRRSET);
   8056   1.3  christos 		if (qctx->dbuf != NULL) {
   8057   1.3  christos 			ns_client_releasename(client, &qctx->fname);
   8058   1.3  christos 		}
   8059   1.1  christos 		qctx->dbuf = NULL;
   8060   1.1  christos 	}
   8061   1.1  christos 
   8062   1.1  christos 	if (qctx->rdataset->trust != dns_trust_secure) {
   8063   1.1  christos 		client->query.attributes &= ~NS_QUERYATTR_SECURE;
   8064   1.1  christos 	}
   8065   1.1  christos 
   8066   1.9  christos 	isc_buffer_allocate(client->mctx, &buffer,
   8067   1.9  christos 			    16 * dns_rdataset_count(qctx->rdataset));
   8068   1.1  christos 	result = dns_message_gettemprdataset(client->message, &myrdataset);
   8069   1.9  christos 	if (result != ISC_R_SUCCESS) {
   8070   1.1  christos 		goto cleanup;
   8071   1.9  christos 	}
   8072   1.1  christos 	result = dns_message_gettemprdatalist(client->message, &myrdatalist);
   8073   1.9  christos 	if (result != ISC_R_SUCCESS) {
   8074   1.1  christos 		goto cleanup;
   8075   1.9  christos 	}
   8076   1.1  christos 
   8077   1.1  christos 	dns_rdatalist_init(myrdatalist);
   8078   1.1  christos 	myrdatalist->rdclass = dns_rdataclass_in;
   8079   1.1  christos 	myrdatalist->type = dns_rdatatype_aaaa;
   8080   1.1  christos 	myrdatalist->ttl = qctx->rdataset->ttl;
   8081   1.1  christos 
   8082   1.1  christos 	i = 0;
   8083   1.1  christos 	for (result = dns_rdataset_first(qctx->rdataset);
   8084   1.1  christos 	     result == ISC_R_SUCCESS;
   8085   1.3  christos 	     result = dns_rdataset_next(qctx->rdataset))
   8086   1.3  christos 	{
   8087   1.9  christos 		if (!client->query.dns64_aaaaok[i++]) {
   8088   1.1  christos 			continue;
   8089   1.9  christos 		}
   8090   1.1  christos 		dns_rdataset_current(qctx->rdataset, &rdata);
   8091   1.1  christos 		INSIST(rdata.length == 16);
   8092   1.1  christos 		isc_buffer_putmem(buffer, rdata.data, rdata.length);
   8093   1.1  christos 		isc_buffer_remainingregion(buffer, &r);
   8094   1.1  christos 		isc_buffer_forward(buffer, rdata.length);
   8095   1.1  christos 		result = dns_message_gettemprdata(client->message, &myrdata);
   8096   1.9  christos 		if (result != ISC_R_SUCCESS) {
   8097   1.1  christos 			goto cleanup;
   8098   1.9  christos 		}
   8099   1.1  christos 		dns_rdata_init(myrdata);
   8100   1.1  christos 		dns_rdata_fromregion(myrdata, dns_rdataclass_in,
   8101   1.1  christos 				     dns_rdatatype_aaaa, &r);
   8102   1.1  christos 		ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link);
   8103   1.1  christos 		myrdata = NULL;
   8104   1.1  christos 		dns_rdata_reset(&rdata);
   8105   1.1  christos 	}
   8106   1.9  christos 	if (result != ISC_R_NOMORE) {
   8107   1.1  christos 		goto cleanup;
   8108   1.9  christos 	}
   8109   1.1  christos 
   8110   1.1  christos 	result = dns_rdatalist_tordataset(myrdatalist, myrdataset);
   8111   1.9  christos 	if (result != ISC_R_SUCCESS) {
   8112   1.1  christos 		goto cleanup;
   8113   1.9  christos 	}
   8114   1.1  christos 	dns_rdataset_setownercase(myrdataset, name);
   8115   1.1  christos 	client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
   8116   1.1  christos 	if (mname == name) {
   8117   1.3  christos 		if (qctx->dbuf != NULL) {
   8118   1.3  christos 			ns_client_keepname(client, name, qctx->dbuf);
   8119   1.3  christos 		}
   8120   1.9  christos 		dns_message_addname(client->message, name, section);
   8121   1.1  christos 		qctx->dbuf = NULL;
   8122   1.1  christos 	}
   8123   1.1  christos 	myrdataset->trust = qctx->rdataset->trust;
   8124   1.3  christos 
   8125   1.3  christos 	query_addtoname(mname, myrdataset);
   8126   1.3  christos 	query_setorder(qctx, mname, myrdataset);
   8127   1.3  christos 
   8128   1.1  christos 	myrdataset = NULL;
   8129   1.1  christos 	myrdatalist = NULL;
   8130   1.1  christos 	dns_message_takebuffer(client->message, &buffer);
   8131   1.1  christos 
   8132   1.9  christos cleanup:
   8133   1.9  christos 	if (buffer != NULL) {
   8134   1.1  christos 		isc_buffer_free(&buffer);
   8135   1.9  christos 	}
   8136   1.1  christos 
   8137   1.9  christos 	if (myrdata != NULL) {
   8138   1.1  christos 		dns_message_puttemprdata(client->message, &myrdata);
   8139   1.9  christos 	}
   8140   1.1  christos 
   8141   1.9  christos 	if (myrdataset != NULL) {
   8142   1.1  christos 		dns_message_puttemprdataset(client->message, &myrdataset);
   8143   1.9  christos 	}
   8144   1.1  christos 
   8145   1.1  christos 	if (myrdatalist != NULL) {
   8146   1.1  christos 		for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata);
   8147   1.1  christos 		     myrdata != NULL;
   8148   1.1  christos 		     myrdata = ISC_LIST_HEAD(myrdatalist->rdata))
   8149   1.1  christos 		{
   8150   1.1  christos 			ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link);
   8151   1.1  christos 			dns_message_puttemprdata(client->message, &myrdata);
   8152   1.1  christos 		}
   8153   1.1  christos 		dns_message_puttemprdatalist(client->message, &myrdatalist);
   8154   1.1  christos 	}
   8155   1.3  christos 	if (qctx->dbuf != NULL) {
   8156   1.3  christos 		ns_client_releasename(client, &name);
   8157   1.3  christos 	}
   8158   1.1  christos 
   8159   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_filter64: done");
   8160   1.1  christos }
   8161   1.1  christos 
   8162   1.1  christos /*%
   8163   1.1  christos  * Handle the case of a name not being found in a database lookup.
   8164   1.1  christos  * Called from query_gotanswer(). Passes off processing to
   8165   1.1  christos  * query_delegation() for a root referral if appropriate.
   8166   1.1  christos  */
   8167   1.1  christos static isc_result_t
   8168   1.1  christos query_notfound(query_ctx_t *qctx) {
   8169   1.1  christos 	isc_result_t result;
   8170   1.1  christos 
   8171   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_notfound");
   8172   1.9  christos 
   8173   1.3  christos 	CALL_HOOK(NS_QUERY_NOTFOUND_BEGIN, qctx);
   8174   1.3  christos 
   8175   1.1  christos 	INSIST(!qctx->is_zone);
   8176   1.1  christos 
   8177   1.9  christos 	if (qctx->db != NULL) {
   8178   1.1  christos 		dns_db_detach(&qctx->db);
   8179   1.9  christos 	}
   8180   1.1  christos 
   8181   1.1  christos 	/*
   8182   1.1  christos 	 * If the cache doesn't even have the root NS,
   8183   1.1  christos 	 * try to get that from the hints DB.
   8184   1.1  christos 	 */
   8185   1.3  christos 	if (qctx->view->hints != NULL) {
   8186   1.1  christos 		dns_clientinfomethods_t cm;
   8187   1.1  christos 		dns_clientinfo_t ci;
   8188   1.1  christos 
   8189   1.1  christos 		dns_clientinfomethods_init(&cm, ns_client_sourceip);
   8190   1.1  christos 		dns_clientinfo_init(&ci, qctx->client, NULL);
   8191   1.1  christos 
   8192   1.3  christos 		dns_db_attach(qctx->view->hints, &qctx->db);
   8193   1.9  christos 		result = dns_db_findext(qctx->db, dns_rootname, NULL,
   8194   1.9  christos 					dns_rdatatype_ns, 0, qctx->client->now,
   8195   1.9  christos 					&qctx->node, qctx->fname, &cm, &ci,
   8196   1.1  christos 					qctx->rdataset, qctx->sigrdataset);
   8197   1.1  christos 	} else {
   8198   1.1  christos 		/* We have no hints. */
   8199   1.1  christos 		result = ISC_R_FAILURE;
   8200   1.1  christos 	}
   8201   1.1  christos 	if (result != ISC_R_SUCCESS) {
   8202   1.1  christos 		/*
   8203   1.1  christos 		 * Nonsensical root hints may require cleanup.
   8204   1.1  christos 		 */
   8205   1.1  christos 		qctx_clean(qctx);
   8206   1.1  christos 
   8207   1.1  christos 		/*
   8208   1.1  christos 		 * We don't have any root server hints, but
   8209   1.1  christos 		 * we may have working forwarders, so try to
   8210   1.1  christos 		 * recurse anyway.
   8211   1.1  christos 		 */
   8212   1.1  christos 		if (RECURSIONOK(qctx->client)) {
   8213   1.1  christos 			INSIST(!REDIRECT(qctx->client));
   8214   1.3  christos 			result = ns_query_recurse(qctx->client, qctx->qtype,
   8215   1.3  christos 						  qctx->client->query.qname,
   8216   1.3  christos 						  NULL, NULL, qctx->resuming);
   8217   1.1  christos 			if (result == ISC_R_SUCCESS) {
   8218   1.3  christos 				CALL_HOOK(NS_QUERY_NOTFOUND_RECURSE, qctx);
   8219   1.1  christos 				qctx->client->query.attributes |=
   8220   1.9  christos 					NS_QUERYATTR_RECURSING;
   8221   1.3  christos 
   8222   1.3  christos 				if (qctx->dns64) {
   8223   1.1  christos 					qctx->client->query.attributes |=
   8224   1.1  christos 						NS_QUERYATTR_DNS64;
   8225   1.3  christos 				}
   8226   1.3  christos 				if (qctx->dns64_exclude) {
   8227   1.1  christos 					qctx->client->query.attributes |=
   8228   1.1  christos 						NS_QUERYATTR_DNS64EXCLUDE;
   8229   1.3  christos 				}
   8230   1.3  christos 			} else {
   8231   1.3  christos 				QUERY_ERROR(qctx, result);
   8232   1.3  christos 			}
   8233   1.3  christos 			return (ns_query_done(qctx));
   8234   1.1  christos 		} else {
   8235   1.1  christos 			/* Unable to give root server referral. */
   8236   1.9  christos 			CCTRACE(ISC_LOG_ERROR, "unable to give root server "
   8237   1.9  christos 					       "referral");
   8238   1.3  christos 			QUERY_ERROR(qctx, result);
   8239   1.3  christos 			return (ns_query_done(qctx));
   8240   1.1  christos 		}
   8241   1.1  christos 	}
   8242   1.1  christos 
   8243   1.1  christos 	return (query_delegation(qctx));
   8244   1.3  christos 
   8245   1.9  christos cleanup:
   8246   1.3  christos 	return (result);
   8247   1.3  christos }
   8248   1.3  christos 
   8249   1.3  christos /*%
   8250   1.3  christos  * We have a delegation but recursion is not allowed, so return the delegation
   8251   1.3  christos  * to the client.
   8252   1.3  christos  */
   8253   1.3  christos static isc_result_t
   8254   1.3  christos query_prepare_delegation_response(query_ctx_t *qctx) {
   8255   1.3  christos 	isc_result_t result;
   8256   1.3  christos 	dns_rdataset_t **sigrdatasetp = NULL;
   8257   1.3  christos 	bool detach = false;
   8258   1.3  christos 
   8259   1.3  christos 	CALL_HOOK(NS_QUERY_PREP_DELEGATION_BEGIN, qctx);
   8260   1.3  christos 
   8261   1.3  christos 	/*
   8262   1.3  christos 	 * qctx->fname could be released in query_addrrset(), so save a copy of
   8263   1.3  christos 	 * it here in case we need it.
   8264   1.3  christos 	 */
   8265   1.3  christos 	dns_fixedname_init(&qctx->dsname);
   8266   1.8  christos 	dns_name_copynf(qctx->fname, dns_fixedname_name(&qctx->dsname));
   8267   1.3  christos 
   8268   1.3  christos 	/*
   8269   1.3  christos 	 * This is the best answer.
   8270   1.3  christos 	 */
   8271   1.3  christos 	qctx->client->query.isreferral = true;
   8272   1.3  christos 
   8273   1.3  christos 	if (!dns_db_iscache(qctx->db) && qctx->client->query.gluedb == NULL) {
   8274   1.3  christos 		dns_db_attach(qctx->db, &qctx->client->query.gluedb);
   8275   1.3  christos 		detach = true;
   8276   1.3  christos 	}
   8277   1.3  christos 
   8278   1.3  christos 	/*
   8279   1.3  christos 	 * We must ensure NOADDITIONAL is off, because the generation of
   8280   1.3  christos 	 * additional data is required in delegations.
   8281   1.3  christos 	 */
   8282   1.3  christos 	qctx->client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL;
   8283   1.3  christos 	if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) {
   8284   1.3  christos 		sigrdatasetp = &qctx->sigrdataset;
   8285   1.3  christos 	}
   8286   1.9  christos 	query_addrrset(qctx, &qctx->fname, &qctx->rdataset, sigrdatasetp,
   8287   1.9  christos 		       qctx->dbuf, DNS_SECTION_AUTHORITY);
   8288   1.3  christos 	if (detach) {
   8289   1.3  christos 		dns_db_detach(&qctx->client->query.gluedb);
   8290   1.3  christos 	}
   8291   1.3  christos 
   8292   1.3  christos 	/*
   8293   1.3  christos 	 * Add a DS if needed.
   8294   1.3  christos 	 */
   8295   1.3  christos 	query_addds(qctx);
   8296   1.3  christos 
   8297   1.3  christos 	return (ns_query_done(qctx));
   8298   1.3  christos 
   8299   1.9  christos cleanup:
   8300   1.3  christos 	return (result);
   8301   1.1  christos }
   8302   1.1  christos 
   8303   1.1  christos /*%
   8304   1.1  christos  * Handle a delegation response from an authoritative lookup. This
   8305   1.1  christos  * may trigger additional lookups, e.g. from the cache database to
   8306   1.1  christos  * see if we have a better answer; if that is not allowed, return the
   8307   1.3  christos  * delegation to the client and call ns_query_done().
   8308   1.1  christos  */
   8309   1.1  christos static isc_result_t
   8310   1.1  christos query_zone_delegation(query_ctx_t *qctx) {
   8311   1.1  christos 	isc_result_t result;
   8312   1.3  christos 
   8313   1.3  christos 	CALL_HOOK(NS_QUERY_ZONE_DELEGATION_BEGIN, qctx);
   8314   1.1  christos 
   8315   1.1  christos 	/*
   8316   1.1  christos 	 * If the query type is DS, look to see if we are
   8317   1.1  christos 	 * authoritative for the child zone
   8318   1.1  christos 	 */
   8319   1.1  christos 	if (!RECURSIONOK(qctx->client) &&
   8320   1.1  christos 	    (qctx->options & DNS_GETDB_NOEXACT) != 0 &&
   8321   1.1  christos 	    qctx->qtype == dns_rdatatype_ds)
   8322   1.1  christos 	{
   8323   1.1  christos 		dns_db_t *tdb = NULL;
   8324   1.1  christos 		dns_zone_t *tzone = NULL;
   8325   1.1  christos 		dns_dbversion_t *tversion = NULL;
   8326   1.9  christos 		result = query_getzonedb(
   8327   1.9  christos 			qctx->client, qctx->client->query.qname, qctx->qtype,
   8328   1.9  christos 			DNS_GETDB_PARTIAL, &tzone, &tdb, &tversion);
   8329   1.1  christos 		if (result != ISC_R_SUCCESS) {
   8330   1.9  christos 			if (tdb != NULL) {
   8331   1.1  christos 				dns_db_detach(&tdb);
   8332   1.9  christos 			}
   8333   1.9  christos 			if (tzone != NULL) {
   8334   1.1  christos 				dns_zone_detach(&tzone);
   8335   1.9  christos 			}
   8336   1.1  christos 		} else {
   8337   1.1  christos 			qctx->options &= ~DNS_GETDB_NOEXACT;
   8338   1.9  christos 			ns_client_putrdataset(qctx->client, &qctx->rdataset);
   8339   1.3  christos 			if (qctx->sigrdataset != NULL) {
   8340   1.3  christos 				ns_client_putrdataset(qctx->client,
   8341   1.3  christos 						      &qctx->sigrdataset);
   8342   1.3  christos 			}
   8343   1.3  christos 			if (qctx->fname != NULL) {
   8344   1.3  christos 				ns_client_releasename(qctx->client,
   8345   1.3  christos 						      &qctx->fname);
   8346   1.3  christos 			}
   8347   1.9  christos 			if (qctx->node != NULL) {
   8348   1.9  christos 				dns_db_detachnode(qctx->db, &qctx->node);
   8349   1.9  christos 			}
   8350   1.9  christos 			if (qctx->db != NULL) {
   8351   1.1  christos 				dns_db_detach(&qctx->db);
   8352   1.9  christos 			}
   8353   1.9  christos 			if (qctx->zone != NULL) {
   8354   1.1  christos 				dns_zone_detach(&qctx->zone);
   8355   1.9  christos 			}
   8356   1.1  christos 			qctx->version = NULL;
   8357   1.1  christos 			RESTORE(qctx->version, tversion);
   8358   1.1  christos 			RESTORE(qctx->db, tdb);
   8359   1.1  christos 			RESTORE(qctx->zone, tzone);
   8360   1.3  christos 			qctx->authoritative = true;
   8361   1.1  christos 
   8362   1.1  christos 			return (query_lookup(qctx));
   8363   1.1  christos 		}
   8364   1.1  christos 	}
   8365   1.1  christos 
   8366   1.3  christos 	if (USECACHE(qctx->client) &&
   8367   1.3  christos 	    (RECURSIONOK(qctx->client) ||
   8368   1.3  christos 	     (qctx->zone != NULL &&
   8369   1.3  christos 	      dns_zone_gettype(qctx->zone) == dns_zone_mirror)))
   8370   1.3  christos 	{
   8371   1.1  christos 		/*
   8372   1.1  christos 		 * We might have a better answer or delegation in the
   8373   1.1  christos 		 * cache.  We'll remember the current values of fname,
   8374   1.1  christos 		 * rdataset, and sigrdataset.  We'll then go looking for
   8375   1.1  christos 		 * QNAME in the cache.  If we find something better, we'll
   8376   1.1  christos 		 * use it instead. If not, then query_lookup() calls
   8377   1.1  christos 		 * query_notfound() which calls query_delegation(), and
   8378   1.1  christos 		 * we'll restore these values there.
   8379   1.1  christos 		 */
   8380   1.3  christos 		ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
   8381   1.1  christos 		SAVE(qctx->zdb, qctx->db);
   8382   1.3  christos 		SAVE(qctx->znode, qctx->node);
   8383   1.1  christos 		SAVE(qctx->zfname, qctx->fname);
   8384   1.1  christos 		SAVE(qctx->zversion, qctx->version);
   8385   1.1  christos 		SAVE(qctx->zrdataset, qctx->rdataset);
   8386   1.1  christos 		SAVE(qctx->zsigrdataset, qctx->sigrdataset);
   8387   1.3  christos 		dns_db_attach(qctx->view->cachedb, &qctx->db);
   8388   1.3  christos 		qctx->is_zone = false;
   8389   1.1  christos 
   8390   1.1  christos 		return (query_lookup(qctx));
   8391   1.1  christos 	}
   8392   1.1  christos 
   8393   1.3  christos 	return (query_prepare_delegation_response(qctx));
   8394   1.1  christos 
   8395   1.9  christos cleanup:
   8396   1.3  christos 	return (result);
   8397   1.1  christos }
   8398   1.1  christos 
   8399   1.1  christos /*%
   8400   1.1  christos  * Handle delegation responses, including root referrals.
   8401   1.1  christos  *
   8402   1.1  christos  * If the delegation was returned from authoritative data,
   8403   1.1  christos  * call query_zone_delgation().  Otherwise, we can start
   8404   1.1  christos  * recursion if allowed; or else return the delegation to the
   8405   1.3  christos  * client and call ns_query_done().
   8406   1.1  christos  */
   8407   1.1  christos static isc_result_t
   8408   1.1  christos query_delegation(query_ctx_t *qctx) {
   8409   1.1  christos 	isc_result_t result;
   8410   1.1  christos 
   8411   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_delegation");
   8412   1.9  christos 
   8413   1.3  christos 	CALL_HOOK(NS_QUERY_DELEGATION_BEGIN, qctx);
   8414   1.3  christos 
   8415   1.3  christos 	qctx->authoritative = false;
   8416   1.1  christos 
   8417   1.1  christos 	if (qctx->is_zone) {
   8418   1.1  christos 		return (query_zone_delegation(qctx));
   8419   1.1  christos 	}
   8420   1.1  christos 
   8421   1.1  christos 	if (qctx->zfname != NULL &&
   8422   1.1  christos 	    (!dns_name_issubdomain(qctx->fname, qctx->zfname) ||
   8423   1.1  christos 	     (qctx->is_staticstub_zone &&
   8424   1.1  christos 	      dns_name_equal(qctx->fname, qctx->zfname))))
   8425   1.1  christos 	{
   8426   1.1  christos 		/*
   8427   1.1  christos 		 * In the following cases use "authoritative"
   8428   1.1  christos 		 * data instead of the cache delegation:
   8429   1.1  christos 		 * 1. We've already got a delegation from
   8430   1.1  christos 		 *    authoritative data, and it is better
   8431   1.1  christos 		 *    than what we found in the cache.
   8432   1.1  christos 		 *    (See the comment above.)
   8433   1.1  christos 		 * 2. The query name matches the origin name
   8434   1.1  christos 		 *    of a static-stub zone.  This needs to be
   8435   1.1  christos 		 *    considered for the case where the NS of
   8436   1.1  christos 		 *    the static-stub zone and the cached NS
   8437   1.1  christos 		 *    are different.  We still need to contact
   8438   1.1  christos 		 *    the nameservers configured in the
   8439   1.1  christos 		 *    static-stub zone.
   8440   1.1  christos 		 */
   8441   1.3  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   8442   1.1  christos 
   8443   1.1  christos 		/*
   8444   1.3  christos 		 * We've already done ns_client_keepname() on
   8445   1.1  christos 		 * qctx->zfname, so we must set dbuf to NULL to
   8446   1.1  christos 		 * prevent query_addrrset() from trying to
   8447   1.3  christos 		 * call ns_client_keepname() again.
   8448   1.1  christos 		 */
   8449   1.1  christos 		qctx->dbuf = NULL;
   8450   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->rdataset);
   8451   1.3  christos 		if (qctx->sigrdataset != NULL) {
   8452   1.9  christos 			ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
   8453   1.3  christos 		}
   8454   1.1  christos 		qctx->version = NULL;
   8455   1.1  christos 
   8456   1.3  christos 		dns_db_detachnode(qctx->db, &qctx->node);
   8457   1.3  christos 		dns_db_detach(&qctx->db);
   8458   1.3  christos 		RESTORE(qctx->db, qctx->zdb);
   8459   1.3  christos 		RESTORE(qctx->node, qctx->znode);
   8460   1.1  christos 		RESTORE(qctx->fname, qctx->zfname);
   8461   1.1  christos 		RESTORE(qctx->version, qctx->zversion);
   8462   1.1  christos 		RESTORE(qctx->rdataset, qctx->zrdataset);
   8463   1.1  christos 		RESTORE(qctx->sigrdataset, qctx->zsigrdataset);
   8464   1.3  christos 	}
   8465   1.1  christos 
   8466   1.3  christos 	result = query_delegation_recurse(qctx);
   8467   1.3  christos 	if (result != ISC_R_COMPLETE) {
   8468   1.3  christos 		return (result);
   8469   1.1  christos 	}
   8470   1.1  christos 
   8471   1.3  christos 	return (query_prepare_delegation_response(qctx));
   8472   1.1  christos 
   8473   1.9  christos cleanup:
   8474   1.3  christos 	return (result);
   8475   1.3  christos }
   8476   1.1  christos 
   8477   1.3  christos /*%
   8478   1.3  christos  * Handle recursive queries that are triggered as part of the
   8479   1.3  christos  * delegation process.
   8480   1.3  christos  */
   8481   1.3  christos static isc_result_t
   8482   1.3  christos query_delegation_recurse(query_ctx_t *qctx) {
   8483   1.3  christos 	isc_result_t result;
   8484   1.3  christos 	dns_name_t *qname = qctx->client->query.qname;
   8485   1.1  christos 
   8486   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_delegation_recurse");
   8487   1.9  christos 
   8488   1.3  christos 	if (!RECURSIONOK(qctx->client)) {
   8489   1.3  christos 		return (ISC_R_COMPLETE);
   8490   1.1  christos 	}
   8491   1.1  christos 
   8492   1.3  christos 	CALL_HOOK(NS_QUERY_DELEGATION_RECURSE_BEGIN, qctx);
   8493   1.3  christos 
   8494   1.1  christos 	/*
   8495   1.3  christos 	 * We have a delegation and recursion is allowed,
   8496   1.3  christos 	 * so we call ns_query_recurse() to follow it.
   8497   1.3  christos 	 * This phase of the query processing is done;
   8498   1.3  christos 	 * we'll resume via fetch_callback() and
   8499   1.3  christos 	 * query_resume() when the recursion is complete.
   8500   1.1  christos 	 */
   8501   1.1  christos 
   8502   1.3  christos 	INSIST(!REDIRECT(qctx->client));
   8503   1.1  christos 
   8504   1.3  christos 	if (dns_rdatatype_atparent(qctx->type)) {
   8505   1.3  christos 		/*
   8506   1.3  christos 		 * Parent is authoritative for this RDATA type (i.e. DS).
   8507   1.3  christos 		 */
   8508   1.3  christos 		result = ns_query_recurse(qctx->client, qctx->qtype, qname,
   8509   1.3  christos 					  NULL, NULL, qctx->resuming);
   8510   1.3  christos 	} else if (qctx->dns64) {
   8511   1.3  christos 		/*
   8512   1.3  christos 		 * Look up an A record so we can synthesize DNS64.
   8513   1.3  christos 		 */
   8514   1.3  christos 		result = ns_query_recurse(qctx->client, dns_rdatatype_a, qname,
   8515   1.3  christos 					  NULL, NULL, qctx->resuming);
   8516   1.3  christos 	} else {
   8517   1.3  christos 		/*
   8518   1.3  christos 		 * Any other recursion.
   8519   1.3  christos 		 */
   8520   1.3  christos 		result = ns_query_recurse(qctx->client, qctx->qtype, qname,
   8521   1.3  christos 					  qctx->fname, qctx->rdataset,
   8522   1.3  christos 					  qctx->resuming);
   8523   1.1  christos 	}
   8524   1.1  christos 
   8525   1.3  christos 	if (result == ISC_R_SUCCESS) {
   8526   1.3  christos 		qctx->client->query.attributes |= NS_QUERYATTR_RECURSING;
   8527   1.3  christos 		if (qctx->dns64) {
   8528   1.3  christos 			qctx->client->query.attributes |= NS_QUERYATTR_DNS64;
   8529   1.3  christos 		}
   8530   1.3  christos 		if (qctx->dns64_exclude) {
   8531   1.3  christos 			qctx->client->query.attributes |=
   8532   1.9  christos 				NS_QUERYATTR_DNS64EXCLUDE;
   8533   1.3  christos 		}
   8534   1.3  christos 	} else {
   8535   1.3  christos 		QUERY_ERROR(qctx, result);
   8536   1.1  christos 	}
   8537   1.1  christos 
   8538   1.3  christos 	return (ns_query_done(qctx));
   8539   1.1  christos 
   8540   1.9  christos cleanup:
   8541   1.3  christos 	return (result);
   8542   1.1  christos }
   8543   1.1  christos 
   8544   1.1  christos /*%
   8545   1.1  christos  * Add a DS record if needed.
   8546   1.1  christos  */
   8547   1.1  christos static void
   8548   1.1  christos query_addds(query_ctx_t *qctx) {
   8549   1.1  christos 	ns_client_t *client = qctx->client;
   8550   1.1  christos 	dns_fixedname_t fixed;
   8551   1.1  christos 	dns_name_t *fname = NULL;
   8552   1.1  christos 	dns_name_t *rname = NULL;
   8553   1.1  christos 	dns_name_t *name;
   8554   1.1  christos 	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
   8555   1.1  christos 	isc_buffer_t *dbuf, b;
   8556   1.1  christos 	isc_result_t result;
   8557   1.1  christos 	unsigned int count;
   8558   1.1  christos 
   8559   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addds");
   8560   1.1  christos 
   8561   1.1  christos 	/*
   8562   1.1  christos 	 * DS not needed.
   8563   1.1  christos 	 */
   8564   1.1  christos 	if (!WANTDNSSEC(client)) {
   8565   1.1  christos 		return;
   8566   1.1  christos 	}
   8567   1.1  christos 
   8568   1.1  christos 	/*
   8569   1.1  christos 	 * We'll need some resources...
   8570   1.1  christos 	 */
   8571   1.3  christos 	rdataset = ns_client_newrdataset(client);
   8572   1.3  christos 	sigrdataset = ns_client_newrdataset(client);
   8573   1.9  christos 	if (rdataset == NULL || sigrdataset == NULL) {
   8574   1.1  christos 		goto cleanup;
   8575   1.9  christos 	}
   8576   1.1  christos 
   8577   1.1  christos 	/*
   8578   1.1  christos 	 * Look for the DS record, which may or may not be present.
   8579   1.1  christos 	 */
   8580   1.1  christos 	result = dns_db_findrdataset(qctx->db, qctx->node, qctx->version,
   8581   1.9  christos 				     dns_rdatatype_ds, 0, client->now, rdataset,
   8582   1.9  christos 				     sigrdataset);
   8583   1.1  christos 	/*
   8584   1.1  christos 	 * If we didn't find it, look for an NSEC.
   8585   1.1  christos 	 */
   8586   1.9  christos 	if (result == ISC_R_NOTFOUND) {
   8587   1.9  christos 		result = dns_db_findrdataset(
   8588   1.9  christos 			qctx->db, qctx->node, qctx->version, dns_rdatatype_nsec,
   8589   1.9  christos 			0, client->now, rdataset, sigrdataset);
   8590   1.9  christos 	}
   8591   1.9  christos 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   8592   1.1  christos 		goto addnsec3;
   8593   1.9  christos 	}
   8594   1.1  christos 	if (!dns_rdataset_isassociated(rdataset) ||
   8595   1.1  christos 	    !dns_rdataset_isassociated(sigrdataset))
   8596   1.9  christos 	{
   8597   1.1  christos 		goto addnsec3;
   8598   1.9  christos 	}
   8599   1.1  christos 
   8600   1.1  christos 	/*
   8601   1.1  christos 	 * We've already added the NS record, so if the name's not there,
   8602   1.1  christos 	 * we have other problems.  Use this name rather than calling
   8603   1.1  christos 	 * query_addrrset().
   8604   1.1  christos 	 */
   8605   1.1  christos 	result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
   8606   1.9  christos 	if (result != ISC_R_SUCCESS) {
   8607   1.1  christos 		goto cleanup;
   8608   1.9  christos 	}
   8609   1.1  christos 
   8610   1.1  christos 	rname = NULL;
   8611   1.9  christos 	dns_message_currentname(client->message, DNS_SECTION_AUTHORITY, &rname);
   8612   1.1  christos 	result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
   8613   1.9  christos 	if (result != ISC_R_SUCCESS) {
   8614   1.1  christos 		goto cleanup;
   8615   1.9  christos 	}
   8616   1.1  christos 
   8617   1.1  christos 	ISC_LIST_APPEND(rname->list, rdataset, link);
   8618   1.1  christos 	ISC_LIST_APPEND(rname->list, sigrdataset, link);
   8619   1.1  christos 	rdataset = NULL;
   8620   1.1  christos 	sigrdataset = NULL;
   8621   1.1  christos 	return;
   8622   1.1  christos 
   8623   1.9  christos addnsec3:
   8624   1.9  christos 	if (!dns_db_iszone(qctx->db)) {
   8625   1.1  christos 		goto cleanup;
   8626   1.9  christos 	}
   8627   1.1  christos 	/*
   8628   1.1  christos 	 * Add the NSEC3 which proves the DS does not exist.
   8629   1.1  christos 	 */
   8630   1.3  christos 	dbuf = ns_client_getnamebuf(client);
   8631   1.9  christos 	if (dbuf == NULL) {
   8632   1.1  christos 		goto cleanup;
   8633   1.9  christos 	}
   8634   1.3  christos 	fname = ns_client_newname(client, dbuf, &b);
   8635   1.1  christos 	dns_fixedname_init(&fixed);
   8636   1.9  christos 	if (dns_rdataset_isassociated(rdataset)) {
   8637   1.1  christos 		dns_rdataset_disassociate(rdataset);
   8638   1.9  christos 	}
   8639   1.9  christos 	if (dns_rdataset_isassociated(sigrdataset)) {
   8640   1.1  christos 		dns_rdataset_disassociate(sigrdataset);
   8641   1.9  christos 	}
   8642   1.1  christos 	name = dns_fixedname_name(&qctx->dsname);
   8643   1.1  christos 	query_findclosestnsec3(name, qctx->db, qctx->version, client, rdataset,
   8644   1.3  christos 			       sigrdataset, fname, true,
   8645   1.1  christos 			       dns_fixedname_name(&fixed));
   8646   1.9  christos 	if (!dns_rdataset_isassociated(rdataset)) {
   8647   1.1  christos 		goto cleanup;
   8648   1.9  christos 	}
   8649   1.3  christos 	query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
   8650   1.1  christos 		       DNS_SECTION_AUTHORITY);
   8651   1.1  christos 	/*
   8652   1.1  christos 	 * Did we find the closest provable encloser instead?
   8653   1.1  christos 	 * If so add the nearest to the closest provable encloser.
   8654   1.1  christos 	 */
   8655   1.1  christos 	if (!dns_name_equal(name, dns_fixedname_name(&fixed))) {
   8656   1.1  christos 		count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1;
   8657   1.1  christos 		dns_name_getlabelsequence(name,
   8658   1.1  christos 					  dns_name_countlabels(name) - count,
   8659   1.1  christos 					  count, dns_fixedname_name(&fixed));
   8660   1.1  christos 		fixfname(client, &fname, &dbuf, &b);
   8661   1.1  christos 		fixrdataset(client, &rdataset);
   8662   1.1  christos 		fixrdataset(client, &sigrdataset);
   8663   1.9  christos 		if (fname == NULL || rdataset == NULL || sigrdataset == NULL) {
   8664   1.9  christos 			goto cleanup;
   8665   1.9  christos 		}
   8666   1.9  christos 		query_findclosestnsec3(dns_fixedname_name(&fixed), qctx->db,
   8667   1.9  christos 				       qctx->version, client, rdataset,
   8668   1.9  christos 				       sigrdataset, fname, false, NULL);
   8669   1.9  christos 		if (!dns_rdataset_isassociated(rdataset)) {
   8670   1.1  christos 			goto cleanup;
   8671   1.9  christos 		}
   8672   1.3  christos 		query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
   8673   1.1  christos 			       DNS_SECTION_AUTHORITY);
   8674   1.1  christos 	}
   8675   1.1  christos 
   8676   1.9  christos cleanup:
   8677   1.3  christos 	if (rdataset != NULL) {
   8678   1.3  christos 		ns_client_putrdataset(client, &rdataset);
   8679   1.3  christos 	}
   8680   1.3  christos 	if (sigrdataset != NULL) {
   8681   1.3  christos 		ns_client_putrdataset(client, &sigrdataset);
   8682   1.3  christos 	}
   8683   1.3  christos 	if (fname != NULL) {
   8684   1.3  christos 		ns_client_releasename(client, &fname);
   8685   1.3  christos 	}
   8686   1.1  christos }
   8687   1.1  christos 
   8688   1.1  christos /*%
   8689   1.1  christos  * Handle authoritative NOERROR/NODATA responses.
   8690   1.1  christos  */
   8691   1.1  christos static isc_result_t
   8692   1.3  christos query_nodata(query_ctx_t *qctx, isc_result_t res) {
   8693   1.3  christos 	isc_result_t result = res;
   8694   1.3  christos 
   8695   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_nodata");
   8696   1.9  christos 
   8697   1.3  christos 	CALL_HOOK(NS_QUERY_NODATA_BEGIN, qctx);
   8698   1.3  christos 
   8699   1.1  christos #ifdef dns64_bis_return_excluded_addresses
   8700   1.1  christos 	if (qctx->dns64)
   8701   1.9  christos #else  /* ifdef dns64_bis_return_excluded_addresses */
   8702   1.1  christos 	if (qctx->dns64 && !qctx->dns64_exclude)
   8703   1.9  christos #endif /* ifdef dns64_bis_return_excluded_addresses */
   8704   1.1  christos 	{
   8705   1.1  christos 		isc_buffer_t b;
   8706   1.1  christos 		/*
   8707   1.1  christos 		 * Restore the answers from the previous AAAA lookup.
   8708   1.1  christos 		 */
   8709   1.9  christos 		if (qctx->rdataset != NULL) {
   8710   1.3  christos 			ns_client_putrdataset(qctx->client, &qctx->rdataset);
   8711   1.9  christos 		}
   8712   1.9  christos 		if (qctx->sigrdataset != NULL) {
   8713   1.3  christos 			ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
   8714   1.9  christos 		}
   8715   1.1  christos 		RESTORE(qctx->rdataset, qctx->client->query.dns64_aaaa);
   8716   1.1  christos 		RESTORE(qctx->sigrdataset, qctx->client->query.dns64_sigaaaa);
   8717   1.1  christos 		if (qctx->fname == NULL) {
   8718   1.3  christos 			qctx->dbuf = ns_client_getnamebuf(qctx->client);
   8719   1.1  christos 			if (qctx->dbuf == NULL) {
   8720   1.9  christos 				CCTRACE(ISC_LOG_ERROR, "query_nodata: "
   8721   1.9  christos 						       "ns_client_getnamebuf "
   8722   1.9  christos 						       "failed (3)");
   8723   1.3  christos 				QUERY_ERROR(qctx, ISC_R_NOMEMORY);
   8724   1.9  christos 				return (ns_query_done(qctx));
   8725   1.1  christos 			}
   8726   1.3  christos 			qctx->fname = ns_client_newname(qctx->client,
   8727   1.3  christos 							qctx->dbuf, &b);
   8728   1.1  christos 			if (qctx->fname == NULL) {
   8729   1.9  christos 				CCTRACE(ISC_LOG_ERROR, "query_nodata: "
   8730   1.9  christos 						       "ns_client_newname "
   8731   1.9  christos 						       "failed (3)");
   8732   1.3  christos 				QUERY_ERROR(qctx, ISC_R_NOMEMORY);
   8733   1.9  christos 				return (ns_query_done(qctx));
   8734   1.1  christos 			}
   8735   1.1  christos 		}
   8736   1.8  christos 		dns_name_copynf(qctx->client->query.qname, qctx->fname);
   8737   1.3  christos 		qctx->dns64 = false;
   8738   1.1  christos #ifdef dns64_bis_return_excluded_addresses
   8739   1.1  christos 		/*
   8740   1.1  christos 		 * Resume the diverted processing of the AAAA response?
   8741   1.1  christos 		 */
   8742   1.9  christos 		if (qctx->dns64_exclude) {
   8743   1.1  christos 			return (query_prepresponse(qctx));
   8744   1.9  christos 		}
   8745   1.9  christos #endif /* ifdef dns64_bis_return_excluded_addresses */
   8746   1.9  christos 	} else if ((result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) &&
   8747   1.9  christos 		   !ISC_LIST_EMPTY(qctx->view->dns64) && !qctx->nxrewrite &&
   8748   1.1  christos 		   qctx->client->message->rdclass == dns_rdataclass_in &&
   8749   1.1  christos 		   qctx->qtype == dns_rdatatype_aaaa)
   8750   1.1  christos 	{
   8751   1.1  christos 		/*
   8752   1.1  christos 		 * Look to see if there are A records for this name.
   8753   1.1  christos 		 */
   8754   1.1  christos 		switch (result) {
   8755   1.1  christos 		case DNS_R_NCACHENXRRSET:
   8756   1.1  christos 			/*
   8757   1.1  christos 			 * This is from the negative cache; if the ttl is
   8758   1.1  christos 			 * zero, we need to work out whether we have just
   8759   1.1  christos 			 * decremented to zero or there was no negative
   8760   1.1  christos 			 * cache ttl in the answer.
   8761   1.1  christos 			 */
   8762   1.1  christos 			if (qctx->rdataset->ttl != 0) {
   8763   1.1  christos 				qctx->client->query.dns64_ttl =
   8764   1.1  christos 					qctx->rdataset->ttl;
   8765   1.1  christos 				break;
   8766   1.1  christos 			}
   8767   1.1  christos 			if (dns_rdataset_first(qctx->rdataset) == ISC_R_SUCCESS)
   8768   1.9  christos 			{
   8769   1.1  christos 				qctx->client->query.dns64_ttl = 0;
   8770   1.9  christos 			}
   8771   1.1  christos 			break;
   8772   1.1  christos 		case DNS_R_NXRRSET:
   8773   1.1  christos 			qctx->client->query.dns64_ttl =
   8774   1.1  christos 				dns64_ttl(qctx->db, qctx->version);
   8775   1.1  christos 			break;
   8776   1.1  christos 		default:
   8777   1.1  christos 			INSIST(0);
   8778   1.3  christos 			ISC_UNREACHABLE();
   8779   1.1  christos 		}
   8780   1.1  christos 
   8781   1.1  christos 		SAVE(qctx->client->query.dns64_aaaa, qctx->rdataset);
   8782   1.1  christos 		SAVE(qctx->client->query.dns64_sigaaaa, qctx->sigrdataset);
   8783   1.3  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   8784   1.1  christos 		dns_db_detachnode(qctx->db, &qctx->node);
   8785   1.1  christos 		qctx->type = qctx->qtype = dns_rdatatype_a;
   8786   1.3  christos 		qctx->dns64 = true;
   8787   1.1  christos 		return (query_lookup(qctx));
   8788   1.1  christos 	}
   8789   1.1  christos 
   8790   1.1  christos 	if (qctx->is_zone) {
   8791   1.1  christos 		return (query_sign_nodata(qctx));
   8792   1.1  christos 	} else {
   8793   1.1  christos 		/*
   8794   1.1  christos 		 * We don't call query_addrrset() because we don't need any
   8795   1.1  christos 		 * of its extra features (and things would probably break!).
   8796   1.1  christos 		 */
   8797   1.1  christos 		if (dns_rdataset_isassociated(qctx->rdataset)) {
   8798   1.3  christos 			ns_client_keepname(qctx->client, qctx->fname,
   8799   1.3  christos 					   qctx->dbuf);
   8800   1.9  christos 			dns_message_addname(qctx->client->message, qctx->fname,
   8801   1.1  christos 					    DNS_SECTION_AUTHORITY);
   8802   1.9  christos 			ISC_LIST_APPEND(qctx->fname->list, qctx->rdataset,
   8803   1.9  christos 					link);
   8804   1.1  christos 			qctx->fname = NULL;
   8805   1.1  christos 			qctx->rdataset = NULL;
   8806   1.1  christos 		}
   8807   1.1  christos 	}
   8808   1.1  christos 
   8809   1.3  christos 	return (ns_query_done(qctx));
   8810   1.3  christos 
   8811   1.9  christos cleanup:
   8812   1.3  christos 	return (result);
   8813   1.1  christos }
   8814   1.1  christos 
   8815   1.1  christos /*%
   8816   1.1  christos  * Add RRSIGs for NOERROR/NODATA responses when answering authoritatively.
   8817   1.1  christos  */
   8818   1.1  christos isc_result_t
   8819   1.1  christos query_sign_nodata(query_ctx_t *qctx) {
   8820   1.1  christos 	isc_result_t result;
   8821   1.9  christos 
   8822   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_sign_nodata");
   8823   1.9  christos 
   8824   1.1  christos 	/*
   8825   1.1  christos 	 * Look for a NSEC3 record if we don't have a NSEC record.
   8826   1.1  christos 	 */
   8827   1.9  christos 	if (qctx->redirected) {
   8828   1.3  christos 		return (ns_query_done(qctx));
   8829   1.9  christos 	}
   8830   1.1  christos 	if (!dns_rdataset_isassociated(qctx->rdataset) &&
   8831   1.9  christos 	    WANTDNSSEC(qctx->client)) {
   8832   1.1  christos 		if ((qctx->fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
   8833   1.1  christos 			dns_name_t *found;
   8834   1.1  christos 			dns_name_t *qname;
   8835   1.1  christos 			dns_fixedname_t fixed;
   8836   1.1  christos 			isc_buffer_t b;
   8837   1.1  christos 
   8838   1.1  christos 			found = dns_fixedname_initname(&fixed);
   8839   1.1  christos 			qname = qctx->client->query.qname;
   8840   1.1  christos 
   8841   1.1  christos 			query_findclosestnsec3(qname, qctx->db, qctx->version,
   8842   1.1  christos 					       qctx->client, qctx->rdataset,
   8843   1.1  christos 					       qctx->sigrdataset, qctx->fname,
   8844   1.3  christos 					       true, found);
   8845   1.1  christos 			/*
   8846   1.1  christos 			 * Did we find the closest provable encloser
   8847   1.1  christos 			 * instead? If so add the nearest to the
   8848   1.1  christos 			 * closest provable encloser.
   8849   1.1  christos 			 */
   8850   1.1  christos 			if (dns_rdataset_isassociated(qctx->rdataset) &&
   8851   1.1  christos 			    !dns_name_equal(qname, found) &&
   8852   1.1  christos 			    (((qctx->client->sctx->options &
   8853   1.1  christos 			       NS_SERVER_NONEAREST) == 0) ||
   8854   1.1  christos 			     qctx->qtype == dns_rdatatype_ds))
   8855   1.1  christos 			{
   8856   1.1  christos 				unsigned int count;
   8857   1.1  christos 				unsigned int skip;
   8858   1.1  christos 
   8859   1.1  christos 				/*
   8860   1.1  christos 				 * Add the closest provable encloser.
   8861   1.1  christos 				 */
   8862   1.3  christos 				query_addrrset(qctx, &qctx->fname,
   8863   1.1  christos 					       &qctx->rdataset,
   8864   1.9  christos 					       &qctx->sigrdataset, qctx->dbuf,
   8865   1.1  christos 					       DNS_SECTION_AUTHORITY);
   8866   1.1  christos 
   8867   1.9  christos 				count = dns_name_countlabels(found) + 1;
   8868   1.9  christos 				skip = dns_name_countlabels(qname) - count;
   8869   1.9  christos 				dns_name_getlabelsequence(qname, skip, count,
   8870   1.1  christos 							  found);
   8871   1.1  christos 
   8872   1.1  christos 				fixfname(qctx->client, &qctx->fname,
   8873   1.1  christos 					 &qctx->dbuf, &b);
   8874   1.1  christos 				fixrdataset(qctx->client, &qctx->rdataset);
   8875   1.1  christos 				fixrdataset(qctx->client, &qctx->sigrdataset);
   8876   1.1  christos 				if (qctx->fname == NULL ||
   8877   1.1  christos 				    qctx->rdataset == NULL ||
   8878   1.1  christos 				    qctx->sigrdataset == NULL) {
   8879   1.9  christos 					CCTRACE(ISC_LOG_ERROR, "query_sign_"
   8880   1.9  christos 							       "nodata: "
   8881   1.9  christos 							       "failure "
   8882   1.9  christos 							       "getting "
   8883   1.9  christos 							       "closest "
   8884   1.9  christos 							       "encloser");
   8885   1.3  christos 					QUERY_ERROR(qctx, ISC_R_NOMEMORY);
   8886   1.3  christos 					return (ns_query_done(qctx));
   8887   1.1  christos 				}
   8888   1.1  christos 				/*
   8889   1.1  christos 				 * 'nearest' doesn't exist so
   8890   1.3  christos 				 * 'exist' is set to false.
   8891   1.1  christos 				 */
   8892   1.9  christos 				query_findclosestnsec3(
   8893   1.9  christos 					found, qctx->db, qctx->version,
   8894   1.9  christos 					qctx->client, qctx->rdataset,
   8895   1.9  christos 					qctx->sigrdataset, qctx->fname, false,
   8896   1.9  christos 					NULL);
   8897   1.1  christos 			}
   8898   1.1  christos 		} else {
   8899   1.3  christos 			ns_client_releasename(qctx->client, &qctx->fname);
   8900   1.3  christos 			query_addwildcardproof(qctx, false, true);
   8901   1.1  christos 		}
   8902   1.1  christos 	}
   8903   1.1  christos 	if (dns_rdataset_isassociated(qctx->rdataset)) {
   8904   1.1  christos 		/*
   8905   1.1  christos 		 * If we've got a NSEC record, we need to save the
   8906   1.1  christos 		 * name now because we're going call query_addsoa()
   8907   1.1  christos 		 * below, and it needs to use the name buffer.
   8908   1.1  christos 		 */
   8909   1.3  christos 		ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
   8910   1.1  christos 	} else if (qctx->fname != NULL) {
   8911   1.1  christos 		/*
   8912   1.1  christos 		 * We're not going to use fname, and need to release
   8913   1.1  christos 		 * our hold on the name buffer so query_addsoa()
   8914   1.1  christos 		 * may use it.
   8915   1.1  christos 		 */
   8916   1.3  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   8917   1.1  christos 	}
   8918   1.1  christos 
   8919   1.1  christos 	/*
   8920   1.1  christos 	 * The RPZ SOA has already been added to the additional section
   8921   1.1  christos 	 * if this was an RPZ rewrite, but if it wasn't, add it now.
   8922   1.1  christos 	 */
   8923   1.1  christos 	if (!qctx->nxrewrite) {
   8924   1.9  christos 		result = query_addsoa(qctx, UINT32_MAX, DNS_SECTION_AUTHORITY);
   8925   1.1  christos 		if (result != ISC_R_SUCCESS) {
   8926   1.1  christos 			QUERY_ERROR(qctx, result);
   8927   1.3  christos 			return (ns_query_done(qctx));
   8928   1.1  christos 		}
   8929   1.1  christos 	}
   8930   1.1  christos 
   8931   1.1  christos 	/*
   8932   1.1  christos 	 * Add NSEC record if we found one.
   8933   1.1  christos 	 */
   8934   1.1  christos 	if (WANTDNSSEC(qctx->client) &&
   8935   1.9  christos 	    dns_rdataset_isassociated(qctx->rdataset)) {
   8936   1.1  christos 		query_addnxrrsetnsec(qctx);
   8937   1.1  christos 	}
   8938   1.1  christos 
   8939   1.3  christos 	return (ns_query_done(qctx));
   8940   1.1  christos }
   8941   1.1  christos 
   8942   1.1  christos static void
   8943   1.1  christos query_addnxrrsetnsec(query_ctx_t *qctx) {
   8944   1.1  christos 	ns_client_t *client = qctx->client;
   8945   1.1  christos 	dns_rdata_t sigrdata;
   8946   1.1  christos 	dns_rdata_rrsig_t sig;
   8947   1.1  christos 	unsigned int labels;
   8948   1.1  christos 	isc_buffer_t *dbuf, b;
   8949   1.1  christos 	dns_name_t *fname;
   8950   1.3  christos 	isc_result_t result;
   8951   1.1  christos 
   8952   1.1  christos 	INSIST(qctx->fname != NULL);
   8953   1.1  christos 
   8954   1.1  christos 	if ((qctx->fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
   8955   1.9  christos 		query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
   8956   1.9  christos 			       &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY);
   8957   1.1  christos 		return;
   8958   1.1  christos 	}
   8959   1.1  christos 
   8960   1.1  christos 	if (qctx->sigrdataset == NULL ||
   8961   1.9  christos 	    !dns_rdataset_isassociated(qctx->sigrdataset)) {
   8962   1.1  christos 		return;
   8963   1.1  christos 	}
   8964   1.1  christos 
   8965   1.1  christos 	if (dns_rdataset_first(qctx->sigrdataset) != ISC_R_SUCCESS) {
   8966   1.1  christos 		return;
   8967   1.1  christos 	}
   8968   1.1  christos 
   8969   1.1  christos 	dns_rdata_init(&sigrdata);
   8970   1.1  christos 	dns_rdataset_current(qctx->sigrdataset, &sigrdata);
   8971   1.3  christos 	result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
   8972   1.3  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8973   1.1  christos 
   8974   1.1  christos 	labels = dns_name_countlabels(qctx->fname);
   8975   1.1  christos 	if ((unsigned int)sig.labels + 1 >= labels) {
   8976   1.1  christos 		return;
   8977   1.1  christos 	}
   8978   1.1  christos 
   8979   1.3  christos 	query_addwildcardproof(qctx, true, false);
   8980   1.1  christos 
   8981   1.1  christos 	/*
   8982   1.1  christos 	 * We'll need some resources...
   8983   1.1  christos 	 */
   8984   1.3  christos 	dbuf = ns_client_getnamebuf(client);
   8985   1.1  christos 	if (dbuf == NULL) {
   8986   1.1  christos 		return;
   8987   1.1  christos 	}
   8988   1.1  christos 
   8989   1.3  christos 	fname = ns_client_newname(client, dbuf, &b);
   8990   1.1  christos 	if (fname == NULL) {
   8991   1.1  christos 		return;
   8992   1.1  christos 	}
   8993   1.1  christos 
   8994   1.1  christos 	dns_name_split(qctx->fname, sig.labels + 1, NULL, fname);
   8995   1.1  christos 	/* This will succeed, since we've stripped labels. */
   8996   1.1  christos 	RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,
   8997   1.1  christos 					   NULL) == ISC_R_SUCCESS);
   8998   1.9  christos 	query_addrrset(qctx, &fname, &qctx->rdataset, &qctx->sigrdataset, dbuf,
   8999   1.9  christos 		       DNS_SECTION_AUTHORITY);
   9000   1.1  christos }
   9001   1.1  christos 
   9002   1.1  christos /*%
   9003   1.1  christos  * Handle NXDOMAIN and empty wildcard responses.
   9004   1.1  christos  */
   9005   1.1  christos static isc_result_t
   9006   1.3  christos query_nxdomain(query_ctx_t *qctx, bool empty_wild) {
   9007   1.1  christos 	dns_section_t section;
   9008   1.3  christos 	uint32_t ttl;
   9009   1.1  christos 	isc_result_t result;
   9010   1.1  christos 
   9011   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_nxdomain");
   9012   1.9  christos 
   9013   1.3  christos 	CALL_HOOK(NS_QUERY_NXDOMAIN_BEGIN, qctx);
   9014   1.3  christos 
   9015   1.1  christos 	INSIST(qctx->is_zone || REDIRECT(qctx->client));
   9016   1.1  christos 
   9017   1.1  christos 	if (!empty_wild) {
   9018   1.1  christos 		result = query_redirect(qctx);
   9019   1.9  christos 		if (result != ISC_R_COMPLETE) {
   9020   1.1  christos 			return (result);
   9021   1.9  christos 		}
   9022   1.1  christos 	}
   9023   1.1  christos 
   9024   1.1  christos 	if (dns_rdataset_isassociated(qctx->rdataset)) {
   9025   1.1  christos 		/*
   9026   1.1  christos 		 * If we've got a NSEC record, we need to save the
   9027   1.1  christos 		 * name now because we're going call query_addsoa()
   9028   1.1  christos 		 * below, and it needs to use the name buffer.
   9029   1.1  christos 		 */
   9030   1.3  christos 		ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
   9031   1.1  christos 	} else if (qctx->fname != NULL) {
   9032   1.1  christos 		/*
   9033   1.1  christos 		 * We're not going to use fname, and need to release
   9034   1.1  christos 		 * our hold on the name buffer so query_addsoa()
   9035   1.1  christos 		 * may use it.
   9036   1.1  christos 		 */
   9037   1.3  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   9038   1.1  christos 	}
   9039   1.1  christos 
   9040   1.1  christos 	/*
   9041   1.1  christos 	 * Add SOA to the additional section if generated by a
   9042   1.1  christos 	 * RPZ rewrite.
   9043   1.1  christos 	 *
   9044   1.1  christos 	 * If the query was for a SOA record force the
   9045   1.1  christos 	 * ttl to zero so that it is possible for clients to find
   9046   1.1  christos 	 * the containing zone of an arbitrary name with a stub
   9047   1.1  christos 	 * resolver and not have it cached.
   9048   1.1  christos 	 */
   9049   1.1  christos 	section = qctx->nxrewrite ? DNS_SECTION_ADDITIONAL
   9050   1.1  christos 				  : DNS_SECTION_AUTHORITY;
   9051   1.3  christos 	ttl = UINT32_MAX;
   9052   1.1  christos 	if (!qctx->nxrewrite && qctx->qtype == dns_rdatatype_soa &&
   9053   1.1  christos 	    qctx->zone != NULL && dns_zone_getzeronosoattl(qctx->zone))
   9054   1.1  christos 	{
   9055   1.1  christos 		ttl = 0;
   9056   1.1  christos 	}
   9057   1.5  christos 	if (!qctx->nxrewrite || qctx->rpz_st->m.rpz->addsoa) {
   9058   1.5  christos 		result = query_addsoa(qctx, ttl, section);
   9059   1.5  christos 		if (result != ISC_R_SUCCESS) {
   9060   1.5  christos 			QUERY_ERROR(qctx, result);
   9061   1.5  christos 			return (ns_query_done(qctx));
   9062   1.5  christos 		}
   9063   1.1  christos 	}
   9064   1.1  christos 
   9065   1.1  christos 	if (WANTDNSSEC(qctx->client)) {
   9066   1.1  christos 		/*
   9067   1.1  christos 		 * Add NSEC record if we found one.
   9068   1.1  christos 		 */
   9069   1.9  christos 		if (dns_rdataset_isassociated(qctx->rdataset)) {
   9070   1.9  christos 			query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
   9071   1.9  christos 				       &qctx->sigrdataset, NULL,
   9072   1.9  christos 				       DNS_SECTION_AUTHORITY);
   9073   1.9  christos 		}
   9074   1.3  christos 		query_addwildcardproof(qctx, false, false);
   9075   1.1  christos 	}
   9076   1.1  christos 
   9077   1.1  christos 	/*
   9078   1.1  christos 	 * Set message rcode.
   9079   1.1  christos 	 */
   9080   1.9  christos 	if (empty_wild) {
   9081   1.1  christos 		qctx->client->message->rcode = dns_rcode_noerror;
   9082   1.9  christos 	} else {
   9083   1.1  christos 		qctx->client->message->rcode = dns_rcode_nxdomain;
   9084   1.9  christos 	}
   9085   1.1  christos 
   9086   1.3  christos 	return (ns_query_done(qctx));
   9087   1.3  christos 
   9088   1.9  christos cleanup:
   9089   1.3  christos 	return (result);
   9090   1.1  christos }
   9091   1.1  christos 
   9092   1.1  christos /*
   9093   1.1  christos  * Handle both types of NXDOMAIN redirection, calling redirect()
   9094   1.1  christos  * (which implements type redirect zones) and redirect2() (which
   9095   1.1  christos  * implements recursive nxdomain-redirect lookups).
   9096   1.1  christos  *
   9097   1.1  christos  * Any result code other than ISC_R_COMPLETE means redirection was
   9098   1.1  christos  * successful and the result code should be returned up the call stack.
   9099   1.1  christos  *
   9100   1.1  christos  * ISC_R_COMPLETE means we reached the end of this function without
   9101   1.1  christos  * redirecting, so query processing should continue past it.
   9102   1.1  christos  */
   9103   1.1  christos static isc_result_t
   9104   1.9  christos query_redirect(query_ctx_t *qctx) {
   9105   1.1  christos 	isc_result_t result;
   9106   1.1  christos 
   9107   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_redirect");
   9108   1.9  christos 
   9109   1.1  christos 	result = redirect(qctx->client, qctx->fname, qctx->rdataset,
   9110   1.9  christos 			  &qctx->node, &qctx->db, &qctx->version, qctx->type);
   9111   1.1  christos 	switch (result) {
   9112   1.1  christos 	case ISC_R_SUCCESS:
   9113   1.9  christos 		inc_stats(qctx->client, ns_statscounter_nxdomainredirect);
   9114   1.1  christos 		return (query_prepresponse(qctx));
   9115   1.1  christos 	case DNS_R_NXRRSET:
   9116   1.3  christos 		qctx->redirected = true;
   9117   1.3  christos 		qctx->is_zone = true;
   9118   1.1  christos 		return (query_nodata(qctx, DNS_R_NXRRSET));
   9119   1.1  christos 	case DNS_R_NCACHENXRRSET:
   9120   1.3  christos 		qctx->redirected = true;
   9121   1.3  christos 		qctx->is_zone = false;
   9122   1.1  christos 		return (query_ncache(qctx, DNS_R_NCACHENXRRSET));
   9123   1.1  christos 	default:
   9124   1.1  christos 		break;
   9125   1.1  christos 	}
   9126   1.1  christos 
   9127   1.1  christos 	result = redirect2(qctx->client, qctx->fname, qctx->rdataset,
   9128   1.9  christos 			   &qctx->node, &qctx->db, &qctx->version, qctx->type,
   9129   1.9  christos 			   &qctx->is_zone);
   9130   1.1  christos 	switch (result) {
   9131   1.1  christos 	case ISC_R_SUCCESS:
   9132   1.9  christos 		inc_stats(qctx->client, ns_statscounter_nxdomainredirect);
   9133   1.1  christos 		return (query_prepresponse(qctx));
   9134   1.1  christos 	case DNS_R_CONTINUE:
   9135   1.1  christos 		inc_stats(qctx->client,
   9136   1.1  christos 			  ns_statscounter_nxdomainredirect_rlookup);
   9137   1.1  christos 		SAVE(qctx->client->query.redirect.db, qctx->db);
   9138   1.1  christos 		SAVE(qctx->client->query.redirect.node, qctx->node);
   9139   1.1  christos 		SAVE(qctx->client->query.redirect.zone, qctx->zone);
   9140   1.1  christos 		qctx->client->query.redirect.qtype = qctx->qtype;
   9141   1.1  christos 		INSIST(qctx->rdataset != NULL);
   9142   1.1  christos 		SAVE(qctx->client->query.redirect.rdataset, qctx->rdataset);
   9143   1.1  christos 		SAVE(qctx->client->query.redirect.sigrdataset,
   9144   1.1  christos 		     qctx->sigrdataset);
   9145   1.1  christos 		qctx->client->query.redirect.result = DNS_R_NCACHENXDOMAIN;
   9146   1.8  christos 		dns_name_copynf(qctx->fname,
   9147   1.9  christos 				qctx->client->query.redirect.fname);
   9148   1.1  christos 		qctx->client->query.redirect.authoritative =
   9149   1.1  christos 			qctx->authoritative;
   9150   1.1  christos 		qctx->client->query.redirect.is_zone = qctx->is_zone;
   9151   1.3  christos 		return (ns_query_done(qctx));
   9152   1.1  christos 	case DNS_R_NXRRSET:
   9153   1.3  christos 		qctx->redirected = true;
   9154   1.3  christos 		qctx->is_zone = true;
   9155   1.1  christos 		return (query_nodata(qctx, DNS_R_NXRRSET));
   9156   1.1  christos 	case DNS_R_NCACHENXRRSET:
   9157   1.3  christos 		qctx->redirected = true;
   9158   1.3  christos 		qctx->is_zone = false;
   9159   1.1  christos 		return (query_ncache(qctx, DNS_R_NCACHENXRRSET));
   9160   1.1  christos 	default:
   9161   1.1  christos 		break;
   9162   1.1  christos 	}
   9163   1.1  christos 
   9164   1.1  christos 	return (ISC_R_COMPLETE);
   9165   1.1  christos }
   9166   1.1  christos 
   9167   1.1  christos /*%
   9168   1.1  christos  * Logging function to be passed to dns_nsec_noexistnodata.
   9169   1.1  christos  */
   9170   1.1  christos static void
   9171   1.1  christos log_noexistnodata(void *val, int level, const char *fmt, ...) {
   9172   1.1  christos 	query_ctx_t *qctx = val;
   9173   1.1  christos 	va_list ap;
   9174   1.1  christos 
   9175   1.1  christos 	va_start(ap, fmt);
   9176   1.9  christos 	ns_client_logv(qctx->client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
   9177   1.9  christos 		       level, fmt, ap);
   9178   1.1  christos 	va_end(ap);
   9179   1.1  christos }
   9180   1.1  christos 
   9181   1.1  christos static dns_ttl_t
   9182   1.1  christos query_synthttl(dns_rdataset_t *soardataset, dns_rdataset_t *sigsoardataset,
   9183   1.1  christos 	       dns_rdataset_t *p1rdataset, dns_rdataset_t *sigp1rdataset,
   9184   1.9  christos 	       dns_rdataset_t *p2rdataset, dns_rdataset_t *sigp2rdataset) {
   9185   1.1  christos 	dns_rdata_soa_t soa;
   9186   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   9187   1.1  christos 	dns_ttl_t ttl;
   9188   1.1  christos 	isc_result_t result;
   9189   1.1  christos 
   9190   1.1  christos 	REQUIRE(soardataset != NULL);
   9191   1.1  christos 	REQUIRE(sigsoardataset != NULL);
   9192   1.1  christos 	REQUIRE(p1rdataset != NULL);
   9193   1.1  christos 	REQUIRE(sigp1rdataset != NULL);
   9194   1.1  christos 
   9195   1.1  christos 	result = dns_rdataset_first(soardataset);
   9196   1.1  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9197   1.1  christos 	dns_rdataset_current(soardataset, &rdata);
   9198   1.3  christos 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   9199   1.3  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9200   1.1  christos 
   9201   1.1  christos 	ttl = ISC_MIN(soa.minimum, soardataset->ttl);
   9202   1.1  christos 	ttl = ISC_MIN(ttl, sigsoardataset->ttl);
   9203   1.1  christos 	ttl = ISC_MIN(ttl, p1rdataset->ttl);
   9204   1.1  christos 	ttl = ISC_MIN(ttl, sigp1rdataset->ttl);
   9205   1.9  christos 	if (p2rdataset != NULL) {
   9206   1.1  christos 		ttl = ISC_MIN(ttl, p2rdataset->ttl);
   9207   1.9  christos 	}
   9208   1.9  christos 	if (sigp2rdataset != NULL) {
   9209   1.1  christos 		ttl = ISC_MIN(ttl, sigp2rdataset->ttl);
   9210   1.9  christos 	}
   9211   1.1  christos 
   9212   1.1  christos 	return (ttl);
   9213   1.1  christos }
   9214   1.1  christos 
   9215   1.1  christos /*
   9216   1.1  christos  * Synthesize a NODATA response from the SOA and covering NSEC in cache.
   9217   1.1  christos  */
   9218   1.1  christos static isc_result_t
   9219   1.1  christos query_synthnodata(query_ctx_t *qctx, const dns_name_t *signer,
   9220   1.1  christos 		  dns_rdataset_t **soardatasetp,
   9221   1.9  christos 		  dns_rdataset_t **sigsoardatasetp) {
   9222   1.1  christos 	dns_name_t *name = NULL;
   9223   1.1  christos 	dns_ttl_t ttl;
   9224   1.1  christos 	isc_buffer_t *dbuf, b;
   9225   1.1  christos 	isc_result_t result;
   9226   1.1  christos 
   9227   1.1  christos 	/*
   9228   1.9  christos 	 * Determine the correct TTL to use for the SOA and RRSIG
   9229   1.1  christos 	 */
   9230   1.9  christos 	ttl = query_synthttl(*soardatasetp, *sigsoardatasetp, qctx->rdataset,
   9231   1.9  christos 			     qctx->sigrdataset, NULL, NULL);
   9232   1.1  christos 	(*soardatasetp)->ttl = (*sigsoardatasetp)->ttl = ttl;
   9233   1.1  christos 
   9234   1.1  christos 	/*
   9235   1.1  christos 	 * We want the SOA record to be first, so save the
   9236   1.1  christos 	 * NODATA proof's name now or else discard it.
   9237   1.1  christos 	 */
   9238   1.1  christos 	if (WANTDNSSEC(qctx->client)) {
   9239   1.3  christos 		ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
   9240   1.1  christos 	} else {
   9241   1.3  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   9242   1.1  christos 	}
   9243   1.1  christos 
   9244   1.3  christos 	dbuf = ns_client_getnamebuf(qctx->client);
   9245   1.1  christos 	if (dbuf == NULL) {
   9246   1.1  christos 		result = ISC_R_NOMEMORY;
   9247   1.1  christos 		goto cleanup;
   9248   1.1  christos 	}
   9249   1.1  christos 
   9250   1.3  christos 	name = ns_client_newname(qctx->client, dbuf, &b);
   9251   1.1  christos 	if (name == NULL) {
   9252   1.1  christos 		result = ISC_R_NOMEMORY;
   9253   1.1  christos 		goto cleanup;
   9254   1.1  christos 	}
   9255   1.1  christos 
   9256   1.8  christos 	dns_name_copynf(signer, name);
   9257   1.1  christos 
   9258   1.1  christos 	/*
   9259   1.1  christos 	 * Add SOA record. Omit the RRSIG if DNSSEC was not requested.
   9260   1.1  christos 	 */
   9261   1.1  christos 	if (!WANTDNSSEC(qctx->client)) {
   9262   1.1  christos 		sigsoardatasetp = NULL;
   9263   1.1  christos 	}
   9264   1.9  christos 	query_addrrset(qctx, &name, soardatasetp, sigsoardatasetp, dbuf,
   9265   1.9  christos 		       DNS_SECTION_AUTHORITY);
   9266   1.1  christos 
   9267   1.1  christos 	if (WANTDNSSEC(qctx->client)) {
   9268   1.1  christos 		/*
   9269   1.1  christos 		 * Add NODATA proof.
   9270   1.1  christos 		 */
   9271   1.9  christos 		query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
   9272   1.9  christos 			       &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY);
   9273   1.1  christos 	}
   9274   1.1  christos 
   9275   1.1  christos 	result = ISC_R_SUCCESS;
   9276   1.1  christos 	inc_stats(qctx->client, ns_statscounter_nodatasynth);
   9277   1.1  christos 
   9278   1.1  christos cleanup:
   9279   1.1  christos 	if (name != NULL) {
   9280   1.3  christos 		ns_client_releasename(qctx->client, &name);
   9281   1.1  christos 	}
   9282   1.1  christos 	return (result);
   9283   1.1  christos }
   9284   1.1  christos 
   9285   1.1  christos /*
   9286   1.1  christos  * Synthesize a wildcard answer using the contents of 'rdataset'.
   9287   1.1  christos  * qctx contains the NODATA proof.
   9288   1.1  christos  */
   9289   1.1  christos static isc_result_t
   9290   1.1  christos query_synthwildcard(query_ctx_t *qctx, dns_rdataset_t *rdataset,
   9291   1.9  christos 		    dns_rdataset_t *sigrdataset) {
   9292   1.1  christos 	dns_name_t *name = NULL;
   9293   1.1  christos 	isc_buffer_t *dbuf, b;
   9294   1.1  christos 	isc_result_t result;
   9295   1.3  christos 	dns_rdataset_t *cloneset = NULL, *clonesigset = NULL;
   9296   1.1  christos 	dns_rdataset_t **sigrdatasetp;
   9297   1.1  christos 
   9298   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_synthwildcard");
   9299   1.9  christos 
   9300   1.1  christos 	/*
   9301   1.1  christos 	 * We want the answer to be first, so save the
   9302   1.1  christos 	 * NOQNAME proof's name now or else discard it.
   9303   1.1  christos 	 */
   9304   1.1  christos 	if (WANTDNSSEC(qctx->client)) {
   9305   1.3  christos 		ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
   9306   1.1  christos 	} else {
   9307   1.3  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   9308   1.1  christos 	}
   9309   1.1  christos 
   9310   1.3  christos 	dbuf = ns_client_getnamebuf(qctx->client);
   9311   1.1  christos 	if (dbuf == NULL) {
   9312   1.1  christos 		result = ISC_R_NOMEMORY;
   9313   1.1  christos 		goto cleanup;
   9314   1.1  christos 	}
   9315   1.1  christos 
   9316   1.3  christos 	name = ns_client_newname(qctx->client, dbuf, &b);
   9317   1.1  christos 	if (name == NULL) {
   9318   1.1  christos 		result = ISC_R_NOMEMORY;
   9319   1.1  christos 		goto cleanup;
   9320   1.1  christos 	}
   9321   1.8  christos 	dns_name_copynf(qctx->client->query.qname, name);
   9322   1.1  christos 
   9323   1.3  christos 	cloneset = ns_client_newrdataset(qctx->client);
   9324   1.3  christos 	if (cloneset == NULL) {
   9325   1.1  christos 		result = ISC_R_NOMEMORY;
   9326   1.1  christos 		goto cleanup;
   9327   1.1  christos 	}
   9328   1.3  christos 	dns_rdataset_clone(rdataset, cloneset);
   9329   1.1  christos 
   9330   1.1  christos 	/*
   9331   1.1  christos 	 * Add answer RRset. Omit the RRSIG if DNSSEC was not requested.
   9332   1.1  christos 	 */
   9333   1.1  christos 	if (WANTDNSSEC(qctx->client)) {
   9334   1.3  christos 		clonesigset = ns_client_newrdataset(qctx->client);
   9335   1.3  christos 		if (clonesigset == NULL) {
   9336   1.1  christos 			result = ISC_R_NOMEMORY;
   9337   1.1  christos 			goto cleanup;
   9338   1.1  christos 		}
   9339   1.3  christos 		dns_rdataset_clone(sigrdataset, clonesigset);
   9340   1.3  christos 		sigrdatasetp = &clonesigset;
   9341   1.1  christos 	} else {
   9342   1.1  christos 		sigrdatasetp = NULL;
   9343   1.1  christos 	}
   9344   1.1  christos 
   9345   1.9  christos 	query_addrrset(qctx, &name, &cloneset, sigrdatasetp, dbuf,
   9346   1.9  christos 		       DNS_SECTION_ANSWER);
   9347   1.1  christos 
   9348   1.1  christos 	if (WANTDNSSEC(qctx->client)) {
   9349   1.1  christos 		/*
   9350   1.1  christos 		 * Add NOQNAME proof.
   9351   1.1  christos 		 */
   9352   1.9  christos 		query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
   9353   1.9  christos 			       &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY);
   9354   1.1  christos 	}
   9355   1.1  christos 
   9356   1.1  christos 	result = ISC_R_SUCCESS;
   9357   1.1  christos 	inc_stats(qctx->client, ns_statscounter_wildcardsynth);
   9358   1.1  christos 
   9359   1.1  christos cleanup:
   9360   1.1  christos 	if (name != NULL) {
   9361   1.3  christos 		ns_client_releasename(qctx->client, &name);
   9362   1.1  christos 	}
   9363   1.3  christos 	if (cloneset != NULL) {
   9364   1.3  christos 		ns_client_putrdataset(qctx->client, &cloneset);
   9365   1.1  christos 	}
   9366   1.3  christos 	if (clonesigset != NULL) {
   9367   1.3  christos 		ns_client_putrdataset(qctx->client, &clonesigset);
   9368   1.1  christos 	}
   9369   1.1  christos 	return (result);
   9370   1.1  christos }
   9371   1.1  christos 
   9372   1.1  christos /*
   9373   1.1  christos  * Add a synthesized CNAME record from the wildard RRset (rdataset)
   9374   1.1  christos  * and NODATA proof by calling query_synthwildcard then setup to
   9375   1.1  christos  * follow the CNAME.
   9376   1.1  christos  */
   9377   1.1  christos static isc_result_t
   9378   1.1  christos query_synthcnamewildcard(query_ctx_t *qctx, dns_rdataset_t *rdataset,
   9379   1.9  christos 			 dns_rdataset_t *sigrdataset) {
   9380   1.1  christos 	isc_result_t result;
   9381   1.1  christos 	dns_name_t *tname = NULL;
   9382   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   9383   1.1  christos 	dns_rdata_cname_t cname;
   9384   1.1  christos 
   9385   1.1  christos 	result = query_synthwildcard(qctx, rdataset, sigrdataset);
   9386   1.1  christos 	if (result != ISC_R_SUCCESS) {
   9387   1.1  christos 		return (result);
   9388   1.1  christos 	}
   9389   1.1  christos 
   9390   1.1  christos 	qctx->client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
   9391   1.1  christos 
   9392   1.1  christos 	/*
   9393   1.1  christos 	 * Reset qname to be the target name of the CNAME and restart
   9394   1.1  christos 	 * the query.
   9395   1.1  christos 	 */
   9396   1.1  christos 	result = dns_message_gettempname(qctx->client->message, &tname);
   9397   1.1  christos 	if (result != ISC_R_SUCCESS) {
   9398   1.1  christos 		return (result);
   9399   1.1  christos 	}
   9400   1.1  christos 
   9401   1.1  christos 	result = dns_rdataset_first(rdataset);
   9402   1.1  christos 	if (result != ISC_R_SUCCESS) {
   9403   1.1  christos 		dns_message_puttempname(qctx->client->message, &tname);
   9404   1.1  christos 		return (result);
   9405   1.1  christos 	}
   9406   1.1  christos 
   9407   1.1  christos 	dns_rdataset_current(rdataset, &rdata);
   9408   1.1  christos 	result = dns_rdata_tostruct(&rdata, &cname, NULL);
   9409   1.3  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9410   1.1  christos 	dns_rdata_reset(&rdata);
   9411   1.1  christos 
   9412   1.1  christos 	dns_name_init(tname, NULL);
   9413   1.9  christos 	dns_name_dup(&cname.cname, qctx->client->mctx, tname);
   9414   1.1  christos 
   9415   1.1  christos 	dns_rdata_freestruct(&cname);
   9416   1.1  christos 	ns_client_qnamereplace(qctx->client, tname);
   9417   1.3  christos 	qctx->want_restart = true;
   9418   1.1  christos 	if (!WANTRECURSION(qctx->client)) {
   9419   1.1  christos 		qctx->options |= DNS_GETDB_NOLOG;
   9420   1.1  christos 	}
   9421   1.1  christos 
   9422   1.1  christos 	return (result);
   9423   1.1  christos }
   9424   1.1  christos 
   9425   1.1  christos /*
   9426   1.1  christos  * Synthesize a NXDOMAIN response from qctx (which contains the
   9427   1.1  christos  * NODATA proof), nowild + nowildrdataset + signowildrdataset (which
   9428   1.1  christos  * contains the NOWILDCARD proof) and signer + soardatasetp + sigsoardatasetp
   9429   1.1  christos  * which contain the SOA record + RRSIG for the negative answer.
   9430   1.1  christos  */
   9431   1.1  christos static isc_result_t
   9432   1.9  christos query_synthnxdomain(query_ctx_t *qctx, dns_name_t *nowild,
   9433   1.1  christos 		    dns_rdataset_t *nowildrdataset,
   9434   1.9  christos 		    dns_rdataset_t *signowildrdataset, dns_name_t *signer,
   9435   1.1  christos 		    dns_rdataset_t **soardatasetp,
   9436   1.9  christos 		    dns_rdataset_t **sigsoardatasetp) {
   9437   1.1  christos 	dns_name_t *name = NULL;
   9438   1.1  christos 	dns_ttl_t ttl;
   9439   1.1  christos 	isc_buffer_t *dbuf, b;
   9440   1.1  christos 	isc_result_t result;
   9441   1.3  christos 	dns_rdataset_t *cloneset = NULL, *clonesigset = NULL;
   9442   1.1  christos 
   9443   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_synthnxdomain");
   9444   1.9  christos 
   9445   1.1  christos 	/*
   9446   1.9  christos 	 * Determine the correct TTL to use for the SOA and RRSIG
   9447   1.1  christos 	 */
   9448   1.9  christos 	ttl = query_synthttl(*soardatasetp, *sigsoardatasetp, qctx->rdataset,
   9449   1.9  christos 			     qctx->sigrdataset, nowildrdataset,
   9450   1.9  christos 			     signowildrdataset);
   9451   1.1  christos 	(*soardatasetp)->ttl = (*sigsoardatasetp)->ttl = ttl;
   9452   1.1  christos 
   9453   1.1  christos 	/*
   9454   1.1  christos 	 * We want the SOA record to be first, so save the
   9455   1.1  christos 	 * NOQNAME proof's name now or else discard it.
   9456   1.1  christos 	 */
   9457   1.1  christos 	if (WANTDNSSEC(qctx->client)) {
   9458   1.3  christos 		ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
   9459   1.1  christos 	} else {
   9460   1.3  christos 		ns_client_releasename(qctx->client, &qctx->fname);
   9461   1.1  christos 	}
   9462   1.1  christos 
   9463   1.3  christos 	dbuf = ns_client_getnamebuf(qctx->client);
   9464   1.1  christos 	if (dbuf == NULL) {
   9465   1.1  christos 		result = ISC_R_NOMEMORY;
   9466   1.1  christos 		goto cleanup;
   9467   1.1  christos 	}
   9468   1.1  christos 
   9469   1.3  christos 	name = ns_client_newname(qctx->client, dbuf, &b);
   9470   1.1  christos 	if (name == NULL) {
   9471   1.1  christos 		result = ISC_R_NOMEMORY;
   9472   1.1  christos 		goto cleanup;
   9473   1.1  christos 	}
   9474   1.1  christos 
   9475   1.8  christos 	dns_name_copynf(signer, name);
   9476   1.1  christos 
   9477   1.1  christos 	/*
   9478   1.1  christos 	 * Add SOA record. Omit the RRSIG if DNSSEC was not requested.
   9479   1.1  christos 	 */
   9480   1.1  christos 	if (!WANTDNSSEC(qctx->client)) {
   9481   1.1  christos 		sigsoardatasetp = NULL;
   9482   1.1  christos 	}
   9483   1.9  christos 	query_addrrset(qctx, &name, soardatasetp, sigsoardatasetp, dbuf,
   9484   1.9  christos 		       DNS_SECTION_AUTHORITY);
   9485   1.1  christos 
   9486   1.1  christos 	if (WANTDNSSEC(qctx->client)) {
   9487   1.1  christos 		/*
   9488   1.1  christos 		 * Add NOQNAME proof.
   9489   1.1  christos 		 */
   9490   1.9  christos 		query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
   9491   1.9  christos 			       &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY);
   9492   1.1  christos 
   9493   1.3  christos 		dbuf = ns_client_getnamebuf(qctx->client);
   9494   1.1  christos 		if (dbuf == NULL) {
   9495   1.1  christos 			result = ISC_R_NOMEMORY;
   9496   1.1  christos 			goto cleanup;
   9497   1.1  christos 		}
   9498   1.1  christos 
   9499   1.3  christos 		name = ns_client_newname(qctx->client, dbuf, &b);
   9500   1.1  christos 		if (name == NULL) {
   9501   1.1  christos 			result = ISC_R_NOMEMORY;
   9502   1.1  christos 			goto cleanup;
   9503   1.1  christos 		}
   9504   1.1  christos 
   9505   1.8  christos 		dns_name_copynf(nowild, name);
   9506   1.1  christos 
   9507   1.3  christos 		cloneset = ns_client_newrdataset(qctx->client);
   9508   1.3  christos 		clonesigset = ns_client_newrdataset(qctx->client);
   9509   1.3  christos 		if (cloneset == NULL || clonesigset == NULL) {
   9510   1.1  christos 			result = ISC_R_NOMEMORY;
   9511   1.1  christos 			goto cleanup;
   9512   1.1  christos 		}
   9513   1.1  christos 
   9514   1.3  christos 		dns_rdataset_clone(nowildrdataset, cloneset);
   9515   1.3  christos 		dns_rdataset_clone(signowildrdataset, clonesigset);
   9516   1.1  christos 
   9517   1.1  christos 		/*
   9518   1.1  christos 		 * Add NOWILDCARD proof.
   9519   1.1  christos 		 */
   9520   1.9  christos 		query_addrrset(qctx, &name, &cloneset, &clonesigset, dbuf,
   9521   1.9  christos 			       DNS_SECTION_AUTHORITY);
   9522   1.1  christos 	}
   9523   1.1  christos 
   9524   1.1  christos 	qctx->client->message->rcode = dns_rcode_nxdomain;
   9525   1.1  christos 	result = ISC_R_SUCCESS;
   9526   1.1  christos 	inc_stats(qctx->client, ns_statscounter_nxdomainsynth);
   9527   1.1  christos 
   9528   1.1  christos cleanup:
   9529   1.1  christos 	if (name != NULL) {
   9530   1.3  christos 		ns_client_releasename(qctx->client, &name);
   9531   1.1  christos 	}
   9532   1.3  christos 	if (cloneset != NULL) {
   9533   1.3  christos 		ns_client_putrdataset(qctx->client, &cloneset);
   9534   1.1  christos 	}
   9535   1.3  christos 	if (clonesigset != NULL) {
   9536   1.3  christos 		ns_client_putrdataset(qctx->client, &clonesigset);
   9537   1.1  christos 	}
   9538   1.1  christos 	return (result);
   9539   1.1  christos }
   9540   1.1  christos 
   9541   1.1  christos /*
   9542   1.1  christos  * Check that all signer names in sigrdataset match the expected signer.
   9543   1.1  christos  */
   9544   1.1  christos static isc_result_t
   9545   1.1  christos checksignames(dns_name_t *signer, dns_rdataset_t *sigrdataset) {
   9546   1.1  christos 	isc_result_t result;
   9547   1.1  christos 
   9548   1.9  christos 	for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS;
   9549   1.9  christos 	     result = dns_rdataset_next(sigrdataset))
   9550   1.9  christos 	{
   9551   1.1  christos 		dns_rdata_t rdata = DNS_RDATA_INIT;
   9552   1.1  christos 		dns_rdata_rrsig_t rrsig;
   9553   1.1  christos 
   9554   1.1  christos 		dns_rdataset_current(sigrdataset, &rdata);
   9555   1.1  christos 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   9556   1.1  christos 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9557   1.1  christos 		if (dns_name_countlabels(signer) == 0) {
   9558   1.8  christos 			dns_name_copynf(&rrsig.signer, signer);
   9559   1.1  christos 		} else if (!dns_name_equal(signer, &rrsig.signer)) {
   9560   1.1  christos 			return (ISC_R_FAILURE);
   9561   1.1  christos 		}
   9562   1.1  christos 	}
   9563   1.1  christos 
   9564   1.1  christos 	return (ISC_R_SUCCESS);
   9565   1.1  christos }
   9566   1.1  christos 
   9567   1.1  christos /*%
   9568   1.1  christos  * Handle covering NSEC responses.
   9569   1.1  christos  *
   9570   1.9  christos  * Verify the NSEC record is appropriate for the QNAME; if not,
   9571   1.1  christos  * redo the initial query without DNS_DBFIND_COVERINGNSEC.
   9572   1.1  christos  *
   9573   1.1  christos  * If the covering NSEC proves that the name exists but not the type,
   9574   1.1  christos  * synthesize a NODATA response.
   9575   1.1  christos  *
   9576   1.1  christos  * If the name doesn't exist, compute the wildcard record and check whether
   9577   1.1  christos  * the wildcard name exists or not.  If we can't determine this, redo the
   9578   1.1  christos  * initial query without DNS_DBFIND_COVERINGNSEC.
   9579   1.1  christos  *
   9580   1.1  christos  * If the wildcard name does not exist, compute the SOA name and look that
   9581   1.1  christos  * up.  If the SOA record does not exist, redo the initial query without
   9582   1.1  christos  * DNS_DBFIND_COVERINGNSEC.  If the SOA record exists, synthesize an
   9583   1.1  christos  * NXDOMAIN response from the found records.
   9584   1.1  christos  *
   9585   1.1  christos  * If the wildcard name does exist, perform a lookup for the requested
   9586   1.1  christos  * type at the wildcard name.
   9587   1.1  christos  */
   9588   1.1  christos static isc_result_t
   9589   1.1  christos query_coveringnsec(query_ctx_t *qctx) {
   9590   1.1  christos 	dns_db_t *db = NULL;
   9591   1.1  christos 	dns_clientinfo_t ci;
   9592   1.1  christos 	dns_clientinfomethods_t cm;
   9593   1.1  christos 	dns_dbnode_t *node = NULL;
   9594   1.1  christos 	dns_fixedname_t fixed;
   9595   1.1  christos 	dns_fixedname_t fnowild;
   9596   1.1  christos 	dns_fixedname_t fsigner;
   9597   1.1  christos 	dns_fixedname_t fwild;
   9598   1.1  christos 	dns_name_t *fname = NULL;
   9599   1.1  christos 	dns_name_t *nowild = NULL;
   9600   1.1  christos 	dns_name_t *signer = NULL;
   9601   1.1  christos 	dns_name_t *wild = NULL;
   9602   1.1  christos 	dns_rdataset_t *soardataset = NULL, *sigsoardataset = NULL;
   9603   1.1  christos 	dns_rdataset_t rdataset, sigrdataset;
   9604   1.3  christos 	bool done = false;
   9605   1.3  christos 	bool exists = true, data = true;
   9606   1.3  christos 	bool redirected = false;
   9607   1.1  christos 	isc_result_t result = ISC_R_SUCCESS;
   9608   1.1  christos 	unsigned int dboptions = qctx->client->query.dboptions;
   9609   1.1  christos 
   9610   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_coveringnsec");
   9611   1.9  christos 
   9612   1.1  christos 	dns_rdataset_init(&rdataset);
   9613   1.1  christos 	dns_rdataset_init(&sigrdataset);
   9614   1.1  christos 
   9615   1.1  christos 	/*
   9616   1.1  christos 	 * If we have no signer name, stop immediately.
   9617   1.1  christos 	 */
   9618   1.1  christos 	if (!dns_rdataset_isassociated(qctx->sigrdataset)) {
   9619   1.1  christos 		goto cleanup;
   9620   1.1  christos 	}
   9621   1.1  christos 
   9622   1.1  christos 	wild = dns_fixedname_initname(&fwild);
   9623   1.1  christos 	fname = dns_fixedname_initname(&fixed);
   9624   1.1  christos 	signer = dns_fixedname_initname(&fsigner);
   9625   1.1  christos 	nowild = dns_fixedname_initname(&fnowild);
   9626   1.1  christos 
   9627   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   9628   1.1  christos 	dns_clientinfo_init(&ci, qctx->client, NULL);
   9629   1.1  christos 
   9630   1.1  christos 	/*
   9631   1.1  christos 	 * All signer names must be the same to accept.
   9632   1.1  christos 	 */
   9633   1.1  christos 	result = checksignames(signer, qctx->sigrdataset);
   9634   1.1  christos 	if (result != ISC_R_SUCCESS) {
   9635   1.1  christos 		result = ISC_R_SUCCESS;
   9636   1.1  christos 		goto cleanup;
   9637   1.1  christos 	}
   9638   1.1  christos 
   9639   1.1  christos 	/*
   9640   1.1  christos 	 * Check that we have the correct NOQNAME NSEC record.
   9641   1.1  christos 	 */
   9642   1.1  christos 	result = dns_nsec_noexistnodata(qctx->qtype, qctx->client->query.qname,
   9643   1.9  christos 					qctx->fname, qctx->rdataset, &exists,
   9644   1.9  christos 					&data, wild, log_noexistnodata, qctx);
   9645   1.1  christos 
   9646   1.1  christos 	if (result != ISC_R_SUCCESS || (exists && data)) {
   9647   1.1  christos 		goto cleanup;
   9648   1.1  christos 	}
   9649   1.1  christos 
   9650   1.1  christos 	if (exists) {
   9651   1.9  christos 		if (qctx->type == dns_rdatatype_any) { /* XXX not yet */
   9652   1.1  christos 			goto cleanup;
   9653   1.1  christos 		}
   9654   1.3  christos 		if (!ISC_LIST_EMPTY(qctx->view->dns64) &&
   9655   1.1  christos 		    (qctx->type == dns_rdatatype_a ||
   9656   1.1  christos 		     qctx->type == dns_rdatatype_aaaa)) /* XXX not yet */
   9657   1.1  christos 		{
   9658   1.1  christos 			goto cleanup;
   9659   1.1  christos 		}
   9660   1.1  christos 		if (!qctx->resuming && !STALE(qctx->rdataset) &&
   9661   1.1  christos 		    qctx->rdataset->ttl == 0 && RECURSIONOK(qctx->client))
   9662   1.1  christos 		{
   9663   1.1  christos 			goto cleanup;
   9664   1.1  christos 		}
   9665   1.1  christos 
   9666   1.3  christos 		soardataset = ns_client_newrdataset(qctx->client);
   9667   1.3  christos 		sigsoardataset = ns_client_newrdataset(qctx->client);
   9668   1.1  christos 		if (soardataset == NULL || sigsoardataset == NULL) {
   9669   1.1  christos 			goto cleanup;
   9670   1.1  christos 		}
   9671   1.1  christos 
   9672   1.1  christos 		/*
   9673   1.1  christos 		 * Look for SOA record to construct NODATA response.
   9674   1.1  christos 		 */
   9675   1.1  christos 		dns_db_attach(qctx->db, &db);
   9676   1.1  christos 		result = dns_db_findext(db, signer, qctx->version,
   9677   1.1  christos 					dns_rdatatype_soa, dboptions,
   9678   1.9  christos 					qctx->client->now, &node, fname, &cm,
   9679   1.9  christos 					&ci, soardataset, sigsoardataset);
   9680   1.1  christos 
   9681   1.1  christos 		if (result != ISC_R_SUCCESS) {
   9682   1.1  christos 			goto cleanup;
   9683   1.1  christos 		}
   9684   1.9  christos 		(void)query_synthnodata(qctx, signer, &soardataset,
   9685   1.9  christos 					&sigsoardataset);
   9686   1.3  christos 		done = true;
   9687   1.1  christos 		goto cleanup;
   9688   1.1  christos 	}
   9689   1.1  christos 
   9690   1.1  christos 	/*
   9691   1.1  christos 	 * Look up the no-wildcard proof.
   9692   1.1  christos 	 */
   9693   1.1  christos 	dns_db_attach(qctx->db, &db);
   9694   1.1  christos 	result = dns_db_findext(db, wild, qctx->version, qctx->type,
   9695   1.1  christos 				dboptions | DNS_DBFIND_COVERINGNSEC,
   9696   1.9  christos 				qctx->client->now, &node, nowild, &cm, &ci,
   9697   1.9  christos 				&rdataset, &sigrdataset);
   9698   1.1  christos 
   9699   1.1  christos 	if (rdataset.trust != dns_trust_secure ||
   9700   1.9  christos 	    sigrdataset.trust != dns_trust_secure) {
   9701   1.1  christos 		goto cleanup;
   9702   1.1  christos 	}
   9703   1.1  christos 
   9704   1.1  christos 	/*
   9705   1.1  christos 	 * Zero TTL handling of wildcard record.
   9706   1.1  christos 	 *
   9707   1.3  christos 	 * We don't yet have code to handle synthesis and type ANY or dns64
   9708   1.3  christos 	 * processing so we abort the synthesis here if there would be a
   9709   1.3  christos 	 * interaction.
   9710   1.1  christos 	 */
   9711   1.1  christos 	switch (result) {
   9712   1.1  christos 	case ISC_R_SUCCESS:
   9713   1.9  christos 		if (qctx->type == dns_rdatatype_any) { /* XXX not yet */
   9714   1.1  christos 			goto cleanup;
   9715   1.1  christos 		}
   9716   1.3  christos 		if (!ISC_LIST_EMPTY(qctx->view->dns64) &&
   9717   1.1  christos 		    (qctx->type == dns_rdatatype_a ||
   9718   1.1  christos 		     qctx->type == dns_rdatatype_aaaa)) /* XXX not yet */
   9719   1.1  christos 		{
   9720   1.1  christos 			goto cleanup;
   9721   1.1  christos 		}
   9722   1.9  christos 	/* FALLTHROUGH */
   9723   1.1  christos 	case DNS_R_CNAME:
   9724   1.9  christos 		if (!qctx->resuming && !STALE(&rdataset) && rdataset.ttl == 0 &&
   9725   1.9  christos 		    RECURSIONOK(qctx->client))
   9726   1.1  christos 		{
   9727   1.1  christos 			goto cleanup;
   9728   1.1  christos 		}
   9729   1.1  christos 	default:
   9730   1.1  christos 		break;
   9731   1.1  christos 	}
   9732   1.1  christos 
   9733   1.1  christos 	switch (result) {
   9734   1.1  christos 	case DNS_R_COVERINGNSEC:
   9735   1.9  christos 		result = dns_nsec_noexistnodata(qctx->qtype, wild, nowild,
   9736   1.9  christos 						&rdataset, &exists, &data, NULL,
   9737   1.1  christos 						log_noexistnodata, qctx);
   9738   1.1  christos 		if (result != ISC_R_SUCCESS || exists) {
   9739   1.1  christos 			goto cleanup;
   9740   1.1  christos 		}
   9741   1.1  christos 		break;
   9742   1.9  christos 	case ISC_R_SUCCESS: /* wild card match */
   9743   1.1  christos 		(void)query_synthwildcard(qctx, &rdataset, &sigrdataset);
   9744   1.3  christos 		done = true;
   9745   1.1  christos 		goto cleanup;
   9746   1.9  christos 	case DNS_R_CNAME: /* wild card cname */
   9747   1.1  christos 		(void)query_synthcnamewildcard(qctx, &rdataset, &sigrdataset);
   9748   1.3  christos 		done = true;
   9749   1.1  christos 		goto cleanup;
   9750   1.9  christos 	case DNS_R_NCACHENXRRSET:  /* wild card nodata */
   9751   1.9  christos 	case DNS_R_NCACHENXDOMAIN: /* direct nxdomain */
   9752   1.1  christos 	default:
   9753   1.1  christos 		goto cleanup;
   9754   1.1  christos 	}
   9755   1.1  christos 
   9756   1.1  christos 	/*
   9757   1.1  christos 	 * We now have the proof that we have an NXDOMAIN.  Apply
   9758   1.1  christos 	 * NXDOMAIN redirection if configured.
   9759   1.1  christos 	 */
   9760   1.1  christos 	result = query_redirect(qctx);
   9761   1.1  christos 	if (result != ISC_R_COMPLETE) {
   9762   1.3  christos 		redirected = true;
   9763   1.1  christos 		goto cleanup;
   9764   1.1  christos 	}
   9765   1.1  christos 
   9766   1.1  christos 	/*
   9767   1.1  christos 	 * Must be signed to accept.
   9768   1.1  christos 	 */
   9769   1.1  christos 	if (!dns_rdataset_isassociated(&sigrdataset)) {
   9770   1.1  christos 		goto cleanup;
   9771   1.1  christos 	}
   9772   1.1  christos 
   9773   1.1  christos 	/*
   9774   1.1  christos 	 * Check signer signer names again.
   9775   1.1  christos 	 */
   9776   1.1  christos 	result = checksignames(signer, &sigrdataset);
   9777   1.1  christos 	if (result != ISC_R_SUCCESS) {
   9778   1.1  christos 		result = ISC_R_SUCCESS;
   9779   1.1  christos 		goto cleanup;
   9780   1.1  christos 	}
   9781   1.1  christos 
   9782   1.1  christos 	if (node != NULL) {
   9783   1.1  christos 		dns_db_detachnode(db, &node);
   9784   1.1  christos 	}
   9785   1.1  christos 
   9786   1.3  christos 	soardataset = ns_client_newrdataset(qctx->client);
   9787   1.3  christos 	sigsoardataset = ns_client_newrdataset(qctx->client);
   9788   1.1  christos 	if (soardataset == NULL || sigsoardataset == NULL) {
   9789   1.1  christos 		goto cleanup;
   9790   1.1  christos 	}
   9791   1.1  christos 
   9792   1.1  christos 	/*
   9793   1.1  christos 	 * Look for SOA record to construct NXDOMAIN response.
   9794   1.1  christos 	 */
   9795   1.9  christos 	result = dns_db_findext(db, signer, qctx->version, dns_rdatatype_soa,
   9796   1.9  christos 				dboptions, qctx->client->now, &node, fname, &cm,
   9797   1.9  christos 				&ci, soardataset, sigsoardataset);
   9798   1.1  christos 
   9799   1.1  christos 	if (result != ISC_R_SUCCESS) {
   9800   1.1  christos 		goto cleanup;
   9801   1.1  christos 	}
   9802   1.1  christos 
   9803   1.9  christos 	(void)query_synthnxdomain(qctx, nowild, &rdataset, &sigrdataset, signer,
   9804   1.9  christos 				  &soardataset, &sigsoardataset);
   9805   1.3  christos 	done = true;
   9806   1.1  christos 
   9807   1.9  christos cleanup:
   9808   1.1  christos 	if (dns_rdataset_isassociated(&rdataset)) {
   9809   1.1  christos 		dns_rdataset_disassociate(&rdataset);
   9810   1.1  christos 	}
   9811   1.1  christos 	if (dns_rdataset_isassociated(&sigrdataset)) {
   9812   1.1  christos 		dns_rdataset_disassociate(&sigrdataset);
   9813   1.1  christos 	}
   9814   1.1  christos 	if (soardataset != NULL) {
   9815   1.3  christos 		ns_client_putrdataset(qctx->client, &soardataset);
   9816   1.1  christos 	}
   9817   1.1  christos 	if (sigsoardataset != NULL) {
   9818   1.3  christos 		ns_client_putrdataset(qctx->client, &sigsoardataset);
   9819   1.1  christos 	}
   9820   1.1  christos 	if (db != NULL) {
   9821   1.1  christos 		if (node != NULL) {
   9822   1.1  christos 			dns_db_detachnode(db, &node);
   9823   1.1  christos 		}
   9824   1.1  christos 		dns_db_detach(&db);
   9825   1.1  christos 	}
   9826   1.1  christos 
   9827   1.1  christos 	if (redirected) {
   9828   1.1  christos 		return (result);
   9829   1.1  christos 	}
   9830   1.1  christos 
   9831   1.1  christos 	if (!done) {
   9832   1.1  christos 		/*
   9833   1.1  christos 		 * No covering NSEC was found; proceed with recursion.
   9834   1.1  christos 		 */
   9835   1.3  christos 		qctx->findcoveringnsec = false;
   9836   1.1  christos 		if (qctx->fname != NULL) {
   9837   1.3  christos 			ns_client_releasename(qctx->client, &qctx->fname);
   9838   1.1  christos 		}
   9839   1.1  christos 		if (qctx->node != NULL) {
   9840   1.1  christos 			dns_db_detachnode(qctx->db, &qctx->node);
   9841   1.1  christos 		}
   9842   1.3  christos 		ns_client_putrdataset(qctx->client, &qctx->rdataset);
   9843   1.1  christos 		if (qctx->sigrdataset != NULL) {
   9844   1.3  christos 			ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
   9845   1.1  christos 		}
   9846   1.1  christos 		return (query_lookup(qctx));
   9847   1.1  christos 	}
   9848   1.1  christos 
   9849   1.3  christos 	return (ns_query_done(qctx));
   9850   1.1  christos }
   9851   1.1  christos 
   9852   1.1  christos /*%
   9853   1.1  christos  * Handle negative cache responses, DNS_R_NCACHENXRRSET or
   9854   1.1  christos  * DNS_R_NCACHENXDOMAIN. (Note: may also be called with result
   9855   1.1  christos  * set to DNS_R_NXDOMAIN when handling DNS64 lookups.)
   9856   1.1  christos  */
   9857   1.1  christos static isc_result_t
   9858   1.1  christos query_ncache(query_ctx_t *qctx, isc_result_t result) {
   9859   1.1  christos 	INSIST(!qctx->is_zone);
   9860   1.1  christos 	INSIST(result == DNS_R_NCACHENXDOMAIN ||
   9861   1.9  christos 	       result == DNS_R_NCACHENXRRSET || result == DNS_R_NXDOMAIN);
   9862   1.9  christos 
   9863   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_ncache");
   9864   1.1  christos 
   9865   1.3  christos 	CALL_HOOK(NS_QUERY_NCACHE_BEGIN, qctx);
   9866   1.3  christos 
   9867   1.3  christos 	qctx->authoritative = false;
   9868   1.1  christos 
   9869   1.1  christos 	if (result == DNS_R_NCACHENXDOMAIN) {
   9870   1.1  christos 		/*
   9871   1.1  christos 		 * Set message rcode. (This is not done when
   9872   1.1  christos 		 * result == DNS_R_NXDOMAIN because that means we're
   9873   1.1  christos 		 * being called after a DNS64 lookup and don't want
   9874   1.1  christos 		 * to update the rcode now.)
   9875   1.1  christos 		 */
   9876   1.1  christos 		qctx->client->message->rcode = dns_rcode_nxdomain;
   9877   1.1  christos 
   9878   1.1  christos 		/* Look for RFC 1918 leakage from Internet. */
   9879   1.1  christos 		if (qctx->qtype == dns_rdatatype_ptr &&
   9880   1.1  christos 		    qctx->client->message->rdclass == dns_rdataclass_in &&
   9881   1.1  christos 		    dns_name_countlabels(qctx->fname) == 7)
   9882   1.1  christos 		{
   9883   1.1  christos 			warn_rfc1918(qctx->client, qctx->fname, qctx->rdataset);
   9884   1.1  christos 		}
   9885   1.1  christos 	}
   9886   1.1  christos 
   9887   1.1  christos 	return (query_nodata(qctx, result));
   9888   1.3  christos 
   9889   1.9  christos cleanup:
   9890   1.3  christos 	return (result);
   9891   1.3  christos }
   9892   1.3  christos 
   9893   1.3  christos /*
   9894   1.3  christos  * If we have a zero ttl from the cache, refetch.
   9895   1.3  christos  */
   9896   1.3  christos static isc_result_t
   9897   1.3  christos query_zerottl_refetch(query_ctx_t *qctx) {
   9898   1.3  christos 	isc_result_t result;
   9899   1.3  christos 
   9900   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_zerottl_refetch");
   9901   1.9  christos 
   9902   1.3  christos 	if (qctx->is_zone || qctx->resuming || STALE(qctx->rdataset) ||
   9903   1.3  christos 	    qctx->rdataset->ttl != 0 || !RECURSIONOK(qctx->client))
   9904   1.3  christos 	{
   9905   1.3  christos 		return (ISC_R_COMPLETE);
   9906   1.3  christos 	}
   9907   1.3  christos 
   9908   1.3  christos 	qctx_clean(qctx);
   9909   1.3  christos 
   9910   1.3  christos 	INSIST(!REDIRECT(qctx->client));
   9911   1.3  christos 
   9912   1.3  christos 	result = ns_query_recurse(qctx->client, qctx->qtype,
   9913   1.9  christos 				  qctx->client->query.qname, NULL, NULL,
   9914   1.9  christos 				  qctx->resuming);
   9915   1.3  christos 	if (result == ISC_R_SUCCESS) {
   9916   1.3  christos 		CALL_HOOK(NS_QUERY_ZEROTTL_RECURSE, qctx);
   9917   1.9  christos 		qctx->client->query.attributes |= NS_QUERYATTR_RECURSING;
   9918   1.3  christos 
   9919   1.3  christos 		if (qctx->dns64) {
   9920   1.9  christos 			qctx->client->query.attributes |= NS_QUERYATTR_DNS64;
   9921   1.3  christos 		}
   9922   1.3  christos 		if (qctx->dns64_exclude) {
   9923   1.3  christos 			qctx->client->query.attributes |=
   9924   1.3  christos 				NS_QUERYATTR_DNS64EXCLUDE;
   9925   1.3  christos 		}
   9926   1.3  christos 	} else {
   9927   1.3  christos 		QUERY_ERROR(qctx, result);
   9928   1.3  christos 	}
   9929   1.3  christos 
   9930   1.3  christos 	return (ns_query_done(qctx));
   9931   1.3  christos 
   9932   1.9  christos cleanup:
   9933   1.3  christos 	return (result);
   9934   1.1  christos }
   9935   1.1  christos 
   9936   1.1  christos /*
   9937   1.1  christos  * Handle CNAME responses.
   9938   1.1  christos  */
   9939   1.1  christos static isc_result_t
   9940   1.1  christos query_cname(query_ctx_t *qctx) {
   9941   1.1  christos 	isc_result_t result;
   9942   1.1  christos 	dns_name_t *tname;
   9943   1.1  christos 	dns_rdataset_t *trdataset;
   9944   1.1  christos 	dns_rdataset_t **sigrdatasetp = NULL;
   9945   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   9946   1.1  christos 	dns_rdata_cname_t cname;
   9947   1.1  christos 
   9948   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_cname");
   9949   1.9  christos 
   9950   1.3  christos 	CALL_HOOK(NS_QUERY_CNAME_BEGIN, qctx);
   9951   1.1  christos 
   9952   1.3  christos 	result = query_zerottl_refetch(qctx);
   9953   1.3  christos 	if (result != ISC_R_COMPLETE) {
   9954   1.3  christos 		return (result);
   9955   1.1  christos 	}
   9956   1.1  christos 
   9957   1.1  christos 	/*
   9958   1.1  christos 	 * Keep a copy of the rdataset.  We have to do this because
   9959   1.1  christos 	 * query_addrrset may clear 'rdataset' (to prevent the
   9960   1.1  christos 	 * cleanup code from cleaning it up).
   9961   1.1  christos 	 */
   9962   1.1  christos 	trdataset = qctx->rdataset;
   9963   1.1  christos 
   9964   1.1  christos 	/*
   9965   1.1  christos 	 * Add the CNAME to the answer section.
   9966   1.1  christos 	 */
   9967   1.9  christos 	if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) {
   9968   1.1  christos 		sigrdatasetp = &qctx->sigrdataset;
   9969   1.9  christos 	}
   9970   1.1  christos 
   9971   1.1  christos 	if (WANTDNSSEC(qctx->client) &&
   9972   1.1  christos 	    (qctx->fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
   9973   1.1  christos 	{
   9974   1.1  christos 		dns_fixedname_init(&qctx->wildcardname);
   9975   1.8  christos 		dns_name_copynf(qctx->fname,
   9976   1.9  christos 				dns_fixedname_name(&qctx->wildcardname));
   9977   1.3  christos 		qctx->need_wildcardproof = true;
   9978   1.1  christos 	}
   9979   1.1  christos 
   9980   1.1  christos 	if (NOQNAME(qctx->rdataset) && WANTDNSSEC(qctx->client)) {
   9981   1.1  christos 		qctx->noqname = qctx->rdataset;
   9982   1.1  christos 	} else {
   9983   1.1  christos 		qctx->noqname = NULL;
   9984   1.1  christos 	}
   9985   1.1  christos 
   9986   1.9  christos 	if (!qctx->is_zone && RECURSIONOK(qctx->client)) {
   9987   1.1  christos 		query_prefetch(qctx->client, qctx->fname, qctx->rdataset);
   9988   1.9  christos 	}
   9989   1.1  christos 
   9990   1.9  christos 	query_addrrset(qctx, &qctx->fname, &qctx->rdataset, sigrdatasetp,
   9991   1.9  christos 		       qctx->dbuf, DNS_SECTION_ANSWER);
   9992   1.1  christos 
   9993   1.1  christos 	query_addnoqnameproof(qctx);
   9994   1.1  christos 
   9995   1.1  christos 	/*
   9996   1.1  christos 	 * We set the PARTIALANSWER attribute so that if anything goes
   9997   1.1  christos 	 * wrong later on, we'll return what we've got so far.
   9998   1.1  christos 	 */
   9999   1.1  christos 	qctx->client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
   10000   1.1  christos 
   10001   1.1  christos 	/*
   10002   1.1  christos 	 * Reset qname to be the target name of the CNAME and restart
   10003   1.1  christos 	 * the query.
   10004   1.1  christos 	 */
   10005   1.1  christos 	tname = NULL;
   10006   1.1  christos 	result = dns_message_gettempname(qctx->client->message, &tname);
   10007   1.9  christos 	if (result != ISC_R_SUCCESS) {
   10008   1.3  christos 		return (ns_query_done(qctx));
   10009   1.9  christos 	}
   10010   1.1  christos 
   10011   1.1  christos 	result = dns_rdataset_first(trdataset);
   10012   1.1  christos 	if (result != ISC_R_SUCCESS) {
   10013   1.1  christos 		dns_message_puttempname(qctx->client->message, &tname);
   10014   1.3  christos 		return (ns_query_done(qctx));
   10015   1.1  christos 	}
   10016   1.1  christos 
   10017   1.1  christos 	dns_rdataset_current(trdataset, &rdata);
   10018   1.1  christos 	result = dns_rdata_tostruct(&rdata, &cname, NULL);
   10019   1.3  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10020   1.1  christos 	dns_rdata_reset(&rdata);
   10021   1.1  christos 
   10022   1.1  christos 	dns_name_init(tname, NULL);
   10023   1.9  christos 	dns_name_dup(&cname.cname, qctx->client->mctx, tname);
   10024   1.1  christos 
   10025   1.1  christos 	dns_rdata_freestruct(&cname);
   10026   1.1  christos 	ns_client_qnamereplace(qctx->client, tname);
   10027   1.3  christos 	qctx->want_restart = true;
   10028   1.9  christos 	if (!WANTRECURSION(qctx->client)) {
   10029   1.1  christos 		qctx->options |= DNS_GETDB_NOLOG;
   10030   1.9  christos 	}
   10031   1.1  christos 
   10032   1.1  christos 	query_addauth(qctx);
   10033   1.1  christos 
   10034   1.3  christos 	return (ns_query_done(qctx));
   10035   1.3  christos 
   10036   1.9  christos cleanup:
   10037   1.3  christos 	return (result);
   10038   1.1  christos }
   10039   1.1  christos 
   10040   1.1  christos /*
   10041   1.1  christos  * Handle DNAME responses.
   10042   1.1  christos  */
   10043   1.1  christos static isc_result_t
   10044   1.1  christos query_dname(query_ctx_t *qctx) {
   10045   1.1  christos 	dns_name_t *tname, *prefix;
   10046   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   10047   1.1  christos 	dns_rdata_dname_t dname;
   10048   1.1  christos 	dns_fixedname_t fixed;
   10049   1.1  christos 	dns_rdataset_t *trdataset;
   10050   1.1  christos 	dns_rdataset_t **sigrdatasetp = NULL;
   10051   1.1  christos 	dns_namereln_t namereln;
   10052   1.1  christos 	isc_buffer_t b;
   10053   1.1  christos 	int order;
   10054   1.1  christos 	isc_result_t result;
   10055   1.1  christos 	unsigned int nlabels;
   10056   1.1  christos 
   10057   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_dname");
   10058   1.9  christos 
   10059   1.3  christos 	CALL_HOOK(NS_QUERY_DNAME_BEGIN, qctx);
   10060   1.3  christos 
   10061   1.1  christos 	/*
   10062   1.1  christos 	 * Compare the current qname to the found name.  We need
   10063   1.1  christos 	 * to know how many labels and bits are in common because
   10064   1.1  christos 	 * we're going to have to split qname later on.
   10065   1.1  christos 	 */
   10066   1.1  christos 	namereln = dns_name_fullcompare(qctx->client->query.qname, qctx->fname,
   10067   1.1  christos 					&order, &nlabels);
   10068   1.1  christos 	INSIST(namereln == dns_namereln_subdomain);
   10069   1.1  christos 
   10070   1.1  christos 	/*
   10071   1.1  christos 	 * Keep a copy of the rdataset.  We have to do this because
   10072   1.1  christos 	 * query_addrrset may clear 'rdataset' (to prevent the
   10073   1.1  christos 	 * cleanup code from cleaning it up).
   10074   1.1  christos 	 */
   10075   1.1  christos 	trdataset = qctx->rdataset;
   10076   1.1  christos 
   10077   1.1  christos 	/*
   10078   1.1  christos 	 * Add the DNAME to the answer section.
   10079   1.1  christos 	 */
   10080   1.9  christos 	if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) {
   10081   1.1  christos 		sigrdatasetp = &qctx->sigrdataset;
   10082   1.9  christos 	}
   10083   1.1  christos 
   10084   1.1  christos 	if (WANTDNSSEC(qctx->client) &&
   10085   1.1  christos 	    (qctx->fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
   10086   1.1  christos 	{
   10087   1.1  christos 		dns_fixedname_init(&qctx->wildcardname);
   10088   1.8  christos 		dns_name_copynf(qctx->fname,
   10089   1.9  christos 				dns_fixedname_name(&qctx->wildcardname));
   10090   1.3  christos 		qctx->need_wildcardproof = true;
   10091   1.1  christos 	}
   10092   1.1  christos 
   10093   1.9  christos 	if (!qctx->is_zone && RECURSIONOK(qctx->client)) {
   10094   1.1  christos 		query_prefetch(qctx->client, qctx->fname, qctx->rdataset);
   10095   1.9  christos 	}
   10096   1.9  christos 	query_addrrset(qctx, &qctx->fname, &qctx->rdataset, sigrdatasetp,
   10097   1.9  christos 		       qctx->dbuf, DNS_SECTION_ANSWER);
   10098   1.1  christos 
   10099   1.1  christos 	/*
   10100   1.1  christos 	 * We set the PARTIALANSWER attribute so that if anything goes
   10101   1.1  christos 	 * wrong later on, we'll return what we've got so far.
   10102   1.1  christos 	 */
   10103   1.1  christos 	qctx->client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
   10104   1.1  christos 
   10105   1.1  christos 	/*
   10106   1.1  christos 	 * Get the target name of the DNAME.
   10107   1.1  christos 	 */
   10108   1.1  christos 	tname = NULL;
   10109   1.1  christos 	result = dns_message_gettempname(qctx->client->message, &tname);
   10110   1.9  christos 	if (result != ISC_R_SUCCESS) {
   10111   1.3  christos 		return (ns_query_done(qctx));
   10112   1.9  christos 	}
   10113   1.1  christos 
   10114   1.1  christos 	result = dns_rdataset_first(trdataset);
   10115   1.1  christos 	if (result != ISC_R_SUCCESS) {
   10116   1.1  christos 		dns_message_puttempname(qctx->client->message, &tname);
   10117   1.3  christos 		return (ns_query_done(qctx));
   10118   1.1  christos 	}
   10119   1.1  christos 
   10120   1.1  christos 	dns_rdataset_current(trdataset, &rdata);
   10121   1.1  christos 	result = dns_rdata_tostruct(&rdata, &dname, NULL);
   10122   1.3  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10123   1.1  christos 	dns_rdata_reset(&rdata);
   10124   1.1  christos 
   10125   1.1  christos 	dns_name_clone(&dname.dname, tname);
   10126   1.1  christos 	dns_rdata_freestruct(&dname);
   10127   1.1  christos 
   10128   1.1  christos 	/*
   10129   1.1  christos 	 * Construct the new qname consisting of
   10130   1.1  christos 	 * <found name prefix>.<dname target>
   10131   1.1  christos 	 */
   10132   1.1  christos 	prefix = dns_fixedname_initname(&fixed);
   10133   1.1  christos 	dns_name_split(qctx->client->query.qname, nlabels, prefix, NULL);
   10134   1.1  christos 	INSIST(qctx->fname == NULL);
   10135   1.3  christos 	qctx->dbuf = ns_client_getnamebuf(qctx->client);
   10136   1.1  christos 	if (qctx->dbuf == NULL) {
   10137   1.1  christos 		dns_message_puttempname(qctx->client->message, &tname);
   10138   1.3  christos 		return (ns_query_done(qctx));
   10139   1.1  christos 	}
   10140   1.3  christos 	qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, &b);
   10141   1.1  christos 	if (qctx->fname == NULL) {
   10142   1.1  christos 		dns_message_puttempname(qctx->client->message, &tname);
   10143   1.3  christos 		return (ns_query_done(qctx));
   10144   1.1  christos 	}
   10145   1.1  christos 	result = dns_name_concatenate(prefix, tname, qctx->fname, NULL);
   10146   1.1  christos 	dns_message_puttempname(qctx->client->message, &tname);
   10147   1.1  christos 
   10148   1.1  christos 	/*
   10149   1.1  christos 	 * RFC2672, section 4.1, subsection 3c says
   10150   1.1  christos 	 * we should return YXDOMAIN if the constructed
   10151   1.1  christos 	 * name would be too long.
   10152   1.1  christos 	 */
   10153   1.9  christos 	if (result == DNS_R_NAMETOOLONG) {
   10154   1.1  christos 		qctx->client->message->rcode = dns_rcode_yxdomain;
   10155   1.9  christos 	}
   10156   1.9  christos 	if (result != ISC_R_SUCCESS) {
   10157   1.3  christos 		return (ns_query_done(qctx));
   10158   1.9  christos 	}
   10159   1.1  christos 
   10160   1.3  christos 	ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
   10161   1.1  christos 
   10162   1.1  christos 	/*
   10163   1.1  christos 	 * Synthesize a CNAME consisting of
   10164   1.1  christos 	 *   <old qname> <dname ttl> CNAME <new qname>
   10165   1.1  christos 	 *	    with <dname trust value>
   10166   1.1  christos 	 *
   10167   1.1  christos 	 * Synthesize a CNAME so old old clients that don't understand
   10168   1.1  christos 	 * DNAME can chain.
   10169   1.1  christos 	 *
   10170   1.1  christos 	 * We do not try to synthesize a signature because we hope
   10171   1.1  christos 	 * that security aware servers will understand DNAME.  Also,
   10172   1.1  christos 	 * even if we had an online key, making a signature
   10173   1.1  christos 	 * on-the-fly is costly, and not really legitimate anyway
   10174   1.1  christos 	 * since the synthesized CNAME is NOT in the zone.
   10175   1.1  christos 	 */
   10176   1.1  christos 	result = query_addcname(qctx, trdataset->trust, trdataset->ttl);
   10177   1.9  christos 	if (result != ISC_R_SUCCESS) {
   10178   1.3  christos 		return (ns_query_done(qctx));
   10179   1.9  christos 	}
   10180   1.1  christos 
   10181   1.1  christos 	/*
   10182  1.11  christos 	 * If the original query was not for a CNAME or ANY then follow the
   10183  1.11  christos 	 * CNAME.
   10184   1.1  christos 	 */
   10185  1.11  christos 	if (qctx->qtype != dns_rdatatype_cname &&
   10186  1.11  christos 	    qctx->qtype != dns_rdatatype_any) {
   10187  1.11  christos 		/*
   10188  1.11  christos 		 * Switch to the new qname and restart.
   10189  1.11  christos 		 */
   10190  1.11  christos 		ns_client_qnamereplace(qctx->client, qctx->fname);
   10191  1.11  christos 		qctx->fname = NULL;
   10192  1.11  christos 		qctx->want_restart = true;
   10193  1.11  christos 		if (!WANTRECURSION(qctx->client)) {
   10194  1.11  christos 			qctx->options |= DNS_GETDB_NOLOG;
   10195  1.11  christos 		}
   10196   1.9  christos 	}
   10197   1.1  christos 
   10198   1.1  christos 	query_addauth(qctx);
   10199   1.1  christos 
   10200   1.3  christos 	return (ns_query_done(qctx));
   10201   1.3  christos 
   10202   1.9  christos cleanup:
   10203   1.3  christos 	return (result);
   10204   1.1  christos }
   10205   1.1  christos 
   10206   1.1  christos /*%
   10207   1.9  christos  * Add CNAME to response.
   10208   1.1  christos  */
   10209   1.1  christos static isc_result_t
   10210   1.1  christos query_addcname(query_ctx_t *qctx, dns_trust_t trust, dns_ttl_t ttl) {
   10211   1.1  christos 	ns_client_t *client = qctx->client;
   10212   1.1  christos 	dns_rdataset_t *rdataset = NULL;
   10213   1.1  christos 	dns_rdatalist_t *rdatalist = NULL;
   10214   1.1  christos 	dns_rdata_t *rdata = NULL;
   10215   1.1  christos 	isc_region_t r;
   10216   1.1  christos 	dns_name_t *aname = NULL;
   10217   1.1  christos 	isc_result_t result;
   10218   1.1  christos 
   10219   1.1  christos 	result = dns_message_gettempname(client->message, &aname);
   10220   1.1  christos 	if (result != ISC_R_SUCCESS) {
   10221   1.1  christos 		return (result);
   10222   1.1  christos 	}
   10223   1.9  christos 	dns_name_dup(client->query.qname, client->mctx, aname);
   10224   1.1  christos 
   10225   1.1  christos 	result = dns_message_gettemprdatalist(client->message, &rdatalist);
   10226   1.1  christos 	if (result != ISC_R_SUCCESS) {
   10227   1.1  christos 		dns_message_puttempname(client->message, &aname);
   10228   1.1  christos 		return (result);
   10229   1.1  christos 	}
   10230   1.1  christos 
   10231   1.1  christos 	result = dns_message_gettemprdata(client->message, &rdata);
   10232   1.1  christos 	if (result != ISC_R_SUCCESS) {
   10233   1.1  christos 		dns_message_puttempname(client->message, &aname);
   10234   1.1  christos 		dns_message_puttemprdatalist(client->message, &rdatalist);
   10235   1.1  christos 		return (result);
   10236   1.1  christos 	}
   10237   1.1  christos 
   10238   1.1  christos 	result = dns_message_gettemprdataset(client->message, &rdataset);
   10239   1.1  christos 	if (result != ISC_R_SUCCESS) {
   10240   1.1  christos 		dns_message_puttempname(client->message, &aname);
   10241   1.1  christos 		dns_message_puttemprdatalist(client->message, &rdatalist);
   10242   1.1  christos 		dns_message_puttemprdata(client->message, &rdata);
   10243   1.1  christos 		return (result);
   10244   1.1  christos 	}
   10245   1.1  christos 
   10246   1.1  christos 	rdatalist->type = dns_rdatatype_cname;
   10247   1.1  christos 	rdatalist->rdclass = client->message->rdclass;
   10248   1.1  christos 	rdatalist->ttl = ttl;
   10249   1.1  christos 
   10250   1.1  christos 	dns_name_toregion(qctx->fname, &r);
   10251   1.1  christos 	rdata->data = r.base;
   10252   1.1  christos 	rdata->length = r.length;
   10253   1.1  christos 	rdata->rdclass = client->message->rdclass;
   10254   1.1  christos 	rdata->type = dns_rdatatype_cname;
   10255   1.1  christos 
   10256   1.1  christos 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
   10257   1.9  christos 	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
   10258   1.9  christos 		      ISC_R_SUCCESS);
   10259   1.1  christos 	rdataset->trust = trust;
   10260   1.1  christos 	dns_rdataset_setownercase(rdataset, aname);
   10261   1.1  christos 
   10262   1.9  christos 	query_addrrset(qctx, &aname, &rdataset, NULL, NULL, DNS_SECTION_ANSWER);
   10263   1.1  christos 	if (rdataset != NULL) {
   10264   1.9  christos 		if (dns_rdataset_isassociated(rdataset)) {
   10265   1.1  christos 			dns_rdataset_disassociate(rdataset);
   10266   1.9  christos 		}
   10267   1.1  christos 		dns_message_puttemprdataset(client->message, &rdataset);
   10268   1.1  christos 	}
   10269   1.9  christos 	if (aname != NULL) {
   10270   1.1  christos 		dns_message_puttempname(client->message, &aname);
   10271   1.9  christos 	}
   10272   1.1  christos 
   10273   1.1  christos 	return (ISC_R_SUCCESS);
   10274   1.1  christos }
   10275   1.1  christos 
   10276   1.1  christos /*%
   10277   1.1  christos  * Prepare to respond: determine whether a wildcard proof is needed,
   10278   1.3  christos  * then hand off to query_respond() or (for type ANY queries)
   10279   1.3  christos  * query_respond_any().
   10280   1.1  christos  */
   10281   1.1  christos static isc_result_t
   10282   1.1  christos query_prepresponse(query_ctx_t *qctx) {
   10283   1.3  christos 	isc_result_t result;
   10284   1.3  christos 
   10285   1.9  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_prepresponse");
   10286   1.9  christos 
   10287   1.3  christos 	CALL_HOOK(NS_QUERY_PREP_RESPONSE_BEGIN, qctx);
   10288   1.3  christos 
   10289   1.1  christos 	if (WANTDNSSEC(qctx->client) &&
   10290   1.1  christos 	    (qctx->fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
   10291   1.1  christos 	{
   10292   1.1  christos 		dns_fixedname_init(&qctx->wildcardname);
   10293   1.8  christos 		dns_name_copynf(qctx->fname,
   10294   1.9  christos 				dns_fixedname_name(&qctx->wildcardname));
   10295   1.3  christos 		qctx->need_wildcardproof = true;
   10296   1.3  christos 	}
   10297   1.3  christos 
   10298   1.3  christos 	if (qctx->type == dns_rdatatype_any) {
   10299   1.3  christos 		return (query_respond_any(qctx));
   10300   1.1  christos 	}
   10301   1.1  christos 
   10302   1.3  christos 	result = query_zerottl_refetch(qctx);
   10303   1.3  christos 	if (result != ISC_R_COMPLETE) {
   10304   1.3  christos 		return (result);
   10305   1.1  christos 	}
   10306   1.1  christos 
   10307   1.3  christos 	return (query_respond(qctx));
   10308   1.1  christos 
   10309   1.9  christos cleanup:
   10310   1.3  christos 	return (result);
   10311   1.1  christos }
   10312   1.1  christos 
   10313   1.1  christos /*%
   10314   1.1  christos  * Add SOA to the authority section when sending negative responses
   10315   1.1  christos  * (or to the additional section if sending negative responses triggered
   10316   1.1  christos  * by RPZ rewriting.)
   10317   1.1  christos  */
   10318   1.1  christos static isc_result_t
   10319   1.1  christos query_addsoa(query_ctx_t *qctx, unsigned int override_ttl,
   10320   1.9  christos 	     dns_section_t section) {
   10321   1.1  christos 	ns_client_t *client = qctx->client;
   10322   1.1  christos 	dns_name_t *name;
   10323   1.1  christos 	dns_dbnode_t *node;
   10324   1.1  christos 	isc_result_t result, eresult;
   10325   1.1  christos 	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
   10326   1.1  christos 	dns_rdataset_t **sigrdatasetp = NULL;
   10327   1.1  christos 	dns_clientinfomethods_t cm;
   10328   1.1  christos 	dns_clientinfo_t ci;
   10329   1.1  christos 
   10330   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addsoa");
   10331   1.1  christos 	/*
   10332   1.1  christos 	 * Initialization.
   10333   1.1  christos 	 */
   10334   1.1  christos 	eresult = ISC_R_SUCCESS;
   10335   1.1  christos 	name = NULL;
   10336   1.1  christos 	rdataset = NULL;
   10337   1.1  christos 	node = NULL;
   10338   1.1  christos 
   10339   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   10340   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   10341   1.1  christos 
   10342   1.1  christos 	/*
   10343   1.1  christos 	 * Don't add the SOA record for test which set "-T nosoa".
   10344   1.1  christos 	 */
   10345   1.1  christos 	if (((client->sctx->options & NS_SERVER_NOSOA) != 0) &&
   10346   1.1  christos 	    (!WANTDNSSEC(client) || !dns_rdataset_isassociated(qctx->rdataset)))
   10347   1.1  christos 	{
   10348   1.1  christos 		return (ISC_R_SUCCESS);
   10349   1.1  christos 	}
   10350   1.1  christos 
   10351   1.1  christos 	/*
   10352   1.1  christos 	 * Get resources and make 'name' be the database origin.
   10353   1.1  christos 	 */
   10354   1.1  christos 	result = dns_message_gettempname(client->message, &name);
   10355   1.9  christos 	if (result != ISC_R_SUCCESS) {
   10356   1.1  christos 		return (result);
   10357   1.9  christos 	}
   10358   1.1  christos 	dns_name_init(name, NULL);
   10359   1.1  christos 	dns_name_clone(dns_db_origin(qctx->db), name);
   10360   1.3  christos 	rdataset = ns_client_newrdataset(client);
   10361   1.1  christos 	if (rdataset == NULL) {
   10362   1.1  christos 		CTRACE(ISC_LOG_ERROR, "unable to allocate rdataset");
   10363   1.1  christos 		eresult = DNS_R_SERVFAIL;
   10364   1.1  christos 		goto cleanup;
   10365   1.1  christos 	}
   10366   1.1  christos 	if (WANTDNSSEC(client) && dns_db_issecure(qctx->db)) {
   10367   1.3  christos 		sigrdataset = ns_client_newrdataset(client);
   10368   1.1  christos 		if (sigrdataset == NULL) {
   10369   1.1  christos 			CTRACE(ISC_LOG_ERROR, "unable to allocate sigrdataset");
   10370   1.1  christos 			eresult = DNS_R_SERVFAIL;
   10371   1.1  christos 			goto cleanup;
   10372   1.1  christos 		}
   10373   1.1  christos 	}
   10374   1.1  christos 
   10375   1.1  christos 	/*
   10376   1.1  christos 	 * Find the SOA.
   10377   1.1  christos 	 */
   10378   1.1  christos 	result = dns_db_getoriginnode(qctx->db, &node);
   10379   1.1  christos 	if (result == ISC_R_SUCCESS) {
   10380   1.1  christos 		result = dns_db_findrdataset(qctx->db, node, qctx->version,
   10381   1.9  christos 					     dns_rdatatype_soa, 0, client->now,
   10382   1.1  christos 					     rdataset, sigrdataset);
   10383   1.1  christos 	} else {
   10384   1.1  christos 		dns_fixedname_t foundname;
   10385   1.1  christos 		dns_name_t *fname;
   10386   1.1  christos 
   10387   1.1  christos 		fname = dns_fixedname_initname(&foundname);
   10388   1.1  christos 
   10389   1.1  christos 		result = dns_db_findext(qctx->db, name, qctx->version,
   10390   1.1  christos 					dns_rdatatype_soa,
   10391   1.9  christos 					client->query.dboptions, 0, &node,
   10392   1.9  christos 					fname, &cm, &ci, rdataset, sigrdataset);
   10393   1.1  christos 	}
   10394   1.1  christos 	if (result != ISC_R_SUCCESS) {
   10395   1.1  christos 		/*
   10396   1.1  christos 		 * This is bad.  We tried to get the SOA RR at the zone top
   10397   1.1  christos 		 * and it didn't work!
   10398   1.1  christos 		 */
   10399   1.1  christos 		CTRACE(ISC_LOG_ERROR, "unable to find SOA RR at zone apex");
   10400   1.1  christos 		eresult = DNS_R_SERVFAIL;
   10401   1.1  christos 	} else {
   10402   1.1  christos 		/*
   10403   1.1  christos 		 * Extract the SOA MINIMUM.
   10404   1.1  christos 		 */
   10405   1.1  christos 		dns_rdata_soa_t soa;
   10406   1.1  christos 		dns_rdata_t rdata = DNS_RDATA_INIT;
   10407   1.1  christos 		result = dns_rdataset_first(rdataset);
   10408   1.1  christos 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10409   1.1  christos 		dns_rdataset_current(rdataset, &rdata);
   10410   1.1  christos 		result = dns_rdata_tostruct(&rdata, &soa, NULL);
   10411   1.3  christos 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10412   1.1  christos 
   10413   1.9  christos 		if (override_ttl != UINT32_MAX && override_ttl < rdataset->ttl)
   10414   1.1  christos 		{
   10415   1.1  christos 			rdataset->ttl = override_ttl;
   10416   1.9  christos 			if (sigrdataset != NULL) {
   10417   1.1  christos 				sigrdataset->ttl = override_ttl;
   10418   1.9  christos 			}
   10419   1.1  christos 		}
   10420   1.1  christos 
   10421   1.1  christos 		/*
   10422   1.1  christos 		 * Add the SOA and its SIG to the response, with the
   10423   1.1  christos 		 * TTLs adjusted per RFC2308 section 3.
   10424   1.1  christos 		 */
   10425   1.9  christos 		if (rdataset->ttl > soa.minimum) {
   10426   1.1  christos 			rdataset->ttl = soa.minimum;
   10427   1.9  christos 		}
   10428   1.9  christos 		if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum) {
   10429   1.1  christos 			sigrdataset->ttl = soa.minimum;
   10430   1.9  christos 		}
   10431   1.1  christos 
   10432   1.9  christos 		if (sigrdataset != NULL) {
   10433   1.1  christos 			sigrdatasetp = &sigrdataset;
   10434   1.9  christos 		} else {
   10435   1.1  christos 			sigrdatasetp = NULL;
   10436   1.9  christos 		}
   10437   1.1  christos 
   10438   1.9  christos 		if (section == DNS_SECTION_ADDITIONAL) {
   10439   1.1  christos 			rdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
   10440   1.9  christos 		}
   10441   1.9  christos 		query_addrrset(qctx, &name, &rdataset, sigrdatasetp, NULL,
   10442   1.9  christos 			       section);
   10443   1.1  christos 	}
   10444   1.1  christos 
   10445   1.9  christos cleanup:
   10446   1.3  christos 	ns_client_putrdataset(client, &rdataset);
   10447   1.9  christos 	if (sigrdataset != NULL) {
   10448   1.3  christos 		ns_client_putrdataset(client, &sigrdataset);
   10449   1.9  christos 	}
   10450   1.9  christos 	if (name != NULL) {
   10451   1.3  christos 		ns_client_releasename(client, &name);
   10452   1.9  christos 	}
   10453   1.9  christos 	if (node != NULL) {
   10454   1.1  christos 		dns_db_detachnode(qctx->db, &node);
   10455   1.9  christos 	}
   10456   1.1  christos 
   10457   1.1  christos 	return (eresult);
   10458   1.1  christos }
   10459   1.1  christos 
   10460   1.1  christos /*%
   10461   1.1  christos  * Add NS to authority section (used when the zone apex is already known).
   10462   1.1  christos  */
   10463   1.1  christos static isc_result_t
   10464   1.1  christos query_addns(query_ctx_t *qctx) {
   10465   1.1  christos 	ns_client_t *client = qctx->client;
   10466   1.1  christos 	isc_result_t result, eresult;
   10467   1.1  christos 	dns_name_t *name = NULL, *fname;
   10468   1.1  christos 	dns_dbnode_t *node = NULL;
   10469   1.1  christos 	dns_fixedname_t foundname;
   10470   1.1  christos 	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
   10471   1.1  christos 	dns_rdataset_t **sigrdatasetp = NULL;
   10472   1.1  christos 	dns_clientinfomethods_t cm;
   10473   1.1  christos 	dns_clientinfo_t ci;
   10474   1.1  christos 
   10475   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addns");
   10476   1.1  christos 
   10477   1.1  christos 	/*
   10478   1.1  christos 	 * Initialization.
   10479   1.1  christos 	 */
   10480   1.1  christos 	eresult = ISC_R_SUCCESS;
   10481   1.1  christos 	fname = dns_fixedname_initname(&foundname);
   10482   1.1  christos 
   10483   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   10484   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   10485   1.1  christos 
   10486   1.1  christos 	/*
   10487   1.1  christos 	 * Get resources and make 'name' be the database origin.
   10488   1.1  christos 	 */
   10489   1.1  christos 	result = dns_message_gettempname(client->message, &name);
   10490   1.1  christos 	if (result != ISC_R_SUCCESS) {
   10491   1.9  christos 		CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_message_gettempname "
   10492   1.9  christos 					 "failed: done");
   10493   1.1  christos 		return (result);
   10494   1.1  christos 	}
   10495   1.1  christos 	dns_name_init(name, NULL);
   10496   1.1  christos 	dns_name_clone(dns_db_origin(qctx->db), name);
   10497   1.3  christos 	rdataset = ns_client_newrdataset(client);
   10498   1.1  christos 	if (rdataset == NULL) {
   10499   1.9  christos 		CTRACE(ISC_LOG_ERROR, "query_addns: ns_client_newrdataset "
   10500   1.9  christos 				      "failed");
   10501   1.1  christos 		eresult = DNS_R_SERVFAIL;
   10502   1.1  christos 		goto cleanup;
   10503   1.1  christos 	}
   10504   1.1  christos 
   10505   1.1  christos 	if (WANTDNSSEC(client) && dns_db_issecure(qctx->db)) {
   10506   1.3  christos 		sigrdataset = ns_client_newrdataset(client);
   10507   1.1  christos 		if (sigrdataset == NULL) {
   10508   1.9  christos 			CTRACE(ISC_LOG_ERROR, "query_addns: "
   10509   1.9  christos 					      "ns_client_newrdataset failed");
   10510   1.1  christos 			eresult = DNS_R_SERVFAIL;
   10511   1.1  christos 			goto cleanup;
   10512   1.1  christos 		}
   10513   1.1  christos 	}
   10514   1.1  christos 
   10515   1.1  christos 	/*
   10516   1.1  christos 	 * Find the NS rdataset.
   10517   1.1  christos 	 */
   10518   1.1  christos 	result = dns_db_getoriginnode(qctx->db, &node);
   10519   1.1  christos 	if (result == ISC_R_SUCCESS) {
   10520   1.1  christos 		result = dns_db_findrdataset(qctx->db, node, qctx->version,
   10521   1.1  christos 					     dns_rdatatype_ns, 0, client->now,
   10522   1.1  christos 					     rdataset, sigrdataset);
   10523   1.1  christos 	} else {
   10524   1.1  christos 		CTRACE(ISC_LOG_DEBUG(3), "query_addns: calling dns_db_find");
   10525   1.1  christos 		result = dns_db_findext(qctx->db, name, NULL, dns_rdatatype_ns,
   10526   1.1  christos 					client->query.dboptions, 0, &node,
   10527   1.1  christos 					fname, &cm, &ci, rdataset, sigrdataset);
   10528   1.1  christos 		CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_db_find complete");
   10529   1.1  christos 	}
   10530   1.1  christos 	if (result != ISC_R_SUCCESS) {
   10531   1.9  christos 		CTRACE(ISC_LOG_ERROR, "query_addns: "
   10532   1.9  christos 				      "dns_db_findrdataset or dns_db_find "
   10533   1.9  christos 				      "failed");
   10534   1.1  christos 		/*
   10535   1.1  christos 		 * This is bad.  We tried to get the NS rdataset at the zone
   10536   1.1  christos 		 * top and it didn't work!
   10537   1.1  christos 		 */
   10538   1.1  christos 		eresult = DNS_R_SERVFAIL;
   10539   1.1  christos 	} else {
   10540   1.1  christos 		if (sigrdataset != NULL) {
   10541   1.1  christos 			sigrdatasetp = &sigrdataset;
   10542   1.1  christos 		}
   10543   1.3  christos 		query_addrrset(qctx, &name, &rdataset, sigrdatasetp, NULL,
   10544   1.1  christos 			       DNS_SECTION_AUTHORITY);
   10545   1.1  christos 	}
   10546   1.1  christos 
   10547   1.9  christos cleanup:
   10548   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addns: cleanup");
   10549   1.3  christos 	ns_client_putrdataset(client, &rdataset);
   10550   1.1  christos 	if (sigrdataset != NULL) {
   10551   1.3  christos 		ns_client_putrdataset(client, &sigrdataset);
   10552   1.1  christos 	}
   10553   1.1  christos 	if (name != NULL) {
   10554   1.3  christos 		ns_client_releasename(client, &name);
   10555   1.1  christos 	}
   10556   1.1  christos 	if (node != NULL) {
   10557   1.1  christos 		dns_db_detachnode(qctx->db, &node);
   10558   1.1  christos 	}
   10559   1.1  christos 
   10560   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addns: done");
   10561   1.1  christos 	return (eresult);
   10562   1.1  christos }
   10563   1.1  christos 
   10564   1.1  christos /*%
   10565   1.1  christos  * Find the zone cut and add the best NS rrset to the authority section.
   10566   1.1  christos  */
   10567   1.1  christos static void
   10568   1.1  christos query_addbestns(query_ctx_t *qctx) {
   10569   1.1  christos 	ns_client_t *client = qctx->client;
   10570   1.1  christos 	dns_db_t *db = NULL, *zdb = NULL;
   10571   1.1  christos 	dns_dbnode_t *node = NULL;
   10572   1.1  christos 	dns_name_t *fname = NULL, *zfname = NULL;
   10573   1.1  christos 	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
   10574   1.1  christos 	dns_rdataset_t *zrdataset = NULL, *zsigrdataset = NULL;
   10575   1.3  christos 	bool is_zone = false, use_zone = false;
   10576   1.1  christos 	isc_buffer_t *dbuf = NULL;
   10577   1.1  christos 	isc_result_t result;
   10578   1.1  christos 	dns_dbversion_t *version = NULL;
   10579   1.1  christos 	dns_zone_t *zone = NULL;
   10580   1.1  christos 	isc_buffer_t b;
   10581   1.1  christos 	dns_clientinfomethods_t cm;
   10582   1.1  christos 	dns_clientinfo_t ci;
   10583   1.1  christos 
   10584   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addbestns");
   10585   1.1  christos 
   10586   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   10587   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   10588   1.1  christos 
   10589   1.1  christos 	/*
   10590   1.1  christos 	 * Find the right database.
   10591   1.1  christos 	 */
   10592   1.1  christos 	result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0,
   10593   1.1  christos 			     &zone, &db, &version, &is_zone);
   10594   1.9  christos 	if (result != ISC_R_SUCCESS) {
   10595   1.1  christos 		goto cleanup;
   10596   1.9  christos 	}
   10597   1.1  christos 
   10598   1.9  christos db_find:
   10599   1.1  christos 	/*
   10600   1.1  christos 	 * We'll need some resources...
   10601   1.1  christos 	 */
   10602   1.3  christos 	dbuf = ns_client_getnamebuf(client);
   10603   1.1  christos 	if (dbuf == NULL) {
   10604   1.1  christos 		goto cleanup;
   10605   1.1  christos 	}
   10606   1.3  christos 	fname = ns_client_newname(client, dbuf, &b);
   10607   1.3  christos 	rdataset = ns_client_newrdataset(client);
   10608   1.1  christos 	if (fname == NULL || rdataset == NULL) {
   10609   1.1  christos 		goto cleanup;
   10610   1.1  christos 	}
   10611   1.1  christos 
   10612   1.1  christos 	/*
   10613   1.1  christos 	 * Get the RRSIGs if the client requested them or if we may
   10614   1.1  christos 	 * need to validate answers from the cache.
   10615   1.1  christos 	 */
   10616   1.1  christos 	if (WANTDNSSEC(client) || !is_zone) {
   10617   1.3  christos 		sigrdataset = ns_client_newrdataset(client);
   10618   1.1  christos 		if (sigrdataset == NULL) {
   10619   1.1  christos 			goto cleanup;
   10620   1.1  christos 		}
   10621   1.1  christos 	}
   10622   1.1  christos 
   10623   1.1  christos 	/*
   10624   1.1  christos 	 * Now look for the zonecut.
   10625   1.1  christos 	 */
   10626   1.1  christos 	if (is_zone) {
   10627   1.9  christos 		result = dns_db_findext(
   10628   1.9  christos 			db, client->query.qname, version, dns_rdatatype_ns,
   10629   1.9  christos 			client->query.dboptions, client->now, &node, fname, &cm,
   10630   1.9  christos 			&ci, rdataset, sigrdataset);
   10631   1.1  christos 		if (result != DNS_R_DELEGATION) {
   10632   1.1  christos 			goto cleanup;
   10633   1.1  christos 		}
   10634   1.1  christos 		if (USECACHE(client)) {
   10635   1.3  christos 			ns_client_keepname(client, fname, dbuf);
   10636   1.1  christos 			dns_db_detachnode(db, &node);
   10637   1.1  christos 			SAVE(zdb, db);
   10638   1.1  christos 			SAVE(zfname, fname);
   10639   1.1  christos 			SAVE(zrdataset, rdataset);
   10640   1.1  christos 			SAVE(zsigrdataset, sigrdataset);
   10641   1.1  christos 			version = NULL;
   10642   1.1  christos 			dns_db_attach(client->view->cachedb, &db);
   10643   1.3  christos 			is_zone = false;
   10644   1.1  christos 			goto db_find;
   10645   1.1  christos 		}
   10646   1.1  christos 	} else {
   10647   1.9  christos 		result = dns_db_findzonecut(
   10648   1.9  christos 			db, client->query.qname, client->query.dboptions,
   10649   1.9  christos 			client->now, &node, fname, NULL, rdataset, sigrdataset);
   10650   1.1  christos 		if (result == ISC_R_SUCCESS) {
   10651   1.1  christos 			if (zfname != NULL &&
   10652   1.1  christos 			    !dns_name_issubdomain(fname, zfname)) {
   10653   1.1  christos 				/*
   10654   1.1  christos 				 * We found a zonecut in the cache, but our
   10655   1.1  christos 				 * zone delegation is better.
   10656   1.1  christos 				 */
   10657   1.3  christos 				use_zone = true;
   10658   1.1  christos 			}
   10659   1.1  christos 		} else if (result == ISC_R_NOTFOUND && zfname != NULL) {
   10660   1.1  christos 			/*
   10661   1.1  christos 			 * We didn't find anything in the cache, but we
   10662   1.1  christos 			 * have a zone delegation, so use it.
   10663   1.1  christos 			 */
   10664   1.3  christos 			use_zone = true;
   10665   1.1  christos 		} else {
   10666   1.1  christos 			goto cleanup;
   10667   1.1  christos 		}
   10668   1.1  christos 	}
   10669   1.1  christos 
   10670   1.1  christos 	if (use_zone) {
   10671   1.3  christos 		ns_client_releasename(client, &fname);
   10672   1.1  christos 		/*
   10673   1.3  christos 		 * We've already done ns_client_keepname() on
   10674   1.1  christos 		 * zfname, so we must set dbuf to NULL to
   10675   1.1  christos 		 * prevent query_addrrset() from trying to
   10676   1.3  christos 		 * call ns_client_keepname() again.
   10677   1.1  christos 		 */
   10678   1.1  christos 		dbuf = NULL;
   10679   1.3  christos 		ns_client_putrdataset(client, &rdataset);
   10680   1.1  christos 		if (sigrdataset != NULL) {
   10681   1.3  christos 			ns_client_putrdataset(client, &sigrdataset);
   10682   1.1  christos 		}
   10683   1.1  christos 
   10684   1.1  christos 		if (node != NULL) {
   10685   1.1  christos 			dns_db_detachnode(db, &node);
   10686   1.1  christos 		}
   10687   1.1  christos 		dns_db_detach(&db);
   10688   1.1  christos 
   10689   1.1  christos 		RESTORE(db, zdb);
   10690   1.1  christos 		RESTORE(fname, zfname);
   10691   1.1  christos 		RESTORE(rdataset, zrdataset);
   10692   1.1  christos 		RESTORE(sigrdataset, zsigrdataset);
   10693   1.1  christos 	}
   10694   1.1  christos 
   10695   1.1  christos 	/*
   10696   1.1  christos 	 * Attempt to validate RRsets that are pending or that are glue.
   10697   1.1  christos 	 */
   10698   1.1  christos 	if ((DNS_TRUST_PENDING(rdataset->trust) ||
   10699   1.1  christos 	     (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust))) &&
   10700   1.1  christos 	    !validate(client, db, fname, rdataset, sigrdataset) &&
   10701   1.1  christos 	    !PENDINGOK(client->query.dboptions))
   10702   1.1  christos 	{
   10703   1.1  christos 		goto cleanup;
   10704   1.1  christos 	}
   10705   1.1  christos 
   10706   1.1  christos 	if ((DNS_TRUST_GLUE(rdataset->trust) ||
   10707   1.1  christos 	     (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
   10708   1.1  christos 	    !validate(client, db, fname, rdataset, sigrdataset) &&
   10709   1.1  christos 	    SECURE(client) && WANTDNSSEC(client))
   10710   1.1  christos 	{
   10711   1.1  christos 		goto cleanup;
   10712   1.1  christos 	}
   10713   1.1  christos 
   10714   1.1  christos 	/*
   10715   1.1  christos 	 * If the answer is secure only add NS records if they are secure
   10716   1.1  christos 	 * when the client may be looking for AD in the response.
   10717   1.1  christos 	 */
   10718   1.1  christos 	if (SECURE(client) && (WANTDNSSEC(client) || WANTAD(client)) &&
   10719   1.1  christos 	    ((rdataset->trust != dns_trust_secure) ||
   10720   1.9  christos 	     (sigrdataset != NULL && sigrdataset->trust != dns_trust_secure)))
   10721   1.1  christos 	{
   10722   1.1  christos 		goto cleanup;
   10723   1.1  christos 	}
   10724   1.1  christos 
   10725   1.1  christos 	/*
   10726   1.1  christos 	 * If the client doesn't want DNSSEC we can discard the sigrdataset
   10727   1.1  christos 	 * now.
   10728   1.1  christos 	 */
   10729   1.1  christos 	if (!WANTDNSSEC(client)) {
   10730   1.3  christos 		ns_client_putrdataset(client, &sigrdataset);
   10731   1.1  christos 	}
   10732   1.1  christos 
   10733   1.3  christos 	query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
   10734   1.1  christos 		       DNS_SECTION_AUTHORITY);
   10735   1.1  christos 
   10736   1.9  christos cleanup:
   10737   1.1  christos 	if (rdataset != NULL) {
   10738   1.3  christos 		ns_client_putrdataset(client, &rdataset);
   10739   1.1  christos 	}
   10740   1.1  christos 	if (sigrdataset != NULL) {
   10741   1.3  christos 		ns_client_putrdataset(client, &sigrdataset);
   10742   1.1  christos 	}
   10743   1.1  christos 	if (fname != NULL) {
   10744   1.3  christos 		ns_client_releasename(client, &fname);
   10745   1.1  christos 	}
   10746   1.1  christos 	if (node != NULL) {
   10747   1.1  christos 		dns_db_detachnode(db, &node);
   10748   1.1  christos 	}
   10749   1.1  christos 	if (db != NULL) {
   10750   1.1  christos 		dns_db_detach(&db);
   10751   1.1  christos 	}
   10752   1.1  christos 	if (zone != NULL) {
   10753   1.1  christos 		dns_zone_detach(&zone);
   10754   1.1  christos 	}
   10755   1.1  christos 	if (zdb != NULL) {
   10756   1.3  christos 		ns_client_putrdataset(client, &zrdataset);
   10757   1.3  christos 		if (zsigrdataset != NULL) {
   10758   1.3  christos 			ns_client_putrdataset(client, &zsigrdataset);
   10759   1.3  christos 		}
   10760   1.3  christos 		if (zfname != NULL) {
   10761   1.3  christos 			ns_client_releasename(client, &zfname);
   10762   1.3  christos 		}
   10763   1.1  christos 		dns_db_detach(&zdb);
   10764   1.1  christos 	}
   10765   1.1  christos }
   10766   1.1  christos 
   10767   1.1  christos static void
   10768   1.9  christos query_addwildcardproof(query_ctx_t *qctx, bool ispositive, bool nodata) {
   10769   1.1  christos 	ns_client_t *client = qctx->client;
   10770   1.1  christos 	isc_buffer_t *dbuf, b;
   10771   1.1  christos 	dns_name_t *name;
   10772   1.1  christos 	dns_name_t *fname = NULL;
   10773   1.1  christos 	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
   10774   1.1  christos 	dns_fixedname_t wfixed;
   10775   1.1  christos 	dns_name_t *wname;
   10776   1.1  christos 	dns_dbnode_t *node = NULL;
   10777   1.1  christos 	unsigned int options;
   10778   1.1  christos 	unsigned int olabels, nlabels, labels;
   10779   1.1  christos 	isc_result_t result;
   10780   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   10781   1.1  christos 	dns_rdata_nsec_t nsec;
   10782   1.3  christos 	bool have_wname;
   10783   1.1  christos 	int order;
   10784   1.1  christos 	dns_fixedname_t cfixed;
   10785   1.1  christos 	dns_name_t *cname;
   10786   1.1  christos 	dns_clientinfomethods_t cm;
   10787   1.1  christos 	dns_clientinfo_t ci;
   10788   1.1  christos 
   10789   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "query_addwildcardproof");
   10790   1.1  christos 
   10791   1.1  christos 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
   10792   1.1  christos 	dns_clientinfo_init(&ci, client, NULL);
   10793   1.1  christos 
   10794   1.1  christos 	/*
   10795   1.1  christos 	 * If a name has been specifically flagged as needing
   10796   1.1  christos 	 * a wildcard proof then it will have been copied to
   10797   1.1  christos 	 * qctx->wildcardname. Otherwise we just use the client
   10798   1.1  christos 	 * QNAME.
   10799   1.1  christos 	 */
   10800   1.1  christos 	if (qctx->need_wildcardproof) {
   10801   1.1  christos 		name = dns_fixedname_name(&qctx->wildcardname);
   10802   1.1  christos 	} else {
   10803   1.1  christos 		name = client->query.qname;
   10804   1.1  christos 	}
   10805   1.1  christos 
   10806   1.1  christos 	/*
   10807   1.1  christos 	 * Get the NOQNAME proof then if !ispositive
   10808   1.1  christos 	 * get the NOWILDCARD proof.
   10809   1.1  christos 	 *
   10810   1.1  christos 	 * DNS_DBFIND_NOWILD finds the NSEC records that covers the
   10811   1.1  christos 	 * name ignoring any wildcard.  From the owner and next names
   10812   1.1  christos 	 * of this record you can compute which wildcard (if it exists)
   10813   1.1  christos 	 * will match by finding the longest common suffix of the
   10814   1.1  christos 	 * owner name and next names with the qname and prefixing that
   10815   1.1  christos 	 * with the wildcard label.
   10816   1.1  christos 	 *
   10817   1.1  christos 	 * e.g.
   10818   1.1  christos 	 *   Given:
   10819   1.1  christos 	 *	example SOA
   10820   1.1  christos 	 *	example NSEC b.example
   10821   1.1  christos 	 *	b.example A
   10822   1.1  christos 	 *	b.example NSEC a.d.example
   10823   1.1  christos 	 *	a.d.example A
   10824   1.1  christos 	 *	a.d.example NSEC g.f.example
   10825   1.1  christos 	 *	g.f.example A
   10826   1.1  christos 	 *	g.f.example NSEC z.i.example
   10827   1.1  christos 	 *	z.i.example A
   10828   1.1  christos 	 *	z.i.example NSEC example
   10829   1.1  christos 	 *
   10830   1.1  christos 	 *   QNAME:
   10831   1.1  christos 	 *   a.example -> example NSEC b.example
   10832   1.1  christos 	 *	owner common example
   10833   1.1  christos 	 *	next common example
   10834   1.1  christos 	 *	wild *.example
   10835   1.1  christos 	 *   d.b.example -> b.example NSEC a.d.example
   10836   1.1  christos 	 *	owner common b.example
   10837   1.1  christos 	 *	next common example
   10838   1.1  christos 	 *	wild *.b.example
   10839   1.1  christos 	 *   a.f.example -> a.d.example NSEC g.f.example
   10840   1.1  christos 	 *	owner common example
   10841   1.1  christos 	 *	next common f.example
   10842   1.1  christos 	 *	wild *.f.example
   10843   1.1  christos 	 *  j.example -> z.i.example NSEC example
   10844   1.1  christos 	 *	owner common example
   10845   1.1  christos 	 *	next common example
   10846   1.1  christos 	 *	wild *.example
   10847   1.1  christos 	 */
   10848   1.1  christos 	options = client->query.dboptions | DNS_DBFIND_NOWILD;
   10849   1.1  christos 	wname = dns_fixedname_initname(&wfixed);
   10850   1.9  christos again:
   10851   1.3  christos 	have_wname = false;
   10852   1.1  christos 	/*
   10853   1.1  christos 	 * We'll need some resources...
   10854   1.1  christos 	 */
   10855   1.3  christos 	dbuf = ns_client_getnamebuf(client);
   10856   1.9  christos 	if (dbuf == NULL) {
   10857   1.1  christos 		goto cleanup;
   10858   1.9  christos 	}
   10859   1.3  christos 	fname = ns_client_newname(client, dbuf, &b);
   10860   1.3  christos 	rdataset = ns_client_newrdataset(client);
   10861   1.3  christos 	sigrdataset = ns_client_newrdataset(client);
   10862   1.9  christos 	if (fname == NULL || rdataset == NULL || sigrdataset == NULL) {
   10863   1.1  christos 		goto cleanup;
   10864   1.9  christos 	}
   10865   1.1  christos 
   10866   1.1  christos 	result = dns_db_findext(qctx->db, name, qctx->version,
   10867   1.9  christos 				dns_rdatatype_nsec, options, 0, &node, fname,
   10868   1.9  christos 				&cm, &ci, rdataset, sigrdataset);
   10869   1.9  christos 	if (node != NULL) {
   10870   1.1  christos 		dns_db_detachnode(qctx->db, &node);
   10871   1.9  christos 	}
   10872   1.1  christos 
   10873   1.1  christos 	if (!dns_rdataset_isassociated(rdataset)) {
   10874   1.1  christos 		/*
   10875   1.1  christos 		 * No NSEC proof available, return NSEC3 proofs instead.
   10876   1.1  christos 		 */
   10877   1.1  christos 		cname = dns_fixedname_initname(&cfixed);
   10878   1.1  christos 		/*
   10879   1.1  christos 		 * Find the closest encloser.
   10880   1.1  christos 		 */
   10881   1.8  christos 		dns_name_copynf(name, cname);
   10882   1.1  christos 		while (result == DNS_R_NXDOMAIN) {
   10883   1.1  christos 			labels = dns_name_countlabels(cname) - 1;
   10884   1.1  christos 			/*
   10885   1.1  christos 			 * Sanity check.
   10886   1.1  christos 			 */
   10887   1.9  christos 			if (labels == 0U) {
   10888   1.1  christos 				goto cleanup;
   10889   1.9  christos 			}
   10890   1.1  christos 			dns_name_split(cname, labels, NULL, cname);
   10891   1.1  christos 			result = dns_db_findext(qctx->db, cname, qctx->version,
   10892   1.9  christos 						dns_rdatatype_nsec, options, 0,
   10893   1.9  christos 						NULL, fname, &cm, &ci, NULL,
   10894   1.9  christos 						NULL);
   10895   1.1  christos 		}
   10896   1.1  christos 		/*
   10897   1.1  christos 		 * Add closest (provable) encloser NSEC3.
   10898   1.1  christos 		 */
   10899   1.9  christos 		query_findclosestnsec3(cname, qctx->db, qctx->version, client,
   10900   1.9  christos 				       rdataset, sigrdataset, fname, true,
   10901   1.9  christos 				       cname);
   10902   1.9  christos 		if (!dns_rdataset_isassociated(rdataset)) {
   10903   1.1  christos 			goto cleanup;
   10904   1.9  christos 		}
   10905   1.9  christos 		if (!ispositive) {
   10906   1.3  christos 			query_addrrset(qctx, &fname, &rdataset, &sigrdataset,
   10907   1.1  christos 				       dbuf, DNS_SECTION_AUTHORITY);
   10908   1.9  christos 		}
   10909   1.1  christos 
   10910   1.1  christos 		/*
   10911   1.1  christos 		 * Replace resources which were consumed by query_addrrset.
   10912   1.1  christos 		 */
   10913   1.1  christos 		if (fname == NULL) {
   10914   1.3  christos 			dbuf = ns_client_getnamebuf(client);
   10915   1.9  christos 			if (dbuf == NULL) {
   10916   1.1  christos 				goto cleanup;
   10917   1.9  christos 			}
   10918   1.3  christos 			fname = ns_client_newname(client, dbuf, &b);
   10919   1.1  christos 		}
   10920   1.1  christos 
   10921   1.9  christos 		if (rdataset == NULL) {
   10922   1.3  christos 			rdataset = ns_client_newrdataset(client);
   10923   1.9  christos 		} else if (dns_rdataset_isassociated(rdataset)) {
   10924   1.1  christos 			dns_rdataset_disassociate(rdataset);
   10925   1.9  christos 		}
   10926   1.1  christos 
   10927   1.9  christos 		if (sigrdataset == NULL) {
   10928   1.3  christos 			sigrdataset = ns_client_newrdataset(client);
   10929   1.9  christos 		} else if (dns_rdataset_isassociated(sigrdataset)) {
   10930   1.1  christos 			dns_rdataset_disassociate(sigrdataset);
   10931   1.9  christos 		}
   10932   1.1  christos 
   10933   1.9  christos 		if (fname == NULL || rdataset == NULL || sigrdataset == NULL) {
   10934   1.1  christos 			goto cleanup;
   10935   1.9  christos 		}
   10936   1.1  christos 		/*
   10937   1.1  christos 		 * Add no qname proof.
   10938   1.1  christos 		 */
   10939   1.1  christos 		labels = dns_name_countlabels(cname) + 1;
   10940   1.9  christos 		if (dns_name_countlabels(name) == labels) {
   10941   1.8  christos 			dns_name_copynf(name, wname);
   10942   1.9  christos 		} else {
   10943   1.1  christos 			dns_name_split(name, labels, NULL, wname);
   10944   1.9  christos 		}
   10945   1.1  christos 
   10946   1.9  christos 		query_findclosestnsec3(wname, qctx->db, qctx->version, client,
   10947   1.9  christos 				       rdataset, sigrdataset, fname, false,
   10948   1.9  christos 				       NULL);
   10949   1.9  christos 		if (!dns_rdataset_isassociated(rdataset)) {
   10950   1.1  christos 			goto cleanup;
   10951   1.9  christos 		}
   10952   1.9  christos 		query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
   10953   1.9  christos 			       DNS_SECTION_AUTHORITY);
   10954   1.1  christos 
   10955   1.9  christos 		if (ispositive) {
   10956   1.1  christos 			goto cleanup;
   10957   1.9  christos 		}
   10958   1.1  christos 
   10959   1.1  christos 		/*
   10960   1.1  christos 		 * Replace resources which were consumed by query_addrrset.
   10961   1.1  christos 		 */
   10962   1.1  christos 		if (fname == NULL) {
   10963   1.3  christos 			dbuf = ns_client_getnamebuf(client);
   10964   1.9  christos 			if (dbuf == NULL) {
   10965   1.1  christos 				goto cleanup;
   10966   1.9  christos 			}
   10967   1.3  christos 			fname = ns_client_newname(client, dbuf, &b);
   10968   1.1  christos 		}
   10969   1.1  christos 
   10970   1.9  christos 		if (rdataset == NULL) {
   10971   1.3  christos 			rdataset = ns_client_newrdataset(client);
   10972   1.9  christos 		} else if (dns_rdataset_isassociated(rdataset)) {
   10973   1.1  christos 			dns_rdataset_disassociate(rdataset);
   10974   1.9  christos 		}
   10975   1.1  christos 
   10976   1.9  christos 		if (sigrdataset == NULL) {
   10977   1.3  christos 			sigrdataset = ns_client_newrdataset(client);
   10978   1.9  christos 		} else if (dns_rdataset_isassociated(sigrdataset)) {
   10979   1.1  christos 			dns_rdataset_disassociate(sigrdataset);
   10980   1.9  christos 		}
   10981   1.1  christos 
   10982   1.9  christos 		if (fname == NULL || rdataset == NULL || sigrdataset == NULL) {
   10983   1.1  christos 			goto cleanup;
   10984   1.9  christos 		}
   10985   1.1  christos 		/*
   10986   1.1  christos 		 * Add the no wildcard proof.
   10987   1.1  christos 		 */
   10988   1.9  christos 		result = dns_name_concatenate(dns_wildcardname, cname, wname,
   10989   1.9  christos 					      NULL);
   10990   1.9  christos 		if (result != ISC_R_SUCCESS) {
   10991   1.1  christos 			goto cleanup;
   10992   1.9  christos 		}
   10993   1.1  christos 
   10994   1.9  christos 		query_findclosestnsec3(wname, qctx->db, qctx->version, client,
   10995   1.9  christos 				       rdataset, sigrdataset, fname, nodata,
   10996   1.9  christos 				       NULL);
   10997   1.9  christos 		if (!dns_rdataset_isassociated(rdataset)) {
   10998   1.1  christos 			goto cleanup;
   10999   1.9  christos 		}
   11000   1.9  christos 		query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
   11001   1.9  christos 			       DNS_SECTION_AUTHORITY);
   11002   1.1  christos 
   11003   1.1  christos 		goto cleanup;
   11004   1.1  christos 	} else if (result == DNS_R_NXDOMAIN) {
   11005   1.9  christos 		if (!ispositive) {
   11006   1.1  christos 			result = dns_rdataset_first(rdataset);
   11007   1.9  christos 		}
   11008   1.1  christos 		if (result == ISC_R_SUCCESS) {
   11009   1.1  christos 			dns_rdataset_current(rdataset, &rdata);
   11010   1.1  christos 			result = dns_rdata_tostruct(&rdata, &nsec, NULL);
   11011   1.3  christos 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   11012   1.1  christos 			(void)dns_name_fullcompare(name, fname, &order,
   11013   1.1  christos 						   &olabels);
   11014   1.1  christos 			(void)dns_name_fullcompare(name, &nsec.next, &order,
   11015   1.1  christos 						   &nlabels);
   11016   1.1  christos 			/*
   11017   1.1  christos 			 * Check for a pathological condition created when
   11018   1.1  christos 			 * serving some malformed signed zones and bail out.
   11019   1.1  christos 			 */
   11020   1.9  christos 			if (dns_name_countlabels(name) == nlabels) {
   11021   1.1  christos 				goto cleanup;
   11022   1.9  christos 			}
   11023   1.1  christos 
   11024   1.9  christos 			if (olabels > nlabels) {
   11025   1.1  christos 				dns_name_split(name, olabels, NULL, wname);
   11026   1.9  christos 			} else {
   11027   1.1  christos 				dns_name_split(name, nlabels, NULL, wname);
   11028   1.9  christos 			}
   11029   1.9  christos 			result = dns_name_concatenate(dns_wildcardname, wname,
   11030   1.9  christos 						      wname, NULL);
   11031   1.9  christos 			if (result == ISC_R_SUCCESS) {
   11032   1.3  christos 				have_wname = true;
   11033   1.9  christos 			}
   11034   1.1  christos 			dns_rdata_freestruct(&nsec);
   11035   1.1  christos 		}
   11036   1.9  christos 		query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
   11037   1.9  christos 			       DNS_SECTION_AUTHORITY);
   11038   1.1  christos 	}
   11039   1.3  christos 	if (rdataset != NULL) {
   11040   1.3  christos 		ns_client_putrdataset(client, &rdataset);
   11041   1.3  christos 	}
   11042   1.3  christos 	if (sigrdataset != NULL) {
   11043   1.3  christos 		ns_client_putrdataset(client, &sigrdataset);
   11044   1.3  christos 	}
   11045   1.3  christos 	if (fname != NULL) {
   11046   1.3  christos 		ns_client_releasename(client, &fname);
   11047   1.3  christos 	}
   11048   1.1  christos 	if (have_wname) {
   11049   1.9  christos 		ispositive = true; /* prevent loop */
   11050   1.1  christos 		if (!dns_name_equal(name, wname)) {
   11051   1.1  christos 			name = wname;
   11052   1.1  christos 			goto again;
   11053   1.1  christos 		}
   11054   1.1  christos 	}
   11055   1.9  christos cleanup:
   11056   1.3  christos 	if (rdataset != NULL) {
   11057   1.3  christos 		ns_client_putrdataset(client, &rdataset);
   11058   1.3  christos 	}
   11059   1.3  christos 	if (sigrdataset != NULL) {
   11060   1.3  christos 		ns_client_putrdataset(client, &sigrdataset);
   11061   1.3  christos 	}
   11062   1.3  christos 	if (fname != NULL) {
   11063   1.3  christos 		ns_client_releasename(client, &fname);
   11064   1.3  christos 	}
   11065   1.1  christos }
   11066   1.1  christos 
   11067   1.1  christos /*%
   11068   1.1  christos  * Add NS records, and NSEC/NSEC3 wildcard proof records if needed,
   11069   1.1  christos  * to the authority section.
   11070   1.1  christos  */
   11071   1.1  christos static void
   11072   1.1  christos query_addauth(query_ctx_t *qctx) {
   11073   1.1  christos 	CCTRACE(ISC_LOG_DEBUG(3), "query_addauth");
   11074   1.1  christos 	/*
   11075   1.1  christos 	 * Add NS records to the authority section (if we haven't already
   11076   1.1  christos 	 * added them to the answer section).
   11077   1.1  christos 	 */
   11078   1.1  christos 	if (!qctx->want_restart && !NOAUTHORITY(qctx->client)) {
   11079   1.1  christos 		if (qctx->is_zone) {
   11080   1.1  christos 			if (!qctx->answer_has_ns) {
   11081   1.1  christos 				(void)query_addns(qctx);
   11082   1.1  christos 			}
   11083   1.1  christos 		} else if (!qctx->answer_has_ns &&
   11084   1.9  christos 			   qctx->qtype != dns_rdatatype_ns) {
   11085   1.1  christos 			if (qctx->fname != NULL) {
   11086   1.3  christos 				ns_client_releasename(qctx->client,
   11087   1.3  christos 						      &qctx->fname);
   11088   1.1  christos 			}
   11089   1.1  christos 			query_addbestns(qctx);
   11090   1.1  christos 		}
   11091   1.1  christos 	}
   11092   1.1  christos 
   11093   1.1  christos 	/*
   11094   1.1  christos 	 * Add NSEC records to the authority section if they're needed for
   11095   1.1  christos 	 * DNSSEC wildcard proofs.
   11096   1.1  christos 	 */
   11097   1.9  christos 	if (qctx->need_wildcardproof && dns_db_issecure(qctx->db)) {
   11098   1.3  christos 		query_addwildcardproof(qctx, true, false);
   11099   1.9  christos 	}
   11100   1.1  christos }
   11101   1.1  christos 
   11102   1.1  christos /*
   11103   1.1  christos  * Find the sort order of 'rdata' in the topology-like
   11104   1.1  christos  * ACL forming the second element in a 2-element top-level
   11105   1.1  christos  * sortlist statement.
   11106   1.1  christos  */
   11107   1.1  christos static int
   11108   1.1  christos query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) {
   11109   1.1  christos 	isc_netaddr_t netaddr;
   11110   1.1  christos 
   11111   1.9  christos 	if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) {
   11112   1.1  christos 		return (INT_MAX);
   11113   1.9  christos 	}
   11114   1.1  christos 	return (ns_sortlist_addrorder2(&netaddr, arg));
   11115   1.1  christos }
   11116   1.1  christos 
   11117   1.1  christos /*
   11118   1.1  christos  * Find the sort order of 'rdata' in the matching element
   11119   1.1  christos  * of a 1-element top-level sortlist statement.
   11120   1.1  christos  */
   11121   1.1  christos static int
   11122   1.1  christos query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) {
   11123   1.1  christos 	isc_netaddr_t netaddr;
   11124   1.1  christos 
   11125   1.9  christos 	if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) {
   11126   1.1  christos 		return (INT_MAX);
   11127   1.9  christos 	}
   11128   1.1  christos 	return (ns_sortlist_addrorder1(&netaddr, arg));
   11129   1.1  christos }
   11130   1.1  christos 
   11131   1.1  christos /*
   11132   1.1  christos  * Find the sortlist statement that applies to 'client' and set up
   11133   1.1  christos  * the sortlist info in in client->message appropriately.
   11134   1.1  christos  */
   11135   1.1  christos static void
   11136   1.1  christos query_setup_sortlist(query_ctx_t *qctx) {
   11137   1.1  christos 	isc_netaddr_t netaddr;
   11138   1.1  christos 	ns_client_t *client = qctx->client;
   11139   1.9  christos 	dns_aclenv_t *env =
   11140   1.9  christos 		ns_interfacemgr_getaclenv(client->manager->interface->mgr);
   11141   1.1  christos 	const void *order_arg = NULL;
   11142   1.1  christos 
   11143   1.1  christos 	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
   11144   1.9  christos 	switch (ns_sortlist_setup(client->view->sortlist, env, &netaddr,
   11145   1.9  christos 				  &order_arg)) {
   11146   1.1  christos 	case NS_SORTLISTTYPE_1ELEMENT:
   11147   1.1  christos 		dns_message_setsortorder(client->message,
   11148   1.9  christos 					 query_sortlist_order_1element, env,
   11149   1.9  christos 					 NULL, order_arg);
   11150   1.1  christos 		break;
   11151   1.1  christos 	case NS_SORTLISTTYPE_2ELEMENT:
   11152   1.1  christos 		dns_message_setsortorder(client->message,
   11153   1.9  christos 					 query_sortlist_order_2element, env,
   11154   1.9  christos 					 order_arg, NULL);
   11155   1.1  christos 		break;
   11156   1.1  christos 	case NS_SORTLISTTYPE_NONE:
   11157   1.1  christos 		break;
   11158   1.1  christos 	default:
   11159   1.1  christos 		INSIST(0);
   11160   1.3  christos 		ISC_UNREACHABLE();
   11161   1.1  christos 	}
   11162   1.1  christos }
   11163   1.1  christos 
   11164   1.1  christos /*
   11165   1.1  christos  * When sending a referral, if the answer to the question is
   11166   1.1  christos  * in the glue, sort it to the start of the additional section.
   11167   1.1  christos  */
   11168   1.1  christos static inline void
   11169   1.1  christos query_glueanswer(query_ctx_t *qctx) {
   11170   1.1  christos 	const dns_namelist_t *secs = qctx->client->message->sections;
   11171   1.1  christos 	const dns_section_t section = DNS_SECTION_ADDITIONAL;
   11172   1.1  christos 	dns_name_t *name;
   11173   1.1  christos 	dns_message_t *msg;
   11174   1.1  christos 	dns_rdataset_t *rdataset = NULL;
   11175   1.1  christos 
   11176   1.1  christos 	if (!ISC_LIST_EMPTY(secs[DNS_SECTION_ANSWER]) ||
   11177   1.1  christos 	    qctx->client->message->rcode != dns_rcode_noerror ||
   11178   1.1  christos 	    (qctx->qtype != dns_rdatatype_a &&
   11179   1.1  christos 	     qctx->qtype != dns_rdatatype_aaaa))
   11180   1.1  christos 	{
   11181   1.1  christos 		return;
   11182   1.1  christos 	}
   11183   1.1  christos 
   11184   1.1  christos 	msg = qctx->client->message;
   11185   1.9  christos 	for (name = ISC_LIST_HEAD(msg->sections[section]); name != NULL;
   11186   1.1  christos 	     name = ISC_LIST_NEXT(name, link))
   11187   1.9  christos 	{
   11188   1.1  christos 		if (dns_name_equal(name, qctx->client->query.qname)) {
   11189   1.1  christos 			for (rdataset = ISC_LIST_HEAD(name->list);
   11190   1.1  christos 			     rdataset != NULL;
   11191   1.1  christos 			     rdataset = ISC_LIST_NEXT(rdataset, link))
   11192   1.9  christos 			{
   11193   1.9  christos 				if (rdataset->type == qctx->qtype) {
   11194   1.1  christos 					break;
   11195   1.9  christos 				}
   11196   1.9  christos 			}
   11197   1.1  christos 			break;
   11198   1.1  christos 		}
   11199   1.9  christos 	}
   11200   1.1  christos 	if (rdataset != NULL) {
   11201   1.1  christos 		ISC_LIST_UNLINK(msg->sections[section], name, link);
   11202   1.1  christos 		ISC_LIST_PREPEND(msg->sections[section], name, link);
   11203   1.1  christos 		ISC_LIST_UNLINK(name->list, rdataset, link);
   11204   1.1  christos 		ISC_LIST_PREPEND(name->list, rdataset, link);
   11205   1.1  christos 		rdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
   11206   1.1  christos 	}
   11207   1.1  christos }
   11208   1.1  christos 
   11209   1.3  christos isc_result_t
   11210   1.3  christos ns_query_done(query_ctx_t *qctx) {
   11211   1.3  christos 	isc_result_t result;
   11212   1.1  christos 	const dns_namelist_t *secs = qctx->client->message->sections;
   11213  1.11  christos 	bool query_stale_only;
   11214   1.1  christos 
   11215   1.3  christos 	CCTRACE(ISC_LOG_DEBUG(3), "ns_query_done");
   11216   1.3  christos 
   11217   1.3  christos 	CALL_HOOK(NS_QUERY_DONE_BEGIN, qctx);
   11218   1.1  christos 
   11219   1.1  christos 	/*
   11220   1.1  christos 	 * General cleanup.
   11221   1.1  christos 	 */
   11222   1.1  christos 	qctx->rpz_st = qctx->client->query.rpz_st;
   11223   1.1  christos 	if (qctx->rpz_st != NULL &&
   11224   1.9  christos 	    (qctx->rpz_st->state & DNS_RPZ_RECURSING) == 0) {
   11225   1.1  christos 		rpz_match_clear(qctx->rpz_st);
   11226   1.1  christos 		qctx->rpz_st->state &= ~DNS_RPZ_DONE_QNAME;
   11227   1.1  christos 	}
   11228   1.1  christos 
   11229   1.1  christos 	qctx_clean(qctx);
   11230   1.1  christos 	qctx_freedata(qctx);
   11231   1.1  christos 
   11232   1.6  christos 	if (qctx->client->query.gluedb != NULL) {
   11233   1.6  christos 		dns_db_detach(&qctx->client->query.gluedb);
   11234   1.6  christos 	}
   11235   1.6  christos 
   11236   1.1  christos 	/*
   11237   1.1  christos 	 * Clear the AA bit if we're not authoritative.
   11238   1.1  christos 	 */
   11239   1.1  christos 	if (qctx->client->query.restarts == 0 && !qctx->authoritative) {
   11240   1.1  christos 		qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA;
   11241   1.1  christos 	}
   11242   1.1  christos 
   11243   1.1  christos 	/*
   11244   1.1  christos 	 * Do we need to restart the query (e.g. for CNAME chaining)?
   11245   1.1  christos 	 */
   11246   1.1  christos 	if (qctx->want_restart && qctx->client->query.restarts < MAX_RESTARTS) {
   11247   1.1  christos 		qctx->client->query.restarts++;
   11248   1.1  christos 		return (ns__query_start(qctx));
   11249   1.1  christos 	}
   11250   1.1  christos 
   11251   1.1  christos 	if (qctx->result != ISC_R_SUCCESS &&
   11252   1.1  christos 	    (!PARTIALANSWER(qctx->client) || WANTRECURSION(qctx->client) ||
   11253   1.1  christos 	     qctx->result == DNS_R_DROP))
   11254   1.1  christos 	{
   11255   1.1  christos 		if (qctx->result == DNS_R_DUPLICATE ||
   11256   1.9  christos 		    qctx->result == DNS_R_DROP) {
   11257   1.1  christos 			/*
   11258   1.1  christos 			 * This was a duplicate query that we are
   11259   1.1  christos 			 * recursing on or the result of rate limiting.
   11260   1.1  christos 			 * Don't send a response now for a duplicate query,
   11261   1.1  christos 			 * because the original will still cause a response.
   11262   1.1  christos 			 */
   11263   1.1  christos 			query_next(qctx->client, qctx->result);
   11264   1.1  christos 		} else {
   11265   1.1  christos 			/*
   11266   1.1  christos 			 * If we don't have any answer to give the client,
   11267   1.1  christos 			 * or if the client requested recursion and thus wanted
   11268   1.1  christos 			 * the complete answer, send an error response.
   11269   1.1  christos 			 */
   11270   1.1  christos 			INSIST(qctx->line >= 0);
   11271   1.1  christos 			query_error(qctx->client, qctx->result, qctx->line);
   11272   1.1  christos 		}
   11273   1.1  christos 
   11274   1.3  christos 		qctx->detach_client = true;
   11275   1.1  christos 		return (qctx->result);
   11276   1.1  christos 	}
   11277   1.1  christos 
   11278   1.1  christos 	/*
   11279   1.1  christos 	 * If we're recursing then just return; the query will
   11280   1.1  christos 	 * resume when recursion ends.
   11281   1.1  christos 	 */
   11282  1.11  christos 	if (RECURSING(qctx->client) &&
   11283  1.11  christos 	    (!QUERY_STALEONLY(&qctx->client->query) ||
   11284  1.11  christos 	     ((qctx->options & DNS_GETDB_STALEFIRST) != 0)))
   11285  1.11  christos 	{
   11286   1.1  christos 		return (qctx->result);
   11287   1.1  christos 	}
   11288   1.1  christos 
   11289   1.1  christos 	/*
   11290   1.1  christos 	 * We are done.  Set up sortlist data for the message
   11291   1.1  christos 	 * rendering code, sort the answer to the front of the
   11292   1.1  christos 	 * additional section if necessary, make a final tweak
   11293   1.1  christos 	 * to the AA bit if the auth-nxdomain config option
   11294   1.1  christos 	 * says so, then render and send the response.
   11295   1.1  christos 	 */
   11296  1.11  christos 	if (!QUERY_ANSWERED(qctx->client)) {
   11297  1.11  christos 		query_setup_sortlist(qctx);
   11298  1.11  christos 		query_glueanswer(qctx);
   11299  1.11  christos 	}
   11300   1.1  christos 
   11301   1.1  christos 	if (qctx->client->message->rcode == dns_rcode_nxdomain &&
   11302  1.10  christos 	    qctx->view->auth_nxdomain)
   11303   1.1  christos 	{
   11304   1.1  christos 		qctx->client->message->flags |= DNS_MESSAGEFLAG_AA;
   11305   1.1  christos 	}
   11306   1.1  christos 
   11307   1.1  christos 	/*
   11308   1.1  christos 	 * If the response is somehow unexpected for the client and this
   11309   1.1  christos 	 * is a result of recursion, return an error to the caller
   11310   1.1  christos 	 * to indicate it may need to be logged.
   11311   1.1  christos 	 */
   11312   1.1  christos 	if (qctx->resuming &&
   11313   1.1  christos 	    (ISC_LIST_EMPTY(secs[DNS_SECTION_ANSWER]) ||
   11314   1.1  christos 	     qctx->client->message->rcode != dns_rcode_noerror))
   11315   1.1  christos 	{
   11316   1.1  christos 		qctx->result = ISC_R_FAILURE;
   11317   1.1  christos 	}
   11318   1.1  christos 
   11319   1.3  christos 	CALL_HOOK(NS_QUERY_DONE_SEND, qctx);
   11320   1.3  christos 
   11321  1.11  christos 	/*
   11322  1.11  christos 	 * Client may have been detached after query_send(), so
   11323  1.11  christos 	 * we test and store the flag state here, for safety.
   11324  1.11  christos 	 */
   11325  1.11  christos 	query_stale_only = QUERY_STALEONLY(&qctx->client->query);
   11326   1.1  christos 	query_send(qctx->client);
   11327   1.1  christos 
   11328  1.11  christos 	if (!query_stale_only) {
   11329  1.11  christos 		qctx->detach_client = true;
   11330  1.11  christos 	}
   11331   1.1  christos 	return (qctx->result);
   11332   1.3  christos 
   11333   1.9  christos cleanup:
   11334   1.3  christos 	return (result);
   11335   1.1  christos }
   11336   1.1  christos 
   11337   1.1  christos static inline void
   11338   1.1  christos log_tat(ns_client_t *client) {
   11339   1.1  christos 	char namebuf[DNS_NAME_FORMATSIZE];
   11340   1.1  christos 	char clientbuf[ISC_NETADDR_FORMATSIZE];
   11341   1.3  christos 	char classbuf[DNS_RDATACLASS_FORMATSIZE];
   11342   1.1  christos 	isc_netaddr_t netaddr;
   11343   1.1  christos 	char *tags = NULL;
   11344   1.1  christos 	size_t taglen = 0;
   11345   1.1  christos 
   11346   1.1  christos 	if (!isc_log_wouldlog(ns_lctx, ISC_LOG_INFO)) {
   11347   1.1  christos 		return;
   11348   1.1  christos 	}
   11349   1.1  christos 
   11350   1.1  christos 	if ((client->query.qtype != dns_rdatatype_null ||
   11351   1.1  christos 	     !dns_name_istat(client->query.qname)) &&
   11352   1.1  christos 	    (client->keytag == NULL ||
   11353   1.1  christos 	     client->query.qtype != dns_rdatatype_dnskey))
   11354   1.1  christos 	{
   11355   1.1  christos 		return;
   11356   1.1  christos 	}
   11357   1.1  christos 
   11358   1.1  christos 	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
   11359   1.1  christos 	dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
   11360   1.3  christos 	isc_netaddr_format(&netaddr, clientbuf, sizeof(clientbuf));
   11361   1.3  christos 	dns_rdataclass_format(client->view->rdclass, classbuf,
   11362   1.3  christos 			      sizeof(classbuf));
   11363   1.1  christos 
   11364   1.1  christos 	if (client->query.qtype == dns_rdatatype_dnskey) {
   11365   1.3  christos 		uint16_t keytags = client->keytag_len / 2;
   11366   1.1  christos 		size_t len = taglen = sizeof("65000") * keytags + 1;
   11367   1.1  christos 		char *cp = tags = isc_mem_get(client->mctx, taglen);
   11368   1.1  christos 		int i = 0;
   11369   1.1  christos 
   11370   1.1  christos 		INSIST(client->keytag != NULL);
   11371   1.1  christos 		if (tags != NULL) {
   11372   1.1  christos 			while (keytags-- > 0U) {
   11373   1.1  christos 				int n;
   11374   1.3  christos 				uint16_t keytag;
   11375   1.1  christos 				keytag = (client->keytag[i * 2] << 8) |
   11376   1.1  christos 					 client->keytag[i * 2 + 1];
   11377   1.1  christos 				n = snprintf(cp, len, " %u", keytag);
   11378   1.1  christos 				if (n > 0 && (size_t)n <= len) {
   11379   1.1  christos 					cp += n;
   11380   1.1  christos 					len -= n;
   11381   1.1  christos 					i++;
   11382   1.1  christos 				} else {
   11383   1.1  christos 					break;
   11384   1.1  christos 				}
   11385   1.1  christos 			}
   11386   1.1  christos 		}
   11387   1.1  christos 	}
   11388   1.1  christos 
   11389   1.1  christos 	isc_log_write(ns_lctx, NS_LOGCATEGORY_TAT, NS_LOGMODULE_QUERY,
   11390   1.1  christos 		      ISC_LOG_INFO, "trust-anchor-telemetry '%s/%s' from %s%s",
   11391   1.9  christos 		      namebuf, classbuf, clientbuf, tags != NULL ? tags : "");
   11392   1.1  christos 	if (tags != NULL) {
   11393   1.1  christos 		isc_mem_put(client->mctx, tags, taglen);
   11394   1.1  christos 	}
   11395   1.1  christos }
   11396   1.1  christos 
   11397   1.1  christos static inline void
   11398   1.1  christos log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
   11399   1.1  christos 	char namebuf[DNS_NAME_FORMATSIZE];
   11400   1.3  christos 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   11401   1.3  christos 	char classbuf[DNS_RDATACLASS_FORMATSIZE];
   11402   1.1  christos 	char onbuf[ISC_NETADDR_FORMATSIZE];
   11403   1.1  christos 	char ecsbuf[DNS_ECS_FORMATSIZE + sizeof(" [ECS ]") - 1] = { 0 };
   11404   1.1  christos 	char ednsbuf[sizeof("E(65535)")] = { 0 };
   11405   1.1  christos 	dns_rdataset_t *rdataset;
   11406   1.1  christos 	int level = ISC_LOG_INFO;
   11407   1.1  christos 
   11408   1.9  christos 	if (!isc_log_wouldlog(ns_lctx, level)) {
   11409   1.1  christos 		return;
   11410   1.9  christos 	}
   11411   1.1  christos 
   11412   1.1  christos 	rdataset = ISC_LIST_HEAD(client->query.qname->list);
   11413   1.1  christos 	INSIST(rdataset != NULL);
   11414   1.1  christos 	dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
   11415   1.3  christos 	dns_rdataclass_format(rdataset->rdclass, classbuf, sizeof(classbuf));
   11416   1.3  christos 	dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
   11417   1.1  christos 	isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf));
   11418   1.1  christos 
   11419   1.9  christos 	if (client->ednsversion >= 0) {
   11420   1.1  christos 		snprintf(ednsbuf, sizeof(ednsbuf), "E(%hd)",
   11421   1.1  christos 			 client->ednsversion);
   11422   1.9  christos 	}
   11423   1.1  christos 
   11424   1.1  christos 	if (HAVEECS(client)) {
   11425   1.1  christos 		strlcpy(ecsbuf, " [ECS ", sizeof(ecsbuf));
   11426   1.1  christos 		dns_ecs_format(&client->ecs, ecsbuf + 6, sizeof(ecsbuf) - 6);
   11427   1.1  christos 		strlcat(ecsbuf, "]", sizeof(ecsbuf));
   11428   1.1  christos 	}
   11429   1.1  christos 
   11430   1.9  christos 	ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, level,
   11431   1.9  christos 		      "query: %s %s %s %s%s%s%s%s%s%s (%s)%s", namebuf,
   11432   1.9  christos 		      classbuf, typebuf, WANTRECURSION(client) ? "+" : "-",
   11433   1.1  christos 		      (client->signer != NULL) ? "S" : "", ednsbuf,
   11434   1.1  christos 		      TCP(client) ? "T" : "",
   11435   1.1  christos 		      ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
   11436   1.1  christos 		      ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "",
   11437  1.11  christos 		      HAVECOOKIE(client)   ? "V"
   11438  1.11  christos 		      : WANTCOOKIE(client) ? "K"
   11439  1.11  christos 					   : "",
   11440   1.1  christos 		      onbuf, ecsbuf);
   11441   1.1  christos }
   11442   1.1  christos 
   11443   1.1  christos static inline void
   11444   1.1  christos log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) {
   11445   1.1  christos 	char namebuf[DNS_NAME_FORMATSIZE];
   11446   1.3  christos 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   11447   1.3  christos 	char classbuf[DNS_RDATACLASS_FORMATSIZE];
   11448   1.1  christos 	const char *namep, *typep, *classp, *sep1, *sep2;
   11449   1.1  christos 	dns_rdataset_t *rdataset;
   11450   1.1  christos 
   11451   1.9  christos 	if (!isc_log_wouldlog(ns_lctx, level)) {
   11452   1.1  christos 		return;
   11453   1.9  christos 	}
   11454   1.1  christos 
   11455   1.1  christos 	namep = typep = classp = sep1 = sep2 = "";
   11456   1.1  christos 
   11457   1.1  christos 	/*
   11458   1.1  christos 	 * Query errors can happen for various reasons.  In some cases we cannot
   11459   1.1  christos 	 * even assume the query contains a valid question section, so we should
   11460   1.1  christos 	 * expect exceptional cases.
   11461   1.1  christos 	 */
   11462   1.1  christos 	if (client->query.origqname != NULL) {
   11463   1.1  christos 		dns_name_format(client->query.origqname, namebuf,
   11464   1.1  christos 				sizeof(namebuf));
   11465   1.1  christos 		namep = namebuf;
   11466   1.1  christos 		sep1 = " for ";
   11467   1.1  christos 
   11468   1.1  christos 		rdataset = ISC_LIST_HEAD(client->query.origqname->list);
   11469   1.1  christos 		if (rdataset != NULL) {
   11470   1.3  christos 			dns_rdataclass_format(rdataset->rdclass, classbuf,
   11471   1.3  christos 					      sizeof(classbuf));
   11472   1.3  christos 			classp = classbuf;
   11473   1.3  christos 			dns_rdatatype_format(rdataset->type, typebuf,
   11474   1.3  christos 					     sizeof(typebuf));
   11475   1.3  christos 			typep = typebuf;
   11476   1.1  christos 			sep2 = "/";
   11477   1.1  christos 		}
   11478   1.1  christos 	}
   11479   1.1  christos 
   11480   1.1  christos 	ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY,
   11481   1.1  christos 		      level, "query failed (%s)%s%s%s%s%s%s at %s:%d",
   11482   1.9  christos 		      isc_result_totext(result), sep1, namep, sep2, classp,
   11483   1.9  christos 		      sep2, typep, __FILE__, line);
   11484   1.1  christos }
   11485   1.1  christos 
   11486   1.1  christos void
   11487  1.11  christos ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) {
   11488   1.1  christos 	isc_result_t result;
   11489   1.8  christos 	dns_message_t *message;
   11490   1.1  christos 	dns_rdataset_t *rdataset;
   11491   1.1  christos 	dns_rdatatype_t qtype;
   11492   1.8  christos 	unsigned int saved_extflags;
   11493   1.8  christos 	unsigned int saved_flags;
   11494   1.1  christos 
   11495   1.1  christos 	REQUIRE(NS_CLIENT_VALID(client));
   11496   1.1  christos 
   11497  1.11  christos 	/*
   11498  1.11  christos 	 * Attach to the request handle
   11499  1.11  christos 	 */
   11500  1.11  christos 	isc_nmhandle_attach(handle, &client->reqhandle);
   11501  1.11  christos 
   11502   1.8  christos 	message = client->message;
   11503   1.8  christos 	saved_extflags = client->extflags;
   11504   1.8  christos 	saved_flags = client->message->flags;
   11505   1.8  christos 
   11506   1.1  christos 	CTRACE(ISC_LOG_DEBUG(3), "ns_query_start");
   11507   1.1  christos 
   11508   1.1  christos 	/*
   11509   1.1  christos 	 * Ensure that appropriate cleanups occur.
   11510   1.1  christos 	 */
   11511   1.9  christos 	client->cleanup = query_cleanup;
   11512   1.1  christos 
   11513   1.9  christos 	if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) {
   11514   1.9  christos 		client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
   11515   1.1  christos 	}
   11516   1.1  christos 
   11517   1.9  christos 	if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0) {
   11518   1.1  christos 		client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
   11519   1.9  christos 	}
   11520   1.1  christos 
   11521   1.1  christos 	switch (client->view->minimalresponses) {
   11522   1.1  christos 	case dns_minimal_no:
   11523   1.1  christos 		break;
   11524   1.1  christos 	case dns_minimal_yes:
   11525   1.1  christos 		client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
   11526   1.1  christos 					     NS_QUERYATTR_NOADDITIONAL);
   11527   1.1  christos 		break;
   11528   1.1  christos 	case dns_minimal_noauth:
   11529   1.1  christos 		client->query.attributes |= NS_QUERYATTR_NOAUTHORITY;
   11530   1.1  christos 		break;
   11531   1.1  christos 	case dns_minimal_noauthrec:
   11532   1.9  christos 		if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) {
   11533   1.1  christos 			client->query.attributes |= NS_QUERYATTR_NOAUTHORITY;
   11534   1.9  christos 		}
   11535   1.1  christos 		break;
   11536   1.1  christos 	}
   11537   1.1  christos 
   11538   1.1  christos 	if (client->view->cachedb == NULL || !client->view->recursion) {
   11539   1.1  christos 		/*
   11540   1.1  christos 		 * We don't have a cache.  Turn off cache support and
   11541   1.1  christos 		 * recursion.
   11542   1.1  christos 		 */
   11543   1.9  christos 		client->query.attributes &= ~(NS_QUERYATTR_RECURSIONOK |
   11544   1.9  christos 					      NS_QUERYATTR_CACHEOK);
   11545   1.1  christos 		client->attributes |= NS_CLIENTATTR_NOSETFC;
   11546   1.1  christos 	} else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
   11547   1.9  christos 		   (message->flags & DNS_MESSAGEFLAG_RD) == 0)
   11548   1.9  christos 	{
   11549   1.1  christos 		/*
   11550   1.1  christos 		 * If the client isn't allowed to recurse (due to
   11551   1.1  christos 		 * "recursion no", the allow-recursion ACL, or the
   11552   1.1  christos 		 * lack of a resolver in this view), or if it
   11553   1.1  christos 		 * doesn't want recursion, turn recursion off.
   11554   1.1  christos 		 */
   11555   1.1  christos 		client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
   11556   1.1  christos 		client->attributes |= NS_CLIENTATTR_NOSETFC;
   11557   1.1  christos 	}
   11558   1.1  christos 
   11559   1.1  christos 	/*
   11560   1.1  christos 	 * Check for multiple question queries, since edns1 is dead.
   11561   1.1  christos 	 */
   11562   1.1  christos 	if (message->counts[DNS_SECTION_QUESTION] > 1) {
   11563   1.1  christos 		query_error(client, DNS_R_FORMERR, __LINE__);
   11564   1.1  christos 		return;
   11565   1.1  christos 	}
   11566   1.1  christos 
   11567   1.1  christos 	/*
   11568   1.1  christos 	 * Get the question name.
   11569   1.1  christos 	 */
   11570   1.1  christos 	result = dns_message_firstname(message, DNS_SECTION_QUESTION);
   11571   1.1  christos 	if (result != ISC_R_SUCCESS) {
   11572   1.1  christos 		query_error(client, result, __LINE__);
   11573   1.1  christos 		return;
   11574   1.1  christos 	}
   11575   1.1  christos 	dns_message_currentname(message, DNS_SECTION_QUESTION,
   11576   1.1  christos 				&client->query.qname);
   11577   1.1  christos 	client->query.origqname = client->query.qname;
   11578   1.1  christos 	result = dns_message_nextname(message, DNS_SECTION_QUESTION);
   11579   1.1  christos 	if (result != ISC_R_NOMORE) {
   11580   1.1  christos 		if (result == ISC_R_SUCCESS) {
   11581   1.1  christos 			/*
   11582   1.1  christos 			 * There's more than one QNAME in the question
   11583   1.1  christos 			 * section.
   11584   1.1  christos 			 */
   11585   1.1  christos 			query_error(client, DNS_R_FORMERR, __LINE__);
   11586   1.9  christos 		} else {
   11587   1.1  christos 			query_error(client, result, __LINE__);
   11588   1.9  christos 		}
   11589   1.1  christos 		return;
   11590   1.1  christos 	}
   11591   1.1  christos 
   11592   1.9  christos 	if ((client->sctx->options & NS_SERVER_LOGQUERIES) != 0) {
   11593   1.1  christos 		log_query(client, saved_flags, saved_extflags);
   11594   1.9  christos 	}
   11595   1.1  christos 
   11596   1.1  christos 	/*
   11597   1.1  christos 	 * Check for meta-queries like IXFR and AXFR.
   11598   1.1  christos 	 */
   11599   1.1  christos 	rdataset = ISC_LIST_HEAD(client->query.qname->list);
   11600   1.1  christos 	INSIST(rdataset != NULL);
   11601   1.1  christos 	client->query.qtype = qtype = rdataset->type;
   11602   1.1  christos 	dns_rdatatypestats_increment(client->sctx->rcvquerystats, qtype);
   11603   1.1  christos 
   11604   1.1  christos 	log_tat(client);
   11605   1.1  christos 
   11606   1.1  christos 	if (dns_rdatatype_ismeta(qtype)) {
   11607   1.1  christos 		switch (qtype) {
   11608   1.1  christos 		case dns_rdatatype_any:
   11609   1.1  christos 			break; /* Let the query logic handle it. */
   11610   1.1  christos 		case dns_rdatatype_ixfr:
   11611   1.1  christos 		case dns_rdatatype_axfr:
   11612   1.1  christos 			ns_xfr_start(client, rdataset->type);
   11613   1.1  christos 			return;
   11614   1.1  christos 		case dns_rdatatype_maila:
   11615   1.1  christos 		case dns_rdatatype_mailb:
   11616   1.1  christos 			query_error(client, DNS_R_NOTIMP, __LINE__);
   11617   1.1  christos 			return;
   11618   1.1  christos 		case dns_rdatatype_tkey:
   11619   1.9  christos 			result = dns_tkey_processquery(
   11620   1.9  christos 				client->message, client->sctx->tkeyctx,
   11621   1.9  christos 				client->view->dynamickeys);
   11622   1.9  christos 			if (result == ISC_R_SUCCESS) {
   11623   1.1  christos 				query_send(client);
   11624   1.9  christos 			} else {
   11625   1.1  christos 				query_error(client, result, __LINE__);
   11626   1.9  christos 			}
   11627   1.1  christos 			return;
   11628   1.1  christos 		default: /* TSIG, etc. */
   11629   1.1  christos 			query_error(client, DNS_R_FORMERR, __LINE__);
   11630   1.1  christos 			return;
   11631   1.1  christos 		}
   11632   1.1  christos 	}
   11633   1.1  christos 
   11634   1.1  christos 	/*
   11635   1.1  christos 	 * Turn on minimal response for (C)DNSKEY and (C)DS queries.
   11636   1.1  christos 	 */
   11637   1.1  christos 	if (qtype == dns_rdatatype_dnskey || qtype == dns_rdatatype_ds ||
   11638   1.1  christos 	    qtype == dns_rdatatype_cdnskey || qtype == dns_rdatatype_cds)
   11639   1.1  christos 	{
   11640   1.1  christos 		client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
   11641   1.1  christos 					     NS_QUERYATTR_NOADDITIONAL);
   11642  1.11  christos 	} else if (qtype == dns_rdatatype_ns) {
   11643  1.11  christos 		/*
   11644  1.11  christos 		 * Always turn on additional records for NS queries.
   11645  1.11  christos 		 */
   11646  1.11  christos 		client->query.attributes &= ~(NS_QUERYATTR_NOAUTHORITY |
   11647  1.11  christos 					      NS_QUERYATTR_NOADDITIONAL);
   11648   1.1  christos 	}
   11649   1.1  christos 
   11650   1.1  christos 	/*
   11651   1.1  christos 	 * Maybe turn on minimal responses for ANY queries.
   11652   1.1  christos 	 */
   11653   1.9  christos 	if (qtype == dns_rdatatype_any && client->view->minimal_any &&
   11654   1.9  christos 	    !TCP(client)) {
   11655   1.1  christos 		client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
   11656   1.1  christos 					     NS_QUERYATTR_NOADDITIONAL);
   11657   1.9  christos 	}
   11658   1.1  christos 
   11659   1.1  christos 	/*
   11660   1.1  christos 	 * Turn on minimal responses for EDNS/UDP bufsize 512 queries.
   11661   1.1  christos 	 */
   11662   1.1  christos 	if (client->ednsversion >= 0 && client->udpsize <= 512U && !TCP(client))
   11663   1.9  christos 	{
   11664   1.1  christos 		client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
   11665   1.1  christos 					     NS_QUERYATTR_NOADDITIONAL);
   11666   1.9  christos 	}
   11667   1.1  christos 
   11668   1.1  christos 	/*
   11669   1.1  christos 	 * If the client has requested that DNSSEC checking be disabled,
   11670   1.1  christos 	 * allow lookups to return pending data and instruct the resolver
   11671   1.1  christos 	 * to return data before validation has completed.
   11672   1.1  christos 	 *
   11673   1.1  christos 	 * We don't need to set DNS_DBFIND_PENDINGOK when validation is
   11674   1.1  christos 	 * disabled as there will be no pending data.
   11675   1.1  christos 	 */
   11676   1.3  christos 	if ((message->flags & DNS_MESSAGEFLAG_CD) != 0 ||
   11677   1.9  christos 	    qtype == dns_rdatatype_rrsig) {
   11678   1.1  christos 		client->query.dboptions |= DNS_DBFIND_PENDINGOK;
   11679   1.1  christos 		client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
   11680   1.9  christos 	} else if (!client->view->enablevalidation) {
   11681   1.1  christos 		client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
   11682   1.9  christos 	}
   11683   1.1  christos 
   11684   1.3  christos 	if (client->view->qminimization) {
   11685   1.3  christos 		client->query.fetchoptions |= DNS_FETCHOPT_QMINIMIZE |
   11686   1.9  christos 					      DNS_FETCHOPT_QMIN_SKIP_IP6A;
   11687   1.3  christos 		if (client->view->qmin_strict) {
   11688   1.3  christos 			client->query.fetchoptions |= DNS_FETCHOPT_QMIN_STRICT;
   11689   1.6  christos 		} else {
   11690   1.6  christos 			client->query.fetchoptions |= DNS_FETCHOPT_QMIN_USE_A;
   11691   1.3  christos 		}
   11692   1.3  christos 	}
   11693   1.3  christos 
   11694   1.1  christos 	/*
   11695   1.1  christos 	 * Allow glue NS records to be added to the authority section
   11696   1.1  christos 	 * if the answer is secure.
   11697   1.1  christos 	 */
   11698   1.3  christos 	if ((message->flags & DNS_MESSAGEFLAG_CD) != 0) {
   11699   1.1  christos 		client->query.attributes &= ~NS_QUERYATTR_SECURE;
   11700   1.3  christos 	}
   11701   1.1  christos 
   11702   1.1  christos 	/*
   11703   1.1  christos 	 * Set NS_CLIENTATTR_WANTAD if the client has set AD in the query.
   11704   1.1  christos 	 * This allows AD to be returned on queries without DO set.
   11705   1.1  christos 	 */
   11706   1.9  christos 	if ((message->flags & DNS_MESSAGEFLAG_AD) != 0) {
   11707   1.1  christos 		client->attributes |= NS_CLIENTATTR_WANTAD;
   11708   1.9  christos 	}
   11709   1.1  christos 
   11710   1.1  christos 	/*
   11711   1.1  christos 	 * This is an ordinary query.
   11712   1.1  christos 	 */
   11713   1.3  christos 	result = dns_message_reply(message, true);
   11714   1.1  christos 	if (result != ISC_R_SUCCESS) {
   11715   1.1  christos 		query_next(client, result);
   11716   1.1  christos 		return;
   11717   1.1  christos 	}
   11718   1.1  christos 
   11719   1.1  christos 	/*
   11720   1.1  christos 	 * Assume authoritative response until it is known to be
   11721   1.1  christos 	 * otherwise.
   11722   1.1  christos 	 *
   11723   1.1  christos 	 * If "-T noaa" has been set on the command line don't set
   11724   1.1  christos 	 * AA on authoritative answers.
   11725   1.1  christos 	 */
   11726   1.9  christos 	if ((client->sctx->options & NS_SERVER_NOAA) == 0) {
   11727   1.1  christos 		message->flags |= DNS_MESSAGEFLAG_AA;
   11728   1.9  christos 	}
   11729   1.1  christos 
   11730   1.1  christos 	/*
   11731   1.1  christos 	 * Set AD.  We must clear it if we add non-validated data to a
   11732   1.1  christos 	 * response.
   11733   1.1  christos 	 */
   11734   1.9  christos 	if (WANTDNSSEC(client) || WANTAD(client)) {
   11735   1.1  christos 		message->flags |= DNS_MESSAGEFLAG_AD;
   11736   1.9  christos 	}
   11737   1.1  christos 
   11738   1.9  christos 	(void)query_setup(client, qtype);
   11739   1.1  christos }
   11740