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