1/* 2 * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: dispatch.h,v 1.64 2011/07/28 23:47:58 tbox Exp $ */ 19 20#ifndef DNS_DISPATCH_H 21#define DNS_DISPATCH_H 1 22 23/***** 24 ***** Module Info 25 *****/ 26 27/*! \file dns/dispatch.h 28 * \brief 29 * DNS Dispatch Management 30 * Shared UDP and single-use TCP dispatches for queries and responses. 31 * 32 * MP: 33 * 34 *\li All locking is performed internally to each dispatch. 35 * Restrictions apply to dns_dispatch_removeresponse(). 36 * 37 * Reliability: 38 * 39 * Resources: 40 * 41 * Security: 42 * 43 *\li Depends on the isc_socket_t and dns_message_t for prevention of 44 * buffer overruns. 45 * 46 * Standards: 47 * 48 *\li None. 49 */ 50 51/*** 52 *** Imports 53 ***/ 54 55#include <isc/buffer.h> 56#include <isc/lang.h> 57#include <isc/mutex.h> 58#include <isc/socket.h> 59#include <isc/types.h> 60 61#include <dns/types.h> 62 63ISC_LANG_BEGINDECLS 64 65/*% 66 * This event is sent to a task when a response comes in. 67 * No part of this structure should ever be modified by the caller, 68 * other than parts of the buffer. The holy parts of the buffer are 69 * the base and size of the buffer. All other parts of the buffer may 70 * be used. On event delivery the used region contains the packet. 71 * 72 * "id" is the received message id, 73 * 74 * "addr" is the host that sent it to us, 75 * 76 * "buffer" holds state on the received data. 77 * 78 * The "free" routine for this event will clean up itself as well as 79 * any buffer space allocated from common pools. 80 */ 81 82struct dns_dispatchevent { 83 ISC_EVENT_COMMON(dns_dispatchevent_t); /*%< standard event common */ 84 isc_result_t result; /*%< result code */ 85 isc_int32_t id; /*%< message id */ 86 isc_sockaddr_t addr; /*%< address recv'd from */ 87 struct in6_pktinfo pktinfo; /*%< reply info for v6 */ 88 isc_buffer_t buffer; /*%< data buffer */ 89 isc_uint32_t attributes; /*%< mirrored from socket.h */ 90}; 91 92/*% 93 * This is a set of one or more dispatches which can be retrieved 94 * round-robin fashion. 95 */ 96struct dns_dispatchset { 97 isc_mem_t *mctx; 98 dns_dispatch_t **dispatches; 99 int ndisp; 100 int cur; 101 isc_mutex_t lock; 102}; 103 104/*@{*/ 105/*% 106 * Attributes for added dispatchers. 107 * 108 * Values with the mask 0xffff0000 are application defined. 109 * Values with the mask 0x0000ffff are library defined. 110 * 111 * Insane values (like setting both TCP and UDP) are not caught. Don't 112 * do that. 113 * 114 * _PRIVATE 115 * The dispatcher cannot be shared. 116 * 117 * _TCP, _UDP 118 * The dispatcher is a TCP or UDP socket. 119 * 120 * _IPV4, _IPV6 121 * The dispatcher uses an IPv4 or IPv6 socket. 122 * 123 * _NOLISTEN 124 * The dispatcher should not listen on the socket. 125 * 126 * _MAKEQUERY 127 * The dispatcher can be used to issue queries to other servers, and 128 * accept replies from them. 129 * 130 * _RANDOMPORT 131 * Previously used to indicate that the port of a dispatch UDP must be 132 * chosen randomly. This behavior now always applies and the attribute 133 * is obsoleted. 134 * 135 * _EXCLUSIVE 136 * A separate socket will be used on-demand for each transaction. 137 */ 138#define DNS_DISPATCHATTR_PRIVATE 0x00000001U 139#define DNS_DISPATCHATTR_TCP 0x00000002U 140#define DNS_DISPATCHATTR_UDP 0x00000004U 141#define DNS_DISPATCHATTR_IPV4 0x00000008U 142#define DNS_DISPATCHATTR_IPV6 0x00000010U 143#define DNS_DISPATCHATTR_NOLISTEN 0x00000020U 144#define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U 145#define DNS_DISPATCHATTR_CONNECTED 0x00000080U 146/*#define DNS_DISPATCHATTR_RANDOMPORT 0x00000100U*/ 147#define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U 148/*@}*/ 149 150isc_result_t 151dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy, 152 dns_dispatchmgr_t **mgrp); 153/*%< 154 * Creates a new dispatchmgr object. 155 * 156 * Requires: 157 *\li "mctx" be a valid memory context. 158 * 159 *\li mgrp != NULL && *mgrp == NULL 160 * 161 *\li "entropy" may be NULL, in which case an insecure random generator 162 * will be used. If it is non-NULL, it must be a valid entropy 163 * source. 164 * 165 * Returns: 166 *\li ISC_R_SUCCESS -- all ok 167 * 168 *\li anything else -- failure 169 */ 170 171 172void 173dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp); 174/*%< 175 * Destroys the dispatchmgr when it becomes empty. This could be 176 * immediately. 177 * 178 * Requires: 179 *\li mgrp != NULL && *mgrp is a valid dispatchmgr. 180 */ 181 182 183void 184dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole); 185/*%< 186 * Sets the dispatcher's "blackhole list," a list of addresses that will 187 * be ignored by all dispatchers created by the dispatchmgr. 188 * 189 * Requires: 190 * \li mgrp is a valid dispatchmgr 191 * \li blackhole is a valid acl 192 */ 193 194 195dns_acl_t * 196dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr); 197/*%< 198 * Gets a pointer to the dispatcher's current blackhole list, 199 * without incrementing its reference count. 200 * 201 * Requires: 202 *\li mgr is a valid dispatchmgr 203 * Returns: 204 *\li A pointer to the current blackhole list, or NULL. 205 */ 206 207void 208dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr, 209 dns_portlist_t *portlist); 210/*%< 211 * This function is deprecated. Use dns_dispatchmgr_setavailports() instead. 212 * 213 * Requires: 214 *\li mgr is a valid dispatchmgr 215 */ 216 217dns_portlist_t * 218dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr); 219/*%< 220 * This function is deprecated and always returns NULL. 221 * 222 * Requires: 223 *\li mgr is a valid dispatchmgr 224 */ 225 226isc_result_t 227dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset, 228 isc_portset_t *v6portset); 229/*%< 230 * Sets a list of UDP ports that can be used for outgoing UDP messages. 231 * 232 * Requires: 233 *\li mgr is a valid dispatchmgr 234 *\li v4portset is NULL or a valid port set 235 *\li v6portset is NULL or a valid port set 236 */ 237 238void 239dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats); 240/*%< 241 * Sets statistics counter for the dispatchmgr. This function is expected to 242 * be called only on zone creation (when necessary). 243 * Once installed, it cannot be removed or replaced. Also, there is no 244 * interface to get the installed stats from the zone; the caller must keep the 245 * stats to reference (e.g. dump) it later. 246 * 247 * Requires: 248 *\li mgr is a valid dispatchmgr with no managed dispatch. 249 *\li stats is a valid statistics supporting resolver statistics counters 250 * (see dns/stats.h). 251 */ 252 253isc_result_t 254dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, 255 isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, 256 unsigned int buffersize, 257 unsigned int maxbuffers, unsigned int maxrequests, 258 unsigned int buckets, unsigned int increment, 259 unsigned int attributes, unsigned int mask, 260 dns_dispatch_t **dispp); 261 262isc_result_t 263dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, 264 isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, 265 unsigned int buffersize, 266 unsigned int maxbuffers, unsigned int maxrequests, 267 unsigned int buckets, unsigned int increment, 268 unsigned int attributes, unsigned int mask, 269 dns_dispatch_t **dispp, dns_dispatch_t *dup); 270/*%< 271 * Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find, 272 * otherwise create a new UDP dispatch. 273 * 274 * Requires: 275 *\li All pointer parameters be valid for their respective types. 276 * 277 *\li dispp != NULL && *disp == NULL 278 * 279 *\li 512 <= buffersize <= 64k 280 * 281 *\li maxbuffers > 0 282 * 283 *\li buckets < 2097169 284 * 285 *\li increment > buckets 286 * 287 *\li (attributes & DNS_DISPATCHATTR_TCP) == 0 288 * 289 * Returns: 290 *\li ISC_R_SUCCESS -- success. 291 * 292 *\li Anything else -- failure. 293 */ 294 295isc_result_t 296dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, 297 isc_taskmgr_t *taskmgr, unsigned int buffersize, 298 unsigned int maxbuffers, unsigned int maxrequests, 299 unsigned int buckets, unsigned int increment, 300 unsigned int attributes, dns_dispatch_t **dispp); 301/*%< 302 * Create a new dns_dispatch and attach it to the provided isc_socket_t. 303 * 304 * For all dispatches, "buffersize" is the maximum packet size we will 305 * accept. 306 * 307 * "maxbuffers" and "maxrequests" control the number of buffers in the 308 * overall system and the number of buffers which can be allocated to 309 * requests. 310 * 311 * "buckets" is the number of buckets to use, and should be prime. 312 * 313 * "increment" is used in a collision avoidance function, and needs to be 314 * a prime > buckets, and not 2. 315 * 316 * Requires: 317 * 318 *\li mgr is a valid dispatch manager. 319 * 320 *\li sock is a valid. 321 * 322 *\li task is a valid task that can be used internally to this dispatcher. 323 * 324 * \li 512 <= buffersize <= 64k 325 * 326 *\li maxbuffers > 0. 327 * 328 *\li maxrequests <= maxbuffers. 329 * 330 *\li buckets < 2097169 (the next prime after 65536 * 32) 331 * 332 *\li increment > buckets (and prime). 333 * 334 *\li attributes includes #DNS_DISPATCHATTR_TCP and does not include 335 * #DNS_DISPATCHATTR_UDP. 336 * 337 * Returns: 338 *\li ISC_R_SUCCESS -- success. 339 * 340 *\li Anything else -- failure. 341 */ 342 343void 344dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp); 345/*%< 346 * Attach to a dispatch handle. 347 * 348 * Requires: 349 *\li disp is valid. 350 * 351 *\li dispp != NULL && *dispp == NULL 352 */ 353 354void 355dns_dispatch_detach(dns_dispatch_t **dispp); 356/*%< 357 * Detaches from the dispatch. 358 * 359 * Requires: 360 *\li dispp != NULL and *dispp be a valid dispatch. 361 */ 362 363void 364dns_dispatch_starttcp(dns_dispatch_t *disp); 365/*%< 366 * Start processing of a TCP dispatch once the socket connects. 367 * 368 * Requires: 369 *\li 'disp' is valid. 370 */ 371 372isc_result_t 373dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, 374 isc_task_t *task, isc_taskaction_t action, void *arg, 375 isc_uint16_t *idp, dns_dispentry_t **resp, 376 isc_socketmgr_t *sockmgr); 377 378isc_result_t 379dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest, 380 isc_task_t *task, isc_taskaction_t action, void *arg, 381 isc_uint16_t *idp, dns_dispentry_t **resp); 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 419void 420dns_dispatch_removeresponse(dns_dispentry_t **resp, 421 dns_dispatchevent_t **sockevent); 422/*%< 423 * Stops the flow of responses for the provided id and destination. 424 * If "sockevent" is non-NULL, the dispatch event and associated buffer is 425 * also returned to the system. 426 * 427 * Requires: 428 *\li "resp" != NULL and "*resp" contain a value previously allocated 429 * by dns_dispatch_addresponse(); 430 * 431 *\li May only be called from within the task given as the 'task' 432 * argument to dns_dispatch_addresponse() when allocating '*resp'. 433 */ 434 435isc_socket_t * 436dns_dispatch_getentrysocket(dns_dispentry_t *resp); 437 438isc_socket_t * 439dns_dispatch_getsocket(dns_dispatch_t *disp); 440/*%< 441 * Return the socket associated with this dispatcher. 442 * 443 * Requires: 444 *\li disp is valid. 445 * 446 * Returns: 447 *\li The socket the dispatcher is using. 448 */ 449 450isc_result_t 451dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp); 452/*%< 453 * Return the local address for this dispatch. 454 * This currently only works for dispatches using UDP sockets. 455 * 456 * Requires: 457 *\li disp is valid. 458 *\li addrp to be non null. 459 * 460 * Returns: 461 *\li ISC_R_SUCCESS 462 *\li ISC_R_NOTIMPLEMENTED 463 */ 464 465void 466dns_dispatch_cancel(dns_dispatch_t *disp); 467/*%< 468 * cancel outstanding clients 469 * 470 * Requires: 471 *\li disp is valid. 472 */ 473 474unsigned int 475dns_dispatch_getattributes(dns_dispatch_t *disp); 476/*%< 477 * Return the attributes (DNS_DISPATCHATTR_xxx) of this dispatch. Only the 478 * non-changeable attributes are expected to be referenced by the caller. 479 * 480 * Requires: 481 *\li disp is valid. 482 */ 483 484void 485dns_dispatch_changeattributes(dns_dispatch_t *disp, 486 unsigned int attributes, unsigned int mask); 487/*%< 488 * Set the bits described by "mask" to the corresponding values in 489 * "attributes". 490 * 491 * That is: 492 * 493 * \code 494 * new = (old & ~mask) | (attributes & mask) 495 * \endcode 496 * 497 * This function has a side effect when #DNS_DISPATCHATTR_NOLISTEN changes. 498 * When the flag becomes off, the dispatch will start receiving on the 499 * corresponding socket. When the flag becomes on, receive events on the 500 * corresponding socket will be canceled. 501 * 502 * Requires: 503 *\li disp is valid. 504 * 505 *\li attributes are reasonable for the dispatch. That is, setting the UDP 506 * attribute on a TCP socket isn't reasonable. 507 */ 508 509void 510dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event); 511/*%< 512 * Inform the dispatcher of a socket receive. This is used for sockets 513 * shared between dispatchers and clients. If the dispatcher fails to copy 514 * or send the event, nothing happens. 515 * 516 * Requires: 517 *\li disp is valid, and the attribute DNS_DISPATCHATTR_NOLISTEN is set. 518 * event != NULL 519 */ 520 521dns_dispatch_t * 522dns_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 531isc_result_t 532dns_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 545void 546dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task); 547/*%< 548 * Cancel socket operations for the dispatches in 'dset'. 549 */ 550 551void 552dns_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 561ISC_LANG_ENDDECLS 562 563#endif /* DNS_DISPATCH_H */ 564