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