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	&lt;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