Home | History | Annotate | Line # | Download | only in ns
      1 /*	$NetBSD: query.h,v 1.11 2026/01/29 18:37:56 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 	isc_counter_t	*qc;
    111 	bool		 timerset;
    112 	dns_name_t	*qname;
    113 	dns_name_t	*origqname;
    114 	dns_rdatatype_t	 qtype;
    115 	unsigned int	 dboptions;
    116 	unsigned int	 fetchoptions;
    117 	dns_db_t	*gluedb;
    118 	dns_db_t	*authdb;
    119 	dns_zone_t	*authzone;
    120 	bool		 authdbset;
    121 	bool		 isreferral;
    122 	isc_mutex_t	 fetchlock;
    123 	ns_hookasync_t	*hookactx;
    124 	dns_rpz_st_t	*rpz_st;
    125 	isc_bufferlist_t namebufs;
    126 	ISC_LIST(ns_dbversion_t) activeversions;
    127 	ISC_LIST(ns_dbversion_t) freeversions;
    128 	dns_rdataset_t *dns64_aaaa;
    129 	dns_rdataset_t *dns64_sigaaaa;
    130 	bool	       *dns64_aaaaok;
    131 	unsigned int	dns64_aaaaoklen;
    132 	unsigned int	dns64_options;
    133 	unsigned int	dns64_ttl;
    134 
    135 	struct {
    136 		dns_db_t       *db;
    137 		dns_zone_t     *zone;
    138 		dns_dbnode_t   *node;
    139 		dns_rdatatype_t qtype;
    140 		dns_name_t     *fname;
    141 		dns_fixedname_t fixed;
    142 		isc_result_t	result;
    143 		dns_rdataset_t *rdataset;
    144 		dns_rdataset_t *sigrdataset;
    145 		bool		authoritative;
    146 		bool		is_zone;
    147 	} redirect;
    148 
    149 	struct {
    150 		isc_nmhandle_t *handle;
    151 		dns_fetch_t    *fetch;
    152 	} recursions[RECTYPE_COUNT];
    153 
    154 	ns_query_recparam_t recparam;
    155 
    156 	dns_keytag_t root_key_sentinel_keyid;
    157 	bool	     root_key_sentinel_is_ta;
    158 	bool	     root_key_sentinel_not_ta;
    159 };
    160 
    161 #define NS_QUERYATTR_RECURSIONOK     0x000001
    162 #define NS_QUERYATTR_CACHEOK	     0x000002
    163 #define NS_QUERYATTR_PARTIALANSWER   0x000004
    164 #define NS_QUERYATTR_NAMEBUFUSED     0x000008
    165 #define NS_QUERYATTR_RECURSING	     0x000010
    166 #define NS_QUERYATTR_QUERYOKVALID    0x000040
    167 #define NS_QUERYATTR_QUERYOK	     0x000080
    168 #define NS_QUERYATTR_WANTRECURSION   0x000100
    169 #define NS_QUERYATTR_SECURE	     0x000200
    170 #define NS_QUERYATTR_NOAUTHORITY     0x000400
    171 #define NS_QUERYATTR_NOADDITIONAL    0x000800
    172 #define NS_QUERYATTR_CACHEACLOKVALID 0x001000
    173 #define NS_QUERYATTR_CACHEACLOK	     0x002000
    174 #define NS_QUERYATTR_DNS64	     0x004000
    175 #define NS_QUERYATTR_DNS64EXCLUDE    0x008000
    176 #define NS_QUERYATTR_RRL_CHECKED     0x010000
    177 #define NS_QUERYATTR_REDIRECT	     0x020000
    178 #define NS_QUERYATTR_ANSWERED	     0x040000
    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		need_wildcardproof; /* wildcard proof needed */
    207 	bool		nxrewrite;	    /* negative answer from RPZ */
    208 	bool		findcoveringnsec;   /* lookup covering NSEC */
    209 	bool		answer_has_ns;	    /* NS is in answer */
    210 	dns_fixedname_t wildcardname;	    /* name needing wcard proof */
    211 	dns_fixedname_t dsname;		    /* name needing DS */
    212 
    213 	ns_client_t *client;	    /* client object */
    214 	bool	     detach_client; /* client needs detaching */
    215 	bool	     async;	    /* asynchronous hook running */
    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