1 /* $NetBSD: request.h,v 1.1 2024/02/18 20:57:38 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 #ifndef DNS_REQUEST_H 17 #define DNS_REQUEST_H 1 18 19 /***** 20 ***** Module Info 21 *****/ 22 23 /*! \file dns/request.h 24 * 25 * \brief 26 * The request module provides simple request/response services useful for 27 * sending SOA queries, DNS Notify messages, and dynamic update requests. 28 * 29 * MP: 30 *\li The module ensures appropriate synchronization of data structures it 31 * creates and manipulates. 32 * 33 * Resources: 34 *\li TBS 35 * 36 * Security: 37 *\li No anticipated impact. 38 */ 39 40 #include <stdbool.h> 41 42 #include <isc/event.h> 43 #include <isc/lang.h> 44 45 #include <dns/types.h> 46 47 #define DNS_REQUESTOPT_TCP 0x00000001U 48 #define DNS_REQUESTOPT_CASE 0x00000002U 49 #define DNS_REQUESTOPT_FIXEDID 0x00000004U 50 #define DNS_REQUESTOPT_SHARE 0x00000008U 51 52 typedef struct dns_requestevent { 53 ISC_EVENT_COMMON(struct dns_requestevent); 54 isc_result_t result; 55 dns_request_t *request; 56 } dns_requestevent_t; 57 58 ISC_LANG_BEGINDECLS 59 60 isc_result_t 61 dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, 62 isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, 63 dns_dispatchmgr_t *dispatchmgr, 64 dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, 65 dns_requestmgr_t **requestmgrp); 66 /*%< 67 * Create a request manager. 68 * 69 * Requires: 70 * 71 *\li 'mctx' is a valid memory context. 72 * 73 *\li 'timermgr' is a valid timer manager. 74 * 75 *\li 'socketmgr' is a valid socket manager. 76 * 77 *\li 'taskmgr' is a valid task manager. 78 * 79 *\li 'dispatchv4' is a valid dispatcher with an IPv4 UDP socket, or is NULL. 80 * 81 *\li 'dispatchv6' is a valid dispatcher with an IPv6 UDP socket, or is NULL. 82 * 83 *\li requestmgrp != NULL && *requestmgrp == NULL 84 * 85 * Ensures: 86 * 87 *\li On success, *requestmgrp is a valid request manager. 88 * 89 * Returns: 90 * 91 *\li ISC_R_SUCCESS 92 * 93 *\li Any other result indicates failure. 94 */ 95 96 void 97 dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task, 98 isc_event_t **eventp); 99 /*%< 100 * Send '*eventp' to 'task' when 'requestmgr' has completed shutdown. 101 * 102 * Notes: 103 * 104 *\li It is not safe to detach the last reference to 'requestmgr' until 105 * shutdown is complete. 106 * 107 * Requires: 108 * 109 *\li 'requestmgr' is a valid request manager. 110 * 111 *\li 'task' is a valid task. 112 * 113 *\li *eventp is a valid event. 114 * 115 * Ensures: 116 * 117 *\li *eventp == NULL. 118 */ 119 120 void 121 dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr); 122 /*%< 123 * Start the shutdown process for 'requestmgr'. 124 * 125 * Notes: 126 * 127 *\li This call has no effect if the request manager is already shutting 128 * down. 129 * 130 * Requires: 131 * 132 *\li 'requestmgr' is a valid requestmgr. 133 */ 134 135 void 136 dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp); 137 /*%< 138 * Attach to the request manager. dns_requestmgr_shutdown() must not 139 * have been called on 'source' prior to calling dns_requestmgr_attach(). 140 * 141 * Requires: 142 * 143 *\li 'source' is a valid requestmgr. 144 * 145 *\li 'targetp' to be non NULL and '*targetp' to be NULL. 146 */ 147 148 void 149 dns_requestmgr_detach(dns_requestmgr_t **requestmgrp); 150 /*%< 151 * Detach from the given requestmgr. If this is the final detach 152 * requestmgr will be destroyed. dns_requestmgr_shutdown() must 153 * be called before the final detach. 154 * 155 * Requires: 156 * 157 *\li '*requestmgrp' is a valid requestmgr. 158 * 159 * Ensures: 160 *\li '*requestmgrp' is NULL. 161 */ 162 163 isc_result_t 164 dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, 165 const isc_sockaddr_t *address, unsigned int options, 166 dns_tsigkey_t *key, unsigned int timeout, isc_task_t *task, 167 isc_taskaction_t action, void *arg, 168 dns_request_t **requestp); 169 /*%< 170 * Create and send a request. 171 * 172 * Notes: 173 * 174 *\li 'message' will be rendered and sent to 'address'. If the 175 * #DNS_REQUESTOPT_TCP option is set, TCP will be used, 176 * #DNS_REQUESTOPT_SHARE option is set too, connecting TCP 177 * (vs. connected) will be shared too. The request 178 * will timeout after 'timeout' seconds. 179 * 180 *\li If the #DNS_REQUESTOPT_CASE option is set, use case sensitive 181 * compression. 182 * 183 *\li When the request completes, successfully, due to a timeout, or 184 * because it was canceled, a completion event will be sent to 'task'. 185 * 186 * Requires: 187 * 188 *\li 'message' is a valid DNS message. 189 * 190 *\li 'address' is a valid sockaddr. 191 * 192 *\li 'timeout' > 0 193 * 194 *\li 'task' is a valid task. 195 * 196 *\li requestp != NULL && *requestp == NULL 197 */ 198 199 isc_result_t 200 dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message, 201 const isc_sockaddr_t *srcaddr, 202 const isc_sockaddr_t *destaddr, isc_dscp_t dscp, 203 unsigned int options, dns_tsigkey_t *key, 204 unsigned int timeout, unsigned int udptimeout, 205 unsigned int udpretries, isc_task_t *task, 206 isc_taskaction_t action, void *arg, 207 dns_request_t **requestp); 208 /*%< 209 * Create and send a request. 210 * 211 * Notes: 212 * 213 *\li 'message' will be rendered and sent to 'address'. If the 214 * #DNS_REQUESTOPT_TCP option is set, TCP will be used, 215 * #DNS_REQUESTOPT_SHARE option is set too, connecting TCP 216 * (vs. connected) will be shared too. The request 217 * will timeout after 'timeout' seconds. UDP requests will be resent 218 * at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero. 219 * 220 *\li If the #DNS_REQUESTOPT_CASE option is set, use case sensitive 221 * compression. 222 * 223 *\li When the request completes, successfully, due to a timeout, or 224 * because it was canceled, a completion event will be sent to 'task'. 225 * 226 * Requires: 227 * 228 *\li 'message' is a valid DNS message. 229 * 230 *\li 'dstaddr' is a valid sockaddr. 231 * 232 *\li 'srcaddr' is a valid sockaddr or NULL. 233 * 234 *\li 'srcaddr' and 'dstaddr' are the same protocol family. 235 * 236 *\li 'timeout' > 0 237 * 238 *\li 'task' is a valid task. 239 * 240 *\li requestp != NULL && *requestp == NULL 241 */ 242 243 isc_result_t 244 dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, 245 const isc_sockaddr_t *srcaddr, 246 const isc_sockaddr_t *destaddr, isc_dscp_t dscp, 247 unsigned int options, unsigned int timeout, 248 unsigned int udptimeout, unsigned int udpretries, 249 isc_task_t *task, isc_taskaction_t action, void *arg, 250 dns_request_t **requestp); 251 /*!< 252 * \brief Create and send a request. 253 * 254 * Notes: 255 * 256 *\li 'msgbuf' will be sent to 'destaddr' after setting the id. If the 257 * #DNS_REQUESTOPT_TCP option is set, TCP will be used, 258 * #DNS_REQUESTOPT_SHARE option is set too, connecting TCP 259 * (vs. connected) will be shared too. The request 260 * will timeout after 'timeout' seconds. UDP requests will be resent 261 * at 'udptimeout' intervals if non-zero or if 'udpretries' is not zero. 262 * 263 *\li When the request completes, successfully, due to a timeout, or 264 * because it was canceled, a completion event will be sent to 'task'. 265 * 266 * Requires: 267 * 268 *\li 'msgbuf' is a valid DNS message in compressed wire format. 269 * 270 *\li 'destaddr' is a valid sockaddr. 271 * 272 *\li 'srcaddr' is a valid sockaddr or NULL. 273 * 274 *\li 'srcaddr' and 'dstaddr' are the same protocol family. 275 * 276 *\li 'timeout' > 0 277 * 278 *\li 'task' is a valid task. 279 * 280 *\li requestp != NULL && *requestp == NULL 281 */ 282 283 void 284 dns_request_cancel(dns_request_t *request); 285 /*%< 286 * Cancel 'request'. 287 * 288 * Requires: 289 * 290 *\li 'request' is a valid request. 291 * 292 * Ensures: 293 * 294 *\li If the completion event for 'request' has not yet been sent, it 295 * will be sent, and the result code will be ISC_R_CANCELED. 296 */ 297 298 isc_result_t 299 dns_request_getresponse(dns_request_t *request, dns_message_t *message, 300 unsigned int options); 301 /*%< 302 * Get the response to 'request' by filling in 'message'. 303 * 304 * 'options' is passed to dns_message_parse(). See dns_message_parse() 305 * for more details. 306 * 307 * Requires: 308 * 309 *\li 'request' is a valid request for which the caller has received the 310 * completion event. 311 * 312 *\li The result code of the completion event was #ISC_R_SUCCESS. 313 * 314 * Returns: 315 * 316 *\li ISC_R_SUCCESS 317 * 318 *\li Any result that dns_message_parse() can return. 319 */ 320 isc_buffer_t * 321 dns_request_getanswer(dns_request_t *request); 322 /* 323 * Get the response to 'request' as a buffer. 324 * 325 * Requires: 326 * 327 *\li 'request' is a valid request for which the caller has received the 328 * completion event. 329 * 330 * Returns: 331 * 332 *\li a pointer to the answer buffer. 333 */ 334 335 bool 336 dns_request_usedtcp(dns_request_t *request); 337 /*%< 338 * Return whether this query used TCP or not. Setting #DNS_REQUESTOPT_TCP 339 * in the call to dns_request_create() will cause the function to return 340 * #true, otherwise the result is based on the query message size. 341 * 342 * Requires: 343 *\li 'request' is a valid request. 344 * 345 * Returns: 346 *\li true if TCP was used. 347 *\li false if UDP was used. 348 */ 349 350 void 351 dns_request_destroy(dns_request_t **requestp); 352 /*%< 353 * Destroy 'request'. 354 * 355 * Requires: 356 * 357 *\li 'request' is a valid request for which the caller has received the 358 * completion event. 359 * 360 * Ensures: 361 * 362 *\li *requestp == NULL 363 */ 364 365 ISC_LANG_ENDDECLS 366 367 #endif /* DNS_REQUEST_H */ 368