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