2 * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.
18 /* $Id: dispatch.h,v 1.64 2011/07/28 23:47:58 tbox Exp $ */
20 #ifndef DNS_DISPATCH_H
21 #define DNS_DISPATCH_H 1
27 /*! \file dns/dispatch.h
29 * DNS Dispatch Management
30 * Shared UDP and single-use TCP dispatches for queries and responses.
34 *\li All locking is performed internally to each dispatch.
35 * Restrictions apply to dns_dispatch_removeresponse().
43 *\li Depends on the isc_socket_t and dns_message_t for prevention of
55 #include <isc/buffer.h>
57 #include <isc/mutex.h>
58 #include <isc/socket.h>
59 #include <isc/types.h>
61 #include <dns/types.h>
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.
72 * "id" is the received message id,
74 * "addr" is the host that sent it to us,
76 * "buffer" holds state on the received data.
78 * The "free" routine for this event will clean up itself as well as
79 * any buffer space allocated from common pools.
82 struct 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 */
93 * This is a set of one or more dispatches which can be retrieved
94 * round-robin fashion.
96 struct dns_dispatchset {
98 dns_dispatch_t **dispatches;
106 * Attributes for added dispatchers.
108 * Values with the mask 0xffff0000 are application defined.
109 * Values with the mask 0x0000ffff are library defined.
111 * Insane values (like setting both TCP and UDP) are not caught. Don't
115 * The dispatcher cannot be shared.
118 * The dispatcher is a TCP or UDP socket.
121 * The dispatcher uses an IPv4 or IPv6 socket.
124 * The dispatcher should not listen on the socket.
127 * The dispatcher can be used to issue queries to other servers, and
128 * accept replies from them.
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
136 * A separate socket will be used on-demand for each transaction.
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
151 dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
152 dns_dispatchmgr_t **mgrp);
154 * Creates a new dispatchmgr object.
157 *\li "mctx" be a valid memory context.
159 *\li mgrp != NULL && *mgrp == NULL
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
166 *\li ISC_R_SUCCESS -- all ok
168 *\li anything else -- failure
173 dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp);
175 * Destroys the dispatchmgr when it becomes empty. This could be
179 *\li mgrp != NULL && *mgrp is a valid dispatchmgr.
184 dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole);
186 * Sets the dispatcher's "blackhole list," a list of addresses that will
187 * be ignored by all dispatchers created by the dispatchmgr.
190 * \li mgrp is a valid dispatchmgr
191 * \li blackhole is a valid acl
196 dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr);
198 * Gets a pointer to the dispatcher's current blackhole list,
199 * without incrementing its reference count.
202 *\li mgr is a valid dispatchmgr
204 *\li A pointer to the current blackhole list, or NULL.
208 dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
209 dns_portlist_t *portlist);
211 * This function is deprecated. Use dns_dispatchmgr_setavailports() instead.
214 *\li mgr is a valid dispatchmgr
218 dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr);
220 * This function is deprecated and always returns NULL.
223 *\li mgr is a valid dispatchmgr
227 dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
228 isc_portset_t *v6portset);
230 * Sets a list of UDP ports that can be used for outgoing UDP messages.
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
239 dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats);
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.
248 *\li mgr is a valid dispatchmgr with no managed dispatch.
249 *\li stats is a valid statistics supporting resolver statistics counters
254 dns_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);
263 dns_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);
271 * Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find,
272 * otherwise create a new UDP dispatch.
275 *\li All pointer parameters be valid for their respective types.
277 *\li dispp != NULL && *disp == NULL
279 *\li 512 <= buffersize <= 64k
283 *\li buckets < 2097169
285 *\li increment > buckets
287 *\li (attributes & DNS_DISPATCHATTR_TCP) == 0
290 *\li ISC_R_SUCCESS -- success.
292 *\li Anything else -- failure.
296 dns_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);
302 * Create a new dns_dispatch and attach it to the provided isc_socket_t.
304 * For all dispatches, "buffersize" is the maximum packet size we will
307 * "maxbuffers" and "maxrequests" control the number of buffers in the
308 * overall system and the number of buffers which can be allocated to
311 * "buckets" is the number of buckets to use, and should be prime.
313 * "increment" is used in a collision avoidance function, and needs to be
314 * a prime > buckets, and not 2.
318 *\li mgr is a valid dispatch manager.
320 *\li sock is a valid.
322 *\li task is a valid task that can be used internally to this dispatcher.
324 * \li 512 <= buffersize <= 64k
328 *\li maxrequests <= maxbuffers.
330 *\li buckets < 2097169 (the next prime after 65536 * 32)
332 *\li increment > buckets (and prime).
334 *\li attributes includes #DNS_DISPATCHATTR_TCP and does not include
335 * #DNS_DISPATCHATTR_UDP.
338 *\li ISC_R_SUCCESS -- success.
340 *\li Anything else -- failure.
344 dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp);
346 * Attach to a dispatch handle.
351 *\li dispp != NULL && *dispp == NULL
355 dns_dispatch_detach(dns_dispatch_t **dispp);
357 * Detaches from the dispatch.
360 *\li dispp != NULL and *dispp be a valid dispatch.
364 dns_dispatch_starttcp(dns_dispatch_t *disp);
366 * Start processing of a TCP dispatch once the socket connects.
369 *\li 'disp' is valid.
373 dns_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);
379 dns_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);
383 * Add a response entry for this dispatch.
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.
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.
393 *\li "idp" be non-NULL.
395 *\li "task" "action" and "arg" be set as appropriate.
397 *\li "dest" be non-NULL and valid.
399 *\li "resp" be non-NULL and *resp be NULL
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.
407 *\li <id, dest> is a unique tuple. That means incoming messages
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.
420 dns_dispatch_removeresponse(dns_dispentry_t **resp,
421 dns_dispatchevent_t **sockevent);
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.
428 *\li "resp" != NULL and "*resp" contain a value previously allocated
429 * by dns_dispatch_addresponse();
431 *\li May only be called from within the task given as the 'task'
432 * argument to dns_dispatch_addresponse() when allocating '*resp'.
436 dns_dispatch_getentrysocket(dns_dispentry_t *resp);
439 dns_dispatch_getsocket(dns_dispatch_t *disp);
441 * Return the socket associated with this dispatcher.
447 *\li The socket the dispatcher is using.
451 dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp);
453 * Return the local address for this dispatch.
454 * This currently only works for dispatches using UDP sockets.
458 *\li addrp to be non null.
462 *\li ISC_R_NOTIMPLEMENTED
466 dns_dispatch_cancel(dns_dispatch_t *disp);
468 * cancel outstanding clients
475 dns_dispatch_getattributes(dns_dispatch_t *disp);
477 * Return the attributes (DNS_DISPATCHATTR_xxx) of this dispatch. Only the
478 * non-changeable attributes are expected to be referenced by the caller.
485 dns_dispatch_changeattributes(dns_dispatch_t *disp,
486 unsigned int attributes, unsigned int mask);
488 * Set the bits described by "mask" to the corresponding values in
494 * new = (old & ~mask) | (attributes & mask)
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.
505 *\li attributes are reasonable for the dispatch. That is, setting the UDP
506 * attribute on a TCP socket isn't reasonable.
510 dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event);
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.
517 *\li disp is valid, and the attribute DNS_DISPATCHATTR_NOLISTEN is set.
522 dns_dispatchset_get(dns_dispatchset_t *dset);
524 * Retrieve the next dispatch from dispatch set 'dset', and increment
525 * the round-robin counter.
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);
536 * Given a valid dispatch 'source', create a dispatch set containing
537 * 'n' UDP dispatches, with the remainder filled out by clones of the
541 *\li source is a valid UDP dispatcher
542 *\li dsetp != NULL, *dsetp == NULL
546 dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task);
548 * Cancel socket operations for the dispatches in 'dset'.
552 dns_dispatchset_destroy(dns_dispatchset_t **dsetp);
554 * Dereference all the dispatches in '*dsetp', free the dispatchset
555 * memory, and set *dsetp to NULL.
563 #endif /* DNS_DISPATCH_H */