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_DISPATCH_H 15 #define DNS_DISPATCH_H 1 16 17 /***** 18 ***** Module Info 19 *****/ 20 21 /*! \file dns/dispatch.h 22 * \brief 23 * DNS Dispatch Management 24 * Shared UDP and single-use TCP dispatches for queries and responses. 25 * 26 * MP: 27 * 28 *\li All locking is performed internally to each dispatch. 29 * Restrictions apply to dns_dispatch_removeresponse(). 30 * 31 * Reliability: 32 * 33 * Resources: 34 * 35 * Security: 36 * 37 *\li Depends on the isc_socket_t and dns_message_t for prevention of 38 * buffer overruns. 39 * 40 * Standards: 41 * 42 *\li None. 43 */ 44 45 /*** 46 *** Imports 47 ***/ 48 49 #include <inttypes.h> 50 #include <stdbool.h> 51 52 #include <isc/buffer.h> 53 #include <isc/lang.h> 54 #include <isc/mutex.h> 55 #include <isc/socket.h> 56 #include <isc/types.h> 57 58 #include <dns/types.h> 59 60 ISC_LANG_BEGINDECLS 61 62 /*% 63 * This event is sent to a task when a response comes in. 64 * No part of this structure should ever be modified by the caller, 65 * other than parts of the buffer. The holy parts of the buffer are 66 * the base and size of the buffer. All other parts of the buffer may 67 * be used. On event delivery the used region contains the packet. 68 * 69 * "id" is the received message id, 70 * 71 * "addr" is the host that sent it to us, 72 * 73 * "buffer" holds state on the received data. 74 * 75 * The "free" routine for this event will clean up itself as well as 76 * any buffer space allocated from common pools. 77 */ 78 79 struct dns_dispatchevent { 80 ISC_EVENT_COMMON(dns_dispatchevent_t); /*%< standard event common */ 81 isc_result_t result; /*%< result code */ 82 int32_t id; /*%< message id */ 83 isc_sockaddr_t addr; /*%< address recv'd from */ 84 struct in6_pktinfo pktinfo; /*%< reply info for v6 */ 85 isc_buffer_t buffer; /*%< data buffer */ 86 uint32_t attributes; /*%< mirrored from socket.h */ 87 }; 88 89 /*% 90 * This is a set of one or more dispatches which can be retrieved 91 * round-robin fashion. 92 */ 93 struct dns_dispatchset { 94 isc_mem_t *mctx; 95 dns_dispatch_t **dispatches; 96 int ndisp; 97 int cur; 98 isc_mutex_t lock; 99 }; 100 101 /*@{*/ 102 /*% 103 * Attributes for added dispatchers. 104 * 105 * Values with the mask 0xffff0000 are application defined. 106 * Values with the mask 0x0000ffff are library defined. 107 * 108 * Insane values (like setting both TCP and UDP) are not caught. Don't 109 * do that. 110 * 111 * _PRIVATE 112 * The dispatcher cannot be shared. 113 * 114 * _TCP, _UDP 115 * The dispatcher is a TCP or UDP socket. 116 * 117 * _IPV4, _IPV6 118 * The dispatcher uses an IPv4 or IPv6 socket. 119 * 120 * _NOLISTEN 121 * The dispatcher should not listen on the socket. 122 * 123 * _MAKEQUERY 124 * The dispatcher can be used to issue queries to other servers, and 125 * accept replies from them. 126 * 127 * _RANDOMPORT 128 * Previously used to indicate that the port of a dispatch UDP must be 129 * chosen randomly. This behavior now always applies and the attribute 130 * is obsoleted. 131 * 132 * _EXCLUSIVE 133 * A separate socket will be used on-demand for each transaction. 134 */ 135 #define DNS_DISPATCHATTR_PRIVATE 0x00000001U 136 #define DNS_DISPATCHATTR_TCP 0x00000002U 137 #define DNS_DISPATCHATTR_UDP 0x00000004U 138 #define DNS_DISPATCHATTR_IPV4 0x00000008U 139 #define DNS_DISPATCHATTR_IPV6 0x00000010U 140 #define DNS_DISPATCHATTR_NOLISTEN 0x00000020U 141 #define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U 142 #define DNS_DISPATCHATTR_CONNECTED 0x00000080U 143 #define DNS_DISPATCHATTR_FIXEDID 0x00000100U 144 #define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U 145 #define DNS_DISPATCHATTR_CANREUSE 0x00000400U 146 /*@}*/ 147 148 /* 149 */ 150 #define DNS_DISPATCHOPT_FIXEDID 0x00000001U 151 152 isc_result_t 153 dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp); 154 /*%< 155 * Creates a new dispatchmgr object. 156 * 157 * Requires: 158 *\li "mctx" be a valid memory context. 159 * 160 *\li mgrp != NULL && *mgrp == NULL 161 * 162 * Returns: 163 *\li ISC_R_SUCCESS -- all ok 164 * 165 *\li anything else -- failure 166 */ 167 168 void 169 dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp); 170 /*%< 171 * Destroys the dispatchmgr when it becomes empty. This could be 172 * immediately. 173 * 174 * Requires: 175 *\li mgrp != NULL && *mgrp is a valid dispatchmgr. 176 */ 177 178 void 179 dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole); 180 /*%< 181 * Sets the dispatcher's "blackhole list," a list of addresses that will 182 * be ignored by all dispatchers created by the dispatchmgr. 183 * 184 * Requires: 185 * \li mgrp is a valid dispatchmgr 186 * \li blackhole is a valid acl 187 */ 188 189 dns_acl_t * 190 dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr); 191 /*%< 192 * Gets a pointer to the dispatcher's current blackhole list, 193 * without incrementing its reference count. 194 * 195 * Requires: 196 *\li mgr is a valid dispatchmgr 197 * Returns: 198 *\li A pointer to the current blackhole list, or NULL. 199 */ 200 201 void 202 dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr, 203 dns_portlist_t *portlist); 204 /*%< 205 * This function is deprecated. Use dns_dispatchmgr_setavailports() instead. 206 * 207 * Requires: 208 *\li mgr is a valid dispatchmgr 209 */ 210 211 dns_portlist_t * 212 dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr); 213 /*%< 214 * This function is deprecated and always returns NULL. 215 * 216 * Requires: 217 *\li mgr is a valid dispatchmgr 218 */ 219 220 isc_result_t 221 dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset, 222 isc_portset_t *v6portset); 223 /*%< 224 * Sets a list of UDP ports that can be used for outgoing UDP messages. 225 * 226 * Requires: 227 *\li mgr is a valid dispatchmgr 228 *\li v4portset is NULL or a valid port set 229 *\li v6portset is NULL or a valid port set 230 */ 231 232 void 233 dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats); 234 /*%< 235 * Sets statistics counter for the dispatchmgr. This function is expected to 236 * be called only on zone creation (when necessary). 237 * Once installed, it cannot be removed or replaced. Also, there is no 238 * interface to get the installed stats from the zone; the caller must keep the 239 * stats to reference (e.g. dump) it later. 240 * 241 * Requires: 242 *\li mgr is a valid dispatchmgr with no managed dispatch. 243 *\li stats is a valid statistics supporting resolver statistics counters 244 * (see dns/stats.h). 245 */ 246 247 isc_result_t 248 dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, 249 isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, 250 unsigned int buffersize, unsigned int maxbuffers, 251 unsigned int maxrequests, unsigned int buckets, 252 unsigned int increment, unsigned int attributes, 253 unsigned int mask, dns_dispatch_t **dispp); 254 255 isc_result_t 256 dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, 257 isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, 258 unsigned int buffersize, unsigned int maxbuffers, 259 unsigned int maxrequests, unsigned int buckets, 260 unsigned int increment, unsigned int attributes, 261 unsigned int mask, dns_dispatch_t **dispp, 262 dns_dispatch_t *dup); 263 /*%< 264 * Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find, 265 * otherwise create a new UDP dispatch. 266 * 267 * Requires: 268 *\li All pointer parameters be valid for their respective types. 269 * 270 *\li dispp != NULL && *disp == NULL 271 * 272 *\li 512 <= buffersize <= 64k 273 * 274 *\li maxbuffers > 0 275 * 276 *\li buckets < 2097169 277 * 278 *\li increment > buckets 279 * 280 *\li (attributes & DNS_DISPATCHATTR_TCP) == 0 281 * 282 * Returns: 283 *\li ISC_R_SUCCESS -- success. 284 * 285 *\li Anything else -- failure. 286 */ 287 288 isc_result_t 289 dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, 290 isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, 291 const isc_sockaddr_t *destaddr, unsigned int buffersize, 292 unsigned int maxbuffers, unsigned int maxrequests, 293 unsigned int buckets, unsigned int increment, 294 unsigned int attributes, dns_dispatch_t **dispp); 295 /*%< 296 * Create a new dns_dispatch and attach it to the provided isc_socket_t. 297 * 298 * For all dispatches, "buffersize" is the maximum packet size we will 299 * accept. 300 * 301 * "maxbuffers" and "maxrequests" control the number of buffers in the 302 * overall system and the number of buffers which can be allocated to 303 * requests. 304 * 305 * "buckets" is the number of buckets to use, and should be prime. 306 * 307 * "increment" is used in a collision avoidance function, and needs to be 308 * a prime > buckets, and not 2. 309 * 310 * Requires: 311 * 312 *\li mgr is a valid dispatch manager. 313 * 314 *\li sock is a valid. 315 * 316 *\li task is a valid task that can be used internally to this dispatcher. 317 * 318 * \li 512 <= buffersize <= 64k 319 * 320 *\li maxbuffers > 0. 321 * 322 *\li maxrequests <= maxbuffers. 323 * 324 *\li buckets < 2097169 (the next prime after 65536 * 32) 325 * 326 *\li increment > buckets (and prime). 327 * 328 *\li attributes includes #DNS_DISPATCHATTR_TCP and does not include 329 * #DNS_DISPATCHATTR_UDP. 330 * 331 * Returns: 332 *\li ISC_R_SUCCESS -- success. 333 * 334 *\li Anything else -- failure. 335 */ 336 337 void 338 dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp); 339 /*%< 340 * Attach to a dispatch handle. 341 * 342 * Requires: 343 *\li disp is valid. 344 * 345 *\li dispp != NULL && *dispp == NULL 346 */ 347 348 void 349 dns_dispatch_detach(dns_dispatch_t **dispp); 350 /*%< 351 * Detaches from the dispatch. 352 * 353 * Requires: 354 *\li dispp != NULL and *dispp be a valid dispatch. 355 */ 356 357 void 358 dns_dispatch_starttcp(dns_dispatch_t *disp); 359 /*%< 360 * Start processing of a TCP dispatch once the socket connects. 361 * 362 * Requires: 363 *\li 'disp' is valid. 364 */ 365 366 isc_result_t 367 dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, 368 const isc_sockaddr_t *localaddr, bool *connected, 369 dns_dispatch_t **dispp); 370 /* 371 * Attempt to connect to a existing TCP connection (connection completed 372 * if connected == NULL). 373 */ 374 375 isc_result_t 376 dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, 377 const isc_sockaddr_t *dest, isc_task_t *task, 378 isc_taskaction_t action, void *arg, uint16_t *idp, 379 dns_dispentry_t **resp, isc_socketmgr_t *sockmgr); 380 /*%< 381 * Add a response entry for this dispatch. 382 * 383 * "*idp" is filled in with the assigned message ID, and *resp is filled in 384 * to contain the magic token used to request event flow stop. 385 * 386 * Arranges for the given task to get a callback for response packets. When 387 * the event is delivered, it must be returned using dns_dispatch_freeevent() 388 * or through dns_dispatch_removeresponse() for another to be delivered. 389 * 390 * Requires: 391 *\li "idp" be non-NULL. 392 * 393 *\li "task" "action" and "arg" be set as appropriate. 394 * 395 *\li "dest" be non-NULL and valid. 396 * 397 *\li "resp" be non-NULL and *resp be NULL 398 * 399 *\li "sockmgr" be NULL or a valid socket manager. If 'disp' has 400 * the DNS_DISPATCHATTR_EXCLUSIVE attribute, this must not be NULL, 401 * which also means dns_dispatch_addresponse() cannot be used. 402 * 403 * Ensures: 404 * 405 *\li <id, dest> is a unique tuple. That means incoming messages 406 * are identifiable. 407 * 408 * Returns: 409 * 410 *\li ISC_R_SUCCESS -- all is well. 411 *\li ISC_R_NOMEMORY -- memory could not be allocated. 412 *\li ISC_R_NOMORE -- no more message ids can be allocated 413 * for this destination. 414 */ 415 416 void 417 dns_dispatch_removeresponse(dns_dispentry_t **resp, 418 dns_dispatchevent_t **sockevent); 419 /*%< 420 * Stops the flow of responses for the provided id and destination. 421 * If "sockevent" is non-NULL, the dispatch event and associated buffer is 422 * also returned to the system. 423 * 424 * Requires: 425 *\li "resp" != NULL and "*resp" contain a value previously allocated 426 * by dns_dispatch_addresponse(); 427 * 428 *\li May only be called from within the task given as the 'task' 429 * argument to dns_dispatch_addresponse() when allocating '*resp'. 430 */ 431 432 isc_socket_t * 433 dns_dispatch_getentrysocket(dns_dispentry_t *resp); 434 435 isc_socket_t * 436 dns_dispatch_getsocket(dns_dispatch_t *disp); 437 /*%< 438 * Return the socket associated with this dispatcher. 439 * 440 * Requires: 441 *\li disp is valid. 442 * 443 * Returns: 444 *\li The socket the dispatcher is using. 445 */ 446 447 isc_result_t 448 dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp); 449 /*%< 450 * Return the local address for this dispatch. 451 * This currently only works for dispatches using UDP sockets. 452 * 453 * Requires: 454 *\li disp is valid. 455 *\li addrp to be non null. 456 * 457 * Returns: 458 *\li ISC_R_SUCCESS 459 *\li ISC_R_NOTIMPLEMENTED 460 */ 461 462 void 463 dns_dispatch_cancel(dns_dispatch_t *disp); 464 /*%< 465 * cancel outstanding clients 466 * 467 * Requires: 468 *\li disp is valid. 469 */ 470 471 unsigned int 472 dns_dispatch_getattributes(dns_dispatch_t *disp); 473 /*%< 474 * Return the attributes (DNS_DISPATCHATTR_xxx) of this dispatch. Only the 475 * non-changeable attributes are expected to be referenced by the caller. 476 * 477 * Requires: 478 *\li disp is valid. 479 */ 480 481 void 482 dns_dispatch_changeattributes(dns_dispatch_t *disp, unsigned int attributes, 483 unsigned int mask); 484 /*%< 485 * Set the bits described by "mask" to the corresponding values in 486 * "attributes". 487 * 488 * That is: 489 * 490 * \code 491 * new = (old & ~mask) | (attributes & mask) 492 * \endcode 493 * 494 * This function has a side effect when #DNS_DISPATCHATTR_NOLISTEN changes. 495 * When the flag becomes off, the dispatch will start receiving on the 496 * corresponding socket. When the flag becomes on, receive events on the 497 * corresponding socket will be canceled. 498 * 499 * Requires: 500 *\li disp is valid. 501 * 502 *\li attributes are reasonable for the dispatch. That is, setting the UDP 503 * attribute on a TCP socket isn't reasonable. 504 */ 505 506 void 507 dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event); 508 /*%< 509 * Inform the dispatcher of a socket receive. This is used for sockets 510 * shared between dispatchers and clients. If the dispatcher fails to copy 511 * or send the event, nothing happens. 512 * 513 * If the attribute DNS_DISPATCHATTR_NOLISTEN is not set, then 514 * the dispatch is already handling a recv; return immediately. 515 * 516 * Requires: 517 *\li disp is valid, and the attribute DNS_DISPATCHATTR_NOLISTEN is set. 518 * event != NULL 519 */ 520 521 dns_dispatch_t * 522 dns_dispatchset_get(dns_dispatchset_t *dset); 523 /*%< 524 * Retrieve the next dispatch from dispatch set 'dset', and increment 525 * the round-robin counter. 526 * 527 * Requires: 528 *\li dset != NULL 529 */ 530 531 isc_result_t 532 dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, 533 isc_taskmgr_t *taskmgr, dns_dispatch_t *source, 534 dns_dispatchset_t **dsetp, int n); 535 /*%< 536 * Given a valid dispatch 'source', create a dispatch set containing 537 * 'n' UDP dispatches, with the remainder filled out by clones of the 538 * source. 539 * 540 * Requires: 541 *\li source is a valid UDP dispatcher 542 *\li dsetp != NULL, *dsetp == NULL 543 */ 544 545 void 546 dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task); 547 /*%< 548 * Cancel socket operations for the dispatches in 'dset'. 549 */ 550 551 void 552 dns_dispatchset_destroy(dns_dispatchset_t **dsetp); 553 /*%< 554 * Dereference all the dispatches in '*dsetp', free the dispatchset 555 * memory, and set *dsetp to NULL. 556 * 557 * Requires: 558 *\li dset is valid 559 */ 560 561 void 562 dns_dispatch_setdscp(dns_dispatch_t *disp, isc_dscp_t dscp); 563 isc_dscp_t 564 dns_dispatch_getdscp(dns_dispatch_t *disp); 565 /*%< 566 * Set/get the DSCP value to be used when sending responses to clients, 567 * as defined in the "listen-on" or "listen-on-v6" statements. 568 * 569 * Requires: 570 *\li disp is valid. 571 */ 572 573 isc_result_t 574 dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent); 575 /*%< 576 * Free the sockevent and trigger the sending of the next item off the 577 * dispatch queue if present. 578 * 579 * Requires: 580 *\li resp is valid 581 *\li *sockevent to be valid 582 */ 583 584 ISC_LANG_ENDDECLS 585 586 #endif /* DNS_DISPATCH_H */ 587