Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: dispatch.h,v 1.9 2026/05/20 16:53: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 #include <isc/netmgr.h>
     19 
     20 /*****
     21 ***** Module Info
     22 *****/
     23 
     24 /*! \file dns/dispatch.h
     25  * \brief
     26  * DNS Dispatch Management
     27  *	Shared UDP and single-use TCP dispatches for queries and responses.
     28  *
     29  * MP:
     30  *
     31  *\li	All locking is performed internally to each dispatch.
     32  *	Restrictions apply to dns_dispatch_done().
     33  *
     34  * Reliability:
     35  *
     36  * Resources:
     37  *
     38  * Security:
     39  *
     40  *\li	Depends on dns_message_t for prevention of buffer overruns.
     41  *
     42  * Standards:
     43  *
     44  *\li	None.
     45  */
     46 
     47 /***
     48  *** Imports
     49  ***/
     50 
     51 #include <inttypes.h>
     52 #include <stdbool.h>
     53 
     54 #include <isc/buffer.h>
     55 #include <isc/lang.h>
     56 #include <isc/mutex.h>
     57 #include <isc/netmgr.h>
     58 #include <isc/refcount.h>
     59 #include <isc/types.h>
     60 
     61 #include <dns/types.h>
     62 
     63 /* Add -DDNS_DISPATCH_TRACE=1 to CFLAGS for detailed reference tracing */
     64 
     65 ISC_LANG_BEGINDECLS
     66 
     67 /*%
     68  * This is a set of one or more dispatches which can be retrieved
     69  * round-robin fashion.
     70  */
     71 struct dns_dispatchset {
     72 	isc_mem_t	*mctx;
     73 	dns_dispatch_t **dispatches;
     74 	uint32_t	 ndisp;
     75 };
     76 
     77 typedef enum dns_dispatchopt {
     78 	DNS_DISPATCHOPT_FIXEDID = 1 << 0,
     79 } dns_dispatchopt_t;
     80 
     81 typedef enum dns_dispatchtype {
     82 	DNS_DISPATCHTYPE_RESOLVER,
     83 	DNS_DISPATCHTYPE_REQUEST,
     84 	DNS_DISPATCHTYPE_XFRIN,
     85 } dns_dispatchtype_t;
     86 
     87 isc_result_t
     88 dns_dispatchmgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, isc_nm_t *nm,
     89 		       dns_dispatchmgr_t **mgrp);
     90 /*%<
     91  * Creates a new dispatchmgr object, and sets the available ports
     92  * to the default range (1024-65535).
     93  *
     94  * Requires:
     95  *\li	'mctx' be a valid memory context.
     96  *
     97  *\li	'nm' is a valid network manager.
     98 
     99  *\li	mgrp != NULL && *mgrp == NULL
    100  *
    101  * Returns:
    102  *\li	ISC_R_SUCCESS	-- all ok
    103  *
    104  *\li	anything else	-- failure
    105  */
    106 
    107 #if DNS_DISPATCH_TRACE
    108 #define dns_dispatchmgr_ref(ptr) \
    109 	dns_dispatchmgr__ref(ptr, __func__, __FILE__, __LINE__)
    110 #define dns_dispatchmgr_unref(ptr) \
    111 	dns_dispatchmgr__unref(ptr, __func__, __FILE__, __LINE__)
    112 #define dns_dispatchmgr_attach(ptr, ptrp) \
    113 	dns_dispatchmgr__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
    114 #define dns_dispatchmgr_detach(ptrp) \
    115 	dns_dispatchmgr__detach(ptrp, __func__, __FILE__, __LINE__)
    116 ISC_REFCOUNT_TRACE_DECL(dns_dispatchmgr);
    117 #else
    118 ISC_REFCOUNT_DECL(dns_dispatchmgr);
    119 #endif
    120 
    121 /*%<
    122  * Attach/Detach to a dispatch manager.
    123  */
    124 
    125 void
    126 dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole);
    127 /*%<
    128  * Sets the dispatcher's "blackhole list," a list of addresses that will
    129  * be ignored by all dispatchers created by the dispatchmgr.
    130  *
    131  * Requires:
    132  * \li	mgrp is a valid dispatchmgr
    133  * \li	blackhole is a valid acl
    134  */
    135 
    136 dns_acl_t *
    137 dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr);
    138 /*%<
    139  * Gets a pointer to the dispatcher's current blackhole list,
    140  * without incrementing its reference count.
    141  *
    142  * Requires:
    143  *\li	mgr is a valid dispatchmgr
    144  * Returns:
    145  *\li	A pointer to the current blackhole list, or NULL.
    146  */
    147 
    148 isc_result_t
    149 dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
    150 			      isc_portset_t *v6portset);
    151 /*%<
    152  * Sets a list of UDP ports that can be used for outgoing UDP messages.
    153  *
    154  * Requires:
    155  *\li	mgr is a valid dispatchmgr
    156  *\li	v4portset is NULL or a valid port set
    157  *\li	v6portset is NULL or a valid port set
    158  */
    159 
    160 void
    161 dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats);
    162 /*%<
    163  * Sets statistics counter for the dispatchmgr.  This function is expected to
    164  * be called only on zone creation (when necessary).
    165  * Once installed, it cannot be removed or replaced.  Also, there is no
    166  * interface to get the installed stats from the zone; the caller must keep the
    167  * stats to reference (e.g. dump) it later.
    168  *
    169  * Requires:
    170  *\li	mgr is a valid dispatchmgr with no managed dispatch.
    171  *\li	stats is a valid statistics supporting resolver statistics counters
    172  *	(see dns/stats.h).
    173  */
    174 
    175 isc_result_t
    176 dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
    177 		       dns_dispatch_t **dispp);
    178 /*%<
    179  * Create a new UDP dispatch.
    180  *
    181  * Requires:
    182  *\li	All pointer parameters be valid for their respective types.
    183  *
    184  *\li	dispp != NULL && *disp == NULL
    185  *
    186  * Returns:
    187  *\li	ISC_R_SUCCESS	-- success.
    188  *
    189  *\li	Anything else	-- failure.
    190  */
    191 
    192 isc_result_t
    193 dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
    194 		       const isc_sockaddr_t *destaddr,
    195 		       dns_transport_t *transport, dns_dispatchtype_t disptype,
    196 		       dns_dispatchopt_t options, dns_dispatch_t **dispp);
    197 /*%<
    198  * Create a new TCP dns_dispatch.
    199  *
    200  * Note: a NULL transport is different from a non-NULL transport of type
    201  *	 DNS_TRANSPORT_TCP, though currently their behavior is the same.
    202  *	 This allows for different types of transactions to be seperated
    203  *	 in the future if needed.
    204  *
    205  * Requires:
    206  *
    207  *\li	mgr is a valid dispatch manager.
    208  *
    209  *\li	dstaddr to be a valid sockaddr.
    210  *
    211  *\li	localaddr to be a valid sockaddr.
    212  *
    213  *\li	transport is NULL or a valid transport.
    214  *
    215  *\li	dispp to be non NULL and *dispp to be NULL
    216  *
    217  * Returns:
    218  *\li	ISC_R_SUCCESS	-- success.
    219  *
    220  *\li	Anything else	-- failure.
    221  */
    222 
    223 #if DNS_DISPATCH_TRACE
    224 #define dns_dispatch_ref(ptr) \
    225 	dns_dispatch__ref(ptr, __func__, __FILE__, __LINE__)
    226 #define dns_dispatch_unref(ptr) \
    227 	dns_dispatch__unref(ptr, __func__, __FILE__, __LINE__)
    228 #define dns_dispatch_attach(ptr, ptrp) \
    229 	dns_dispatch__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
    230 #define dns_dispatch_detach(ptrp) \
    231 	dns_dispatch__detach(ptrp, __func__, __FILE__, __LINE__)
    232 ISC_REFCOUNT_TRACE_DECL(dns_dispatch);
    233 #else
    234 ISC_REFCOUNT_DECL(dns_dispatch);
    235 #endif
    236 /*%<
    237  * Attach/Detach to a dispatch handle.
    238  *
    239  * Requires:
    240  *\li	disp is valid.
    241  *
    242  *\li	dispp != NULL && *dispp == NULL
    243  */
    244 
    245 isc_result_t
    246 dns_dispatch_connect(dns_dispentry_t *resp);
    247 /*%<
    248  * Connect to the remote server configured in 'resp' and run the
    249  * connect callback that was set up via dns_dispatch_add().
    250  *
    251  * Requires:
    252  *\li	'resp' is valid.
    253  */
    254 
    255 void
    256 dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r);
    257 /*%<
    258  * Send region 'r' using the socket in 'resp', then run the specified
    259  * callback.
    260  *
    261  * Requires:
    262  *\li	'resp' is valid.
    263  */
    264 
    265 void
    266 dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout);
    267 /*%<
    268  * Reset the read timeout in the socket associated with 'resp' and
    269  * continue reading.
    270  *
    271  * Requires:
    272  *\li	'resp' is valid.
    273  */
    274 
    275 typedef void (*dispatch_cb_t)(isc_result_t eresult, isc_region_t *region,
    276 			      void *cbarg);
    277 
    278 isc_result_t
    279 dns_dispatch_add(dns_dispatch_t *disp, isc_loop_t *loop,
    280 		 dns_dispatchopt_t options, unsigned int timeout,
    281 		 const isc_sockaddr_t *dest, dns_transport_t *transport,
    282 		 isc_tlsctx_cache_t *tlsctx_cache, dispatch_cb_t connected,
    283 		 dispatch_cb_t sent, dispatch_cb_t response, void *arg,
    284 		 dns_messageid_t *idp, dns_dispentry_t **resp);
    285 /*%<
    286  * Add a response entry for this dispatch.
    287  *
    288  * "*idp" is filled in with the assigned message ID, and *resp is filled in
    289  * with the dispatch entry object.
    290  *
    291  * The 'connected' and 'sent' callbacks are run to inform the caller when
    292  * the connect and send functions are complete. The 'timedout' callback
    293  * is run to inform the caller that a read has timed out; it may optionally
    294  * reset the read timer. The 'response' callback is run for recv results
    295  * (response packets, timeouts, or cancellations).
    296  *
    297  * All the callback functions are sent 'arg' as a parameter.
    298  *
    299  * Requires:
    300  *\li	"idp" be non-NULL.
    301  *
    302  *\li	"response" and "arg" be set as appropriate.
    303  *
    304  *\li	"dest" be non-NULL and valid.
    305  *
    306  *\li	"resp" be non-NULL and *resp be NULL
    307  *
    308  *\li	"transport" to be the same one used with dns_dispatch_createtcp or
    309  *	dns_dispatch_gettcp.
    310  *
    311  * Ensures:
    312  *
    313  *\li	&lt;id, dest> is a unique tuple.  That means incoming messages
    314  *	are identifiable.
    315  *
    316  * Returns:
    317  *
    318  *\li	ISC_R_SUCCESS		-- all is well.
    319  *\li	ISC_R_NOMEMORY		-- memory could not be allocated.
    320  *\li	ISC_R_NOMORE		-- no more message ids can be allocated
    321  *				   for this destination.
    322  */
    323 
    324 void
    325 dns_dispatch_done(dns_dispentry_t **respp);
    326 /*<
    327  * Disconnect a dispatch response entry from its dispatch, cancel all
    328  * pending connects and reads in a dispatch entry and shut it down.
    329 
    330  *
    331  * Requires:
    332  *\li	"resp" != NULL and "*resp" contain a value previously allocated
    333  *	by dns_dispatch_add();
    334  */
    335 
    336 isc_result_t
    337 dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp);
    338 /*%<
    339  * Return the local address for this dispatch.
    340  * This currently only works for dispatches using UDP sockets.
    341  *
    342  * Requires:
    343  *\li	disp is valid.
    344  *\li	addrp to be non NULL.
    345  *
    346  * Returns:
    347  *\li	ISC_R_SUCCESS
    348  *\li	ISC_R_NOTIMPLEMENTED
    349  */
    350 
    351 isc_result_t
    352 dns_dispentry_getlocaladdress(dns_dispentry_t *resp, isc_sockaddr_t *addrp);
    353 /*%<
    354  * Return the local address for this dispatch entry.
    355  *
    356  * Requires:
    357  *\li	resp is valid.
    358  *\li	addrp to be non NULL.
    359  *
    360  * Returns:
    361  *\li	ISC_R_SUCCESS
    362  *\li	ISC_R_NOTIMPLEMENTED
    363  */
    364 
    365 dns_dispatch_t *
    366 dns_dispatchset_get(dns_dispatchset_t *dset);
    367 /*%<
    368  * Retrieve the next dispatch from dispatch set 'dset', and increment
    369  * the round-robin counter.
    370  *
    371  * Requires:
    372  *\li	dset != NULL
    373  */
    374 
    375 isc_result_t
    376 dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source,
    377 		       dns_dispatchset_t **dsetp, uint32_t n);
    378 /*%<
    379  * Given a valid dispatch 'source', create a dispatch set containing
    380  * 'n' UDP dispatches, with the remainder filled out by clones of the
    381  * source.
    382  *
    383  * Requires:
    384  *\li	source is a valid UDP dispatcher
    385  *\li	dsetp != NULL, *dsetp == NULL
    386  */
    387 
    388 void
    389 dns_dispatchset_destroy(dns_dispatchset_t **dsetp);
    390 /*%<
    391  * Dereference all the dispatches in '*dsetp', free the dispatchset
    392  * memory, and set *dsetp to NULL.
    393  *
    394  * Requires:
    395  *\li	dset is valid
    396  */
    397 
    398 isc_result_t
    399 dns_dispatch_getnext(dns_dispentry_t *resp);
    400 /*%<
    401  * Trigger the sending of the next item off the dispatch queue if present.
    402  *
    403  * Requires:
    404  *\li	resp is valid
    405  */
    406 
    407 isc_result_t
    408 dns_dispatch_checkperm(dns_dispatch_t *disp);
    409 /*%<
    410  * Check whether it is permitted to do a zone transfer over a dispatch.
    411  * See isc_nm_xfr_checkperm().
    412  *
    413  * Requires:
    414  *\li	disp is valid
    415  */
    416 
    417 ISC_LANG_ENDDECLS
    418