Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: request.h,v 1.8 2025/01/26 16:25:28 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 /*****
     19 ***** Module Info
     20 *****/
     21 
     22 /*! \file dns/request.h
     23  *
     24  * \brief
     25  * The request module provides simple request/response services useful for
     26  * sending SOA queries, DNS Notify messages, and dynamic update requests.
     27  *
     28  * MP:
     29  *\li	The module ensures appropriate synchronization of data structures it
     30  *	creates and manipulates.
     31  *
     32  * Resources:
     33  *\li	TBS
     34  *
     35  * Security:
     36  *\li	No anticipated impact.
     37  */
     38 
     39 #include <stdbool.h>
     40 
     41 #include <isc/job.h>
     42 #include <isc/lang.h>
     43 #include <isc/tls.h>
     44 
     45 #include <dns/types.h>
     46 
     47 /* Add -DDNS_REQUEST_TRACE=1 to CFLAGS for detailed reference tracing */
     48 
     49 #define DNS_REQUESTOPT_TCP     0x00000001U
     50 #define DNS_REQUESTOPT_CASE    0x00000002U
     51 #define DNS_REQUESTOPT_FIXEDID 0x00000004U
     52 #define DNS_REQUESTOPT_LARGE   0x00000008U
     53 
     54 ISC_LANG_BEGINDECLS
     55 
     56 isc_result_t
     57 dns_requestmgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
     58 		      dns_dispatchmgr_t *dispatchmgr,
     59 		      dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
     60 		      dns_requestmgr_t **requestmgrp);
     61 /*%<
     62  * Create a request manager.
     63  *
     64  * Requires:
     65  *
     66  *\li	'mctx' is a valid memory context.
     67  *
     68  *\li	'dispatchv4' is a valid dispatcher with an IPv4 UDP socket, or is NULL.
     69  *
     70  *\li	'dispatchv6' is a valid dispatcher with an IPv6 UDP socket, or is NULL.
     71  *
     72  *\li	requestmgrp != NULL && *requestmgrp == NULL
     73  *
     74  * Ensures:
     75  *
     76  *\li	On success, *requestmgrp is a valid request manager.
     77  *
     78  * Returns:
     79  *
     80  *\li	ISC_R_SUCCESS
     81  *
     82  *\li	Any other result indicates failure.
     83  */
     84 
     85 void
     86 dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr);
     87 /*%<
     88  * Start the shutdown process for 'requestmgr'.
     89  *
     90  * Notes:
     91  *
     92  *\li	This call has no effect if the request manager is already shutting
     93  *	down.
     94  *
     95  * Requires:
     96  *
     97  *\li	'requestmgr' is a valid requestmgr.
     98  */
     99 
    100 #if DNS_REQUEST_TRACE
    101 #define dns_requestmgr_ref(ptr) \
    102 	dns_requestmgr__ref(ptr, __func__, __FILE__, __LINE__)
    103 #define dns_requestmgr_unref(ptr) \
    104 	dns_requestmgr__unref(ptr, __func__, __FILE__, __LINE__)
    105 #define dns_requestmgr_attach(ptr, ptrp) \
    106 	dns_requestmgr__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
    107 #define dns_requestmgr_detach(ptrp) \
    108 	dns_requestmgr__detach(ptrp, __func__, __FILE__, __LINE__)
    109 ISC_REFCOUNT_TRACE_DECL(dns_requestmgr);
    110 #else
    111 ISC_REFCOUNT_DECL(dns_requestmgr);
    112 #endif
    113 
    114 isc_result_t
    115 dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
    116 		   const isc_sockaddr_t *srcaddr,
    117 		   const isc_sockaddr_t *destaddr, dns_transport_t *transport,
    118 		   isc_tlsctx_cache_t *tlsctx_cache, unsigned int options,
    119 		   dns_tsigkey_t *key, unsigned int timeout,
    120 		   unsigned int udptimeout, unsigned int udpretries,
    121 		   isc_loop_t *loop, isc_job_cb cb, void *arg,
    122 		   dns_request_t **requestp);
    123 /*%<
    124  * Create and send a request.
    125  *
    126  * Notes:
    127  *
    128  *\li	'message' will be rendered and sent to 'address'.  If the
    129  *	#DNS_REQUESTOPT_TCP option is set, TCP will be used,
    130  *	#DNS_REQUESTOPT_SHARE option is set too, connecting TCP
    131  *	(vs. connected) will be shared too.  The request
    132  *	will timeout after 'timeout' seconds.  UDP requests will be resent
    133  *	at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero.
    134  *
    135  *\li	If the #DNS_REQUESTOPT_CASE option is set, use case sensitive
    136  *	compression.
    137  *
    138  *\li	If the #DNS_REQUESTOPT_LARGE option is set, use a large
    139  *	compression context to accommodate more names.
    140  *
    141  *\li	When the request completes, successfully, due to a timeout, or
    142  *	because it was canceled, a completion callback will run on 'loop'.
    143  *
    144  * Requires:
    145  *
    146  *\li	'message' is a valid DNS message.
    147  *
    148  *\li	'dstaddr' is a valid sockaddr.
    149  *
    150  *\li	'srcaddr' is a valid sockaddr or NULL.
    151  *
    152  *\li	'srcaddr' and 'dstaddr' are the same protocol family.
    153  *
    154  *\li	'timeout' > 0
    155  *
    156  *\li	'loop' is a valid loop.
    157  *
    158  *\li	requestp != NULL && *requestp == NULL
    159  */
    160 
    161 isc_result_t
    162 dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
    163 		      const isc_sockaddr_t *srcaddr,
    164 		      const isc_sockaddr_t *destaddr,
    165 		      dns_transport_t	   *transport,
    166 		      isc_tlsctx_cache_t *tlsctx_cache, unsigned int options,
    167 		      unsigned int timeout, unsigned int udptimeout,
    168 		      unsigned int udpretries, isc_loop_t *loop, isc_job_cb cb,
    169 		      void *arg, dns_request_t **requestp);
    170 /*!<
    171  * \brief Create and send a request.
    172  *
    173  * Notes:
    174  *
    175  *\li	'msgbuf' will be sent to 'destaddr' after setting the id.  If the
    176  *	#DNS_REQUESTOPT_TCP option is set, TCP will be used,
    177  *	#DNS_REQUESTOPT_SHARE option is set too, connecting TCP
    178  *	(vs. connected) will be shared too.  The request
    179  *	will timeout after 'timeout' seconds.   UDP requests will be resent
    180  *	at 'udptimeout' intervals if non-zero or if 'udpretries' is not zero.
    181  *
    182  *\li	When the request completes, successfully, due to a timeout, or
    183  *	because it was canceled, a completion callback will run in 'loop'.
    184  *
    185  * Requires:
    186  *
    187  *\li	'msgbuf' is a valid DNS message in compressed wire format.
    188  *
    189  *\li	'destaddr' is a valid sockaddr.
    190  *
    191  *\li	'srcaddr' is a valid sockaddr or NULL.
    192  *
    193  *\li	'srcaddr' and 'dstaddr' are the same protocol family.
    194  *
    195  *\li	'timeout' > 0
    196  *
    197  *\li	'loop' is a valid loop.
    198  *
    199  *\li	requestp != NULL && *requestp == NULL
    200  */
    201 
    202 void
    203 dns_request_cancel(dns_request_t *request);
    204 /*%<
    205  * Cancel 'request'.
    206  *
    207  * Requires:
    208  *
    209  *\li	'request' is a valid request.
    210  *
    211  * Ensures:
    212  *
    213  *\li	If the completion event for 'request' has not yet been sent, it
    214  *	will be sent, and the result code will be ISC_R_CANCELED.
    215  */
    216 
    217 isc_result_t
    218 dns_request_getresponse(dns_request_t *request, dns_message_t *message,
    219 			unsigned int options);
    220 /*%<
    221  * Get the response to 'request' by filling in 'message'.
    222  *
    223  * 'options' is passed to dns_message_parse().  See dns_message_parse()
    224  * for more details.
    225  *
    226  * Requires:
    227  *
    228  *\li	'request' is a valid request for which the caller has received the
    229  *	completion event.
    230  *
    231  *\li	The result code of the completion event was #ISC_R_SUCCESS.
    232  *
    233  * Returns:
    234  *
    235  *\li	ISC_R_SUCCESS
    236  *
    237  *\li	Any result that dns_message_parse() can return.
    238  */
    239 isc_buffer_t *
    240 dns_request_getanswer(dns_request_t *request);
    241 /*
    242  * Get the response to 'request' as a buffer.
    243  *
    244  * Requires:
    245  *
    246  *\li	'request' is a valid request for which the caller has received the
    247  *	completion event.
    248  *
    249  * Returns:
    250  *
    251  *\li	a pointer to the answer buffer.
    252  */
    253 
    254 bool
    255 dns_request_usedtcp(dns_request_t *request);
    256 /*%<
    257  * Return whether this query used TCP or not.  Setting #DNS_REQUESTOPT_TCP
    258  * in the call to dns_request_create() will cause the function to return
    259  * #true, otherwise the result is based on the query message size.
    260  *
    261  * Requires:
    262  *\li	'request' is a valid request.
    263  *
    264  * Returns:
    265  *\li	true	if TCP was used.
    266  *\li	false	if UDP was used.
    267  */
    268 
    269 void
    270 dns_request_destroy(dns_request_t **requestp);
    271 /*%<
    272  * Destroy 'request'.
    273  *
    274  * Requires:
    275  *
    276  *\li	'request' is a valid request for which the caller has received the
    277  *	completion event.
    278  *
    279  * Ensures:
    280  *
    281  *\li	*requestp == NULL
    282  */
    283 
    284 void *
    285 dns_request_getarg(dns_request_t *request);
    286 /*%<
    287  * Return the value of 'arg' that was passed in when 'request' was
    288  * created.
    289  */
    290 
    291 isc_result_t
    292 dns_request_getresult(dns_request_t *request);
    293 /*%<
    294  * Get the result code of 'request'. (This is to be called by the
    295  * completion handler.)
    296  */
    297 
    298 #if DNS_REQUEST_TRACE
    299 #define dns_request_ref(ptr) dns_request__ref(ptr, __func__, __FILE__, __LINE__)
    300 #define dns_request_unref(ptr) \
    301 	dns_request__unref(ptr, __func__, __FILE__, __LINE__)
    302 #define dns_request_attach(ptr, ptrp) \
    303 	dns_request__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
    304 #define dns_request_detach(ptrp) \
    305 	dns_request__detach(ptrp, __func__, __FILE__, __LINE__)
    306 ISC_REFCOUNT_TRACE_DECL(dns_request);
    307 #else
    308 ISC_REFCOUNT_DECL(dns_request);
    309 #endif
    310 
    311 ISC_LANG_ENDDECLS
    312