xref: /netbsd-src/external/mpl/bind/dist/lib/ns/include/ns/query.h (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: query.h,v 1.9 2025/01/26 16:25: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/types.h>
25 
26 #include <dns/rdataset.h>
27 #include <dns/resolver.h>
28 #include <dns/rpz.h>
29 #include <dns/types.h>
30 
31 #include <ns/types.h>
32 
33 /*% nameserver database version structure */
34 typedef struct ns_dbversion {
35 	dns_db_t	*db;
36 	dns_dbversion_t *version;
37 	bool		 acl_checked;
38 	bool		 queryok;
39 	ISC_LINK(struct ns_dbversion) link;
40 } ns_dbversion_t;
41 
42 /* DB lookup options */
43 typedef struct dns_getdb_options {
44 	bool noexact	: 1;
45 	bool nolog	: 1;
46 	bool partial	: 1;
47 	bool ignoreacl	: 1;
48 	bool stalefirst : 1;
49 } dns_getdb_options_t;
50 
51 /*%
52  * recursion type; various features can initiate recursion and this enum value
53  * allows common code paths to differentiate between them
54  */
55 typedef enum {
56 	RECTYPE_NORMAL,
57 	RECTYPE_PREFETCH,
58 	RECTYPE_RPZ,
59 	RECTYPE_STALE_REFRESH,
60 	RECTYPE_HOOK,
61 	RECTYPE_COUNT,
62 } ns_query_rectype_t;
63 
64 /*%
65  * Helper macros for accessing isc_nmhandle_t pointers for a specific recursion
66  * a given client is associated with.
67  */
68 #define HANDLE_RECTYPE_NORMAL(client) \
69 	((client)->query.recursions[RECTYPE_NORMAL].handle)
70 #define HANDLE_RECTYPE_PREFETCH(client) \
71 	((client)->query.recursions[RECTYPE_PREFETCH].handle)
72 #define HANDLE_RECTYPE_RPZ(client) \
73 	((client)->query.recursions[RECTYPE_RPZ].handle)
74 #define HANDLE_RECTYPE_STALE_REFRESH(client) \
75 	((client)->query.recursions[RECTYPE_STALE_REFRESH].handle)
76 #define HANDLE_RECTYPE_HOOK(client) \
77 	((client)->query.recursions[RECTYPE_HOOK].handle)
78 
79 /*%
80  * Helper macros for accessing dns_fetch_t pointers for a specific recursion a
81  * given client is associated with.
82  */
83 #define FETCH_RECTYPE_NORMAL(client) \
84 	((client)->query.recursions[RECTYPE_NORMAL].fetch)
85 #define FETCH_RECTYPE_PREFETCH(client) \
86 	((client)->query.recursions[RECTYPE_PREFETCH].fetch)
87 #define FETCH_RECTYPE_RPZ(client) \
88 	((client)->query.recursions[RECTYPE_RPZ].fetch)
89 #define FETCH_RECTYPE_STALE_REFRESH(client) \
90 	((client)->query.recursions[RECTYPE_STALE_REFRESH].fetch)
91 #define FETCH_RECTYPE_HOOK(client) \
92 	((client)->query.recursions[RECTYPE_HOOK].fetch)
93 
94 /*%
95  * nameserver recursion parameters, to uniquely identify a recursion
96  * query; this is used to detect a recursion loop
97  */
98 typedef struct ns_query_recparam {
99 	dns_rdatatype_t qtype;
100 	dns_name_t     *qname;
101 	dns_fixedname_t fqname;
102 	dns_name_t     *qdomain;
103 	dns_fixedname_t fqdomain;
104 } ns_query_recparam_t;
105 
106 /*% nameserver query structure */
107 struct ns_query {
108 	unsigned int	 attributes;
109 	unsigned int	 restarts;
110 	bool		 timerset;
111 	dns_name_t	*qname;
112 	dns_name_t	*origqname;
113 	dns_rdatatype_t	 qtype;
114 	unsigned int	 dboptions;
115 	unsigned int	 fetchoptions;
116 	dns_db_t	*gluedb;
117 	dns_db_t	*authdb;
118 	dns_zone_t	*authzone;
119 	bool		 authdbset;
120 	bool		 isreferral;
121 	isc_mutex_t	 fetchlock;
122 	ns_hookasync_t	*hookactx;
123 	dns_rpz_st_t	*rpz_st;
124 	isc_bufferlist_t namebufs;
125 	ISC_LIST(ns_dbversion_t) activeversions;
126 	ISC_LIST(ns_dbversion_t) freeversions;
127 	dns_rdataset_t *dns64_aaaa;
128 	dns_rdataset_t *dns64_sigaaaa;
129 	bool	       *dns64_aaaaok;
130 	unsigned int	dns64_aaaaoklen;
131 	unsigned int	dns64_options;
132 	unsigned int	dns64_ttl;
133 
134 	struct {
135 		dns_db_t       *db;
136 		dns_zone_t     *zone;
137 		dns_dbnode_t   *node;
138 		dns_rdatatype_t qtype;
139 		dns_name_t     *fname;
140 		dns_fixedname_t fixed;
141 		isc_result_t	result;
142 		dns_rdataset_t *rdataset;
143 		dns_rdataset_t *sigrdataset;
144 		bool		authoritative;
145 		bool		is_zone;
146 	} redirect;
147 
148 	struct {
149 		isc_nmhandle_t *handle;
150 		dns_fetch_t    *fetch;
151 	} recursions[RECTYPE_COUNT];
152 
153 	ns_query_recparam_t recparam;
154 
155 	dns_keytag_t root_key_sentinel_keyid;
156 	bool	     root_key_sentinel_is_ta;
157 	bool	     root_key_sentinel_not_ta;
158 };
159 
160 #define NS_QUERYATTR_RECURSIONOK     0x000001
161 #define NS_QUERYATTR_CACHEOK	     0x000002
162 #define NS_QUERYATTR_PARTIALANSWER   0x000004
163 #define NS_QUERYATTR_NAMEBUFUSED     0x000008
164 #define NS_QUERYATTR_RECURSING	     0x000010
165 #define NS_QUERYATTR_QUERYOKVALID    0x000040
166 #define NS_QUERYATTR_QUERYOK	     0x000080
167 #define NS_QUERYATTR_WANTRECURSION   0x000100
168 #define NS_QUERYATTR_SECURE	     0x000200
169 #define NS_QUERYATTR_NOAUTHORITY     0x000400
170 #define NS_QUERYATTR_NOADDITIONAL    0x000800
171 #define NS_QUERYATTR_CACHEACLOKVALID 0x001000
172 #define NS_QUERYATTR_CACHEACLOK	     0x002000
173 #define NS_QUERYATTR_DNS64	     0x004000
174 #define NS_QUERYATTR_DNS64EXCLUDE    0x008000
175 #define NS_QUERYATTR_RRL_CHECKED     0x010000
176 #define NS_QUERYATTR_REDIRECT	     0x020000
177 #define NS_QUERYATTR_ANSWERED	     0x040000
178 #define NS_QUERYATTR_STALEOK	     0x080000
179 
180 typedef struct query_ctx query_ctx_t;
181 
182 /* query context structure */
183 struct query_ctx {
184 	isc_buffer_t *dbuf;	     /* name buffer */
185 	dns_name_t   *fname;	     /* found name from DB lookup */
186 	dns_name_t   *tname;	     /* temporary name, used
187 				      * when processing ANY
188 				      * queries */
189 	dns_rdataset_t *rdataset;    /* found rdataset */
190 	dns_rdataset_t *sigrdataset; /* found sigrdataset */
191 	dns_rdataset_t *noqname;     /* rdataset needing
192 				      * NOQNAME proof */
193 	dns_rdatatype_t qtype;
194 	dns_rdatatype_t type;
195 
196 	dns_getdb_options_t options; /* DB lookup options */
197 
198 	bool redirected; /* nxdomain redirected? */
199 	bool is_zone;	 /* is DB a zone DB? */
200 	bool is_staticstub_zone;
201 	bool resuming; /* resumed from recursion? */
202 	bool dns64, dns64_exclude, rpz;
203 	bool authoritative;		    /* authoritative query? */
204 	bool want_restart;		    /* CNAME chain or other
205 					     * restart needed */
206 	bool		refresh_rrset;	    /* stale RRset refresh needed */
207 	bool		need_wildcardproof; /* wildcard proof needed */
208 	bool		nxrewrite;	    /* negative answer from RPZ */
209 	bool		findcoveringnsec;   /* lookup covering NSEC */
210 	bool		answer_has_ns;	    /* NS is in answer */
211 	dns_fixedname_t wildcardname;	    /* name needing wcard proof */
212 	dns_fixedname_t dsname;		    /* name needing DS */
213 
214 	ns_client_t *client;	    /* client object */
215 	bool	     detach_client; /* client needs detaching */
216 
217 	dns_fetchresponse_t *fresp; /* recursion response */
218 
219 	dns_db_t	*db;	  /* zone or cache database */
220 	dns_dbversion_t *version; /* DB version */
221 	dns_dbnode_t	*node;	  /* DB node */
222 
223 	dns_db_t	*zdb;	 /* zone DB values, saved */
224 	dns_dbnode_t	*znode;	 /* while searching cache */
225 	dns_name_t	*zfname; /* for a better answer */
226 	dns_dbversion_t *zversion;
227 	dns_rdataset_t	*zrdataset;
228 	dns_rdataset_t	*zsigrdataset;
229 
230 	dns_rpz_st_t *rpz_st; /* RPZ state */
231 	dns_zone_t   *zone;   /* zone to search */
232 
233 	dns_view_t *view; /* client view */
234 
235 	isc_result_t result; /* query result */
236 	int	     line;   /* line to report error */
237 };
238 
239 typedef isc_result_t (*ns_query_starthookasync_t)(query_ctx_t *qctx,
240 						  isc_mem_t *mctx, void *arg,
241 						  isc_loop_t *loop,
242 						  isc_job_cb cb, void *evarg,
243 						  ns_hookasync_t **ctxp);
244 
245 /*
246  * The following functions are expected to be used only within query.c
247  * and query modules.
248  */
249 
250 isc_result_t
251 ns_query_done(query_ctx_t *qctx);
252 /*%<
253  * Finalize this phase of the query process:
254  *
255  * - Clean up.
256  * - If we have an answer ready (positive or negative), send it.
257  * - If we need to restart for a chaining query, call ns__query_start() again.
258  * - If we've started recursion, then just clean up; things will be
259  *   restarted via fetch_callback()/query_resume().
260  */
261 
262 isc_result_t
263 ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
264 		 dns_name_t *qdomain, dns_rdataset_t *nameservers,
265 		 bool resuming);
266 /*%<
267  * Prepare client for recursion, then create a resolver fetch, with
268  * the event callback set to fetch_callback(). Afterward we terminate
269  * this phase of the query, and resume with a new query context when
270  * recursion completes.
271  */
272 
273 isc_result_t
274 ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync,
275 		   void *arg);
276 /*%<
277  * Prepare the client for an asynchronous hook action, then call the
278  * specified 'runasync' function to start an asynchronous process running
279  * in the background.  This function works similarly to ns_query_recurse(),
280  * but is expected to be called from a query hook action to support
281  * asynchronous event handling in a hook. A typical use case would be for
282  * a plugin to initiate recursion, but it may also be used to carry out
283  * other time-consuming tasks without blocking the caller or the worker
284  * thread.
285  *
286  * The calling plugin action must pass 'qctx' as passed from the query
287  * module.
288  *
289  * Once a plugin action calls this function, the ownership of 'qctx' is
290  * essentially transferred to the query module. Regardless of the return
291  * value of this function, the hook must not use 'qctx' anymore.
292  *
293  * This function must not be called after ns_query_recurse() is called,
294  * until the fetch is completed, as it needs resources that
295  * ns_query_recurse() would also use.
296  *
297  * See hooks.h for details about how 'runasync' is supposed to work, and
298  * other aspects of hook-triggered asynchronous event handling.
299  */
300 
301 void
302 ns_query_init(ns_client_t *client);
303 
304 void
305 ns_query_free(ns_client_t *client);
306 
307 void
308 ns_query_start(ns_client_t *client, isc_nmhandle_t *handle);
309 
310 void
311 ns_query_cancel(ns_client_t *client);
312 
313 /*
314  * The following functions are expected to be used only within query.c
315  * and query modules.
316  */
317 
318 isc_result_t
319 ns__query_sfcache(query_ctx_t *qctx);
320 /*%<
321  * (Must not be used outside this module and its associated unit tests.)
322  */
323 
324 isc_result_t
325 ns__query_start(query_ctx_t *qctx);
326 /*%<
327  * (Must not be used outside this module and its associated unit tests.)
328  */
329