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