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