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