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