1/*	$NetBSD: query.h,v 1.8 2024/02/21 22:52:46 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16#pragma once
17
18/*! \file */
19
20#include <stdbool.h>
21
22#include <isc/buffer.h>
23#include <isc/netaddr.h>
24#include <isc/task.h>
25#include <isc/types.h>
26
27#include <dns/rdataset.h>
28#include <dns/resolver.h>
29#include <dns/rpz.h>
30#include <dns/types.h>
31
32#include <ns/types.h>
33
34/*% nameserver database version structure */
35typedef struct ns_dbversion {
36	dns_db_t	*db;
37	dns_dbversion_t *version;
38	bool		 acl_checked;
39	bool		 queryok;
40	ISC_LINK(struct ns_dbversion) link;
41} ns_dbversion_t;
42
43/*%
44 * nameserver recursion parameters, to uniquely identify a recursion
45 * query; this is used to detect a recursion loop
46 */
47typedef struct ns_query_recparam {
48	dns_rdatatype_t qtype;
49	dns_name_t     *qname;
50	dns_fixedname_t fqname;
51	dns_name_t     *qdomain;
52	dns_fixedname_t fqdomain;
53} ns_query_recparam_t;
54
55/*% nameserver query structure */
56struct ns_query {
57	unsigned int	 attributes;
58	unsigned int	 restarts;
59	bool		 timerset;
60	dns_name_t	*qname;
61	dns_name_t	*origqname;
62	dns_rdatatype_t	 qtype;
63	unsigned int	 dboptions;
64	unsigned int	 fetchoptions;
65	dns_db_t	*gluedb;
66	dns_db_t	*authdb;
67	dns_zone_t	*authzone;
68	bool		 authdbset;
69	bool		 isreferral;
70	isc_mutex_t	 fetchlock;
71	dns_fetch_t	*fetch;
72	dns_fetch_t	*prefetch;
73	ns_hookasync_t	*hookactx;
74	dns_rpz_st_t	*rpz_st;
75	isc_bufferlist_t namebufs;
76	ISC_LIST(ns_dbversion_t) activeversions;
77	ISC_LIST(ns_dbversion_t) freeversions;
78	dns_rdataset_t *dns64_aaaa;
79	dns_rdataset_t *dns64_sigaaaa;
80	bool	       *dns64_aaaaok;
81	unsigned int	dns64_aaaaoklen;
82	unsigned int	dns64_options;
83	unsigned int	dns64_ttl;
84
85	struct {
86		dns_db_t       *db;
87		dns_zone_t     *zone;
88		dns_dbnode_t   *node;
89		dns_rdatatype_t qtype;
90		dns_name_t     *fname;
91		dns_fixedname_t fixed;
92		isc_result_t	result;
93		dns_rdataset_t *rdataset;
94		dns_rdataset_t *sigrdataset;
95		bool		authoritative;
96		bool		is_zone;
97	} redirect;
98
99	ns_query_recparam_t recparam;
100
101	dns_keytag_t root_key_sentinel_keyid;
102	bool	     root_key_sentinel_is_ta;
103	bool	     root_key_sentinel_not_ta;
104};
105
106#define NS_QUERYATTR_RECURSIONOK     0x000001
107#define NS_QUERYATTR_CACHEOK	     0x000002
108#define NS_QUERYATTR_PARTIALANSWER   0x000004
109#define NS_QUERYATTR_NAMEBUFUSED     0x000008
110#define NS_QUERYATTR_RECURSING	     0x000010
111#define NS_QUERYATTR_QUERYOKVALID    0x000040
112#define NS_QUERYATTR_QUERYOK	     0x000080
113#define NS_QUERYATTR_WANTRECURSION   0x000100
114#define NS_QUERYATTR_SECURE	     0x000200
115#define NS_QUERYATTR_NOAUTHORITY     0x000400
116#define NS_QUERYATTR_NOADDITIONAL    0x000800
117#define NS_QUERYATTR_CACHEACLOKVALID 0x001000
118#define NS_QUERYATTR_CACHEACLOK	     0x002000
119#define NS_QUERYATTR_DNS64	     0x004000
120#define NS_QUERYATTR_DNS64EXCLUDE    0x008000
121#define NS_QUERYATTR_RRL_CHECKED     0x010000
122#define NS_QUERYATTR_REDIRECT	     0x020000
123#define NS_QUERYATTR_ANSWERED	     0x040000
124#define NS_QUERYATTR_STALEOK	     0x080000
125#define NS_QUERYATTR_STALEPENDING    0x100000
126
127typedef struct query_ctx query_ctx_t;
128
129/* query context structure */
130struct query_ctx {
131	isc_buffer_t *dbuf;	     /* name buffer */
132	dns_name_t   *fname;	     /* found name from DB lookup */
133	dns_name_t   *tname;	     /* temporary name, used
134				      * when processing ANY
135				      * queries */
136	dns_rdataset_t *rdataset;    /* found rdataset */
137	dns_rdataset_t *sigrdataset; /* found sigrdataset */
138	dns_rdataset_t *noqname;     /* rdataset needing
139				      * NOQNAME proof */
140	dns_rdatatype_t qtype;
141	dns_rdatatype_t type;
142
143	unsigned int options; /* DB lookup options */
144
145	bool redirected; /* nxdomain redirected? */
146	bool is_zone;	 /* is DB a zone DB? */
147	bool is_staticstub_zone;
148	bool resuming; /* resumed from recursion? */
149	bool dns64, dns64_exclude, rpz;
150	bool authoritative;		    /* authoritative query? */
151	bool want_restart;		    /* CNAME chain or other
152					     * restart needed */
153	bool		refresh_rrset;	    /* stale RRset refresh needed */
154	bool		need_wildcardproof; /* wildcard proof needed */
155	bool		nxrewrite;	    /* negative answer from RPZ */
156	bool		findcoveringnsec;   /* lookup covering NSEC */
157	bool		answer_has_ns;	    /* NS is in answer */
158	dns_fixedname_t wildcardname;	    /* name needing wcard proof */
159	dns_fixedname_t dsname;		    /* name needing DS */
160
161	ns_client_t *client;	    /* client object */
162	bool	     detach_client; /* client needs detaching */
163
164	dns_fetchevent_t *event; /* recursion event */
165
166	dns_db_t	*db;	  /* zone or cache database */
167	dns_dbversion_t *version; /* DB version */
168	dns_dbnode_t	*node;	  /* DB node */
169
170	dns_db_t	*zdb;	 /* zone DB values, saved */
171	dns_dbnode_t	*znode;	 /* while searching cache */
172	dns_name_t	*zfname; /* for a better answer */
173	dns_dbversion_t *zversion;
174	dns_rdataset_t	*zrdataset;
175	dns_rdataset_t	*zsigrdataset;
176
177	dns_rpz_st_t *rpz_st; /* RPZ state */
178	dns_zone_t   *zone;   /* zone to search */
179
180	dns_view_t *view; /* client view */
181
182	isc_result_t result; /* query result */
183	int	     line;   /* line to report error */
184};
185
186typedef isc_result_t (*ns_query_starthookasync_t)(
187	query_ctx_t *qctx, isc_mem_t *mctx, void *arg, isc_task_t *task,
188	isc_taskaction_t action, void *evarg, ns_hookasync_t **ctxp);
189
190/*
191 * The following functions are expected to be used only within query.c
192 * and query modules.
193 */
194
195isc_result_t
196ns_query_done(query_ctx_t *qctx);
197/*%<
198 * Finalize this phase of the query process:
199 *
200 * - Clean up.
201 * - If we have an answer ready (positive or negative), send it.
202 * - If we need to restart for a chaining query, call ns__query_start() again.
203 * - If we've started recursion, then just clean up; things will be
204 *   restarted via fetch_callback()/query_resume().
205 */
206
207isc_result_t
208ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
209		 dns_name_t *qdomain, dns_rdataset_t *nameservers,
210		 bool resuming);
211/*%<
212 * Prepare client for recursion, then create a resolver fetch, with
213 * the event callback set to fetch_callback(). Afterward we terminate
214 * this phase of the query, and resume with a new query context when
215 * recursion completes.
216 */
217
218isc_result_t
219ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync,
220		   void *arg);
221/*%<
222 * Prepare the client for an asynchronous hook action, then call the
223 * specified 'runasync' function to start an asynchronous process running
224 * in the background.  This function works similarly to ns_query_recurse(),
225 * but is expected to be called from a query hook action to support
226 * asynchronous event handling in a hook. A typical use case would be for
227 * a plugin to initiate recursion, but it may also be used to carry out
228 * other time-consuming tasks without blocking the caller or the worker
229 * thread.
230 *
231 * The calling plugin action must pass 'qctx' as passed from the query
232 * module.
233 *
234 * Once a plugin action calls this function, the ownership of 'qctx' is
235 * essentially transferred to the query module. Regardless of the return
236 * value of this function, the hook must not use 'qctx' anymore.
237 *
238 * This function must not be called after ns_query_recurse() is called,
239 * until the fetch is completed, as it needs resources that
240 * ns_query_recurse() would also use.
241 *
242 * See hooks.h for details about how 'runasync' is supposed to work, and
243 * other aspects of hook-triggered asynchronous event handling.
244 */
245
246isc_result_t
247ns_query_init(ns_client_t *client);
248
249void
250ns_query_free(ns_client_t *client);
251
252void
253ns_query_start(ns_client_t *client, isc_nmhandle_t *handle);
254
255void
256ns_query_cancel(ns_client_t *client);
257
258/*
259 * The following functions are expected to be used only within query.c
260 * and query modules.
261 */
262
263isc_result_t
264ns__query_sfcache(query_ctx_t *qctx);
265/*%<
266 * (Must not be used outside this module and its associated unit tests.)
267 */
268
269isc_result_t
270ns__query_start(query_ctx_t *qctx);
271/*%<
272 * (Must not be used outside this module and its associated unit tests.)
273 */
274